課程名稱:線性代數 CS233 B
授課教師:簡廷因
發放時間:2020-10-05
截止時間:2020-10-26 23:59:59


Get a filename F1 from parameter, and using STDOUT for output

Sample input : case1.bmp
Sample output : This is the testing sentence and will convert into a QR-code like photo.
Sample command : ./tinin.exe case1.bmp


題目說明

給一個 bmp 檔案,由下而上,由左至右,每 8 個像素點代表一組二進位數字 ( 白為 0、黑為 1 ),表示為 Ascii Code,求解碼後的字串。

解題思路

bmp 檔案其實就是以二進制檔案來表示圖片的儲存格式,以本次作業的測資來說,前 54 個 byte 為 bmp 的 header,紀錄一些圖片的基本訊息,如:長度、寬度 … 等等。接著就是像素點的訊息,3 個 byte 一組,分別代表一個像素點的 B、G、R,並且由圖片的下而上,左至右。由於題目只需要後面關於像素點的資料,所以使用 seekg() 跳過前面的 54 個 byte,之後使用 while()get() 讀檔,同時做二進位的轉換,直到檔案的最後即可。需要注意的是當讀了 8 個像素點後,字元若為無法顯示的字元,代表句子已經結尾了,同時表示這張圖片已經處理完了。

參考解法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <fstream>

using namespace std;

// fast IO
static auto __ = []()
{
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();

int main(int argc, char* argv[])
{
if (argc < 2) return 0; // no file path

ifstream file(argv[1], ios::binary);
file.seekg(54, ios::beg); // avoid header

// read file and print
int cnt = 0;
char ch, tmp = 0;
while (file.get(ch).get(ch).get(ch)) // B, G, R
{
++cnt;
tmp = (tmp << 1) + ch + 1; // ch == -1 -> white = 0, ch == 0 -> black = 1
if (cnt == 8)
{
if (tmp < 32 || tmp > 126) break;
cout << tmp;
cnt = tmp = 0;
}
}
}