由於BMP格式的圖像簡單,讀寫BMP圖的實現也相對容易,所以在構建自己的圖像處理庫的時候,都是使用BMP作爲測試圖像。首先說一BMP圖像相關的知識。
BMP圖像的組成
BMP圖像由4個部分組成:
- 文件頭:BITMAPFILEHEADER(14字節)
- 信息頭:BITMAPINFOHEADER(40字節)
- 顏色表:RGBQUAD(8位的爲1024字節)(小於24位的圖有,24位沒有)
- 圖像數據
文件頭 BITMAPFILEHEADER
typedef struct tagBITMAPFILEHEADER
{
WORD bfType; //位圖文件的類型,該值必需是0x4D42,也就是字符'BM'。
DWORD bfSize; //位圖文件大小:文件頭+信息頭+顏色表+數據部分
WORD bfReserved1; //保留字,爲0,留做擴展,對實際的解碼格式沒有影響。
WORD bfReserved2; //同上
DWORD bfOffBits; //位圖文件頭到圖像數據的偏移量,以字節爲單位
} BITMAPFILEHEADER;
這個結構的長度是固定的,爲14個字節(WORD爲無符號16位整數,DWORD爲無符號32位整數)。該結果體作爲文件存儲的時候用。
結構體的定義參考Windows.h
信息頭BITMAPINFOHEADER
這部分告訴應用程序圖像的詳細信息,在屏幕上顯示圖像將會使用這些信息,它從文件的第15個字節開始。
typedef struct tagBITMAPINFOHEADER
{
DWORD biSize; //BITMAPINFOHEADER結構大小,字節爲單位
LONG biWidth; //寬度(以像素爲單位,不是每行字節數!!)
LONG biHeight; //高度(以像素爲單位)
WORD biPlanes; //目標設備的級別,必須爲1
WORD biBitCount; //顏色深度,每個像素所需要的位數
DWORD biCompression; //位圖的壓縮類型
DWORD biSizeImage; //位圖數據部分的大小,以字節爲單位(4字節對齊)
LONG biXPelsPerMeter; //位圖水平分辨率,每米像素數
LONG biYPelsPerMeter; //位圖垂直分辨率,每米像素數
DWORD biClrUsed; //位圖實際使用的顏色表中的顏色數
DWORD biClrImportant; //位圖顯示過程中重要的顏色數
} BITMAPINFOHEADER;
該結構體大小爲40字節。
顏色表RGBQUAD
BMP只能存儲單色(1位),16色(4位),256色(8位),和真彩色(24位)4種格式的數據,只有真彩色沒有調色板(顏色表)。
8位的BMP中,每個像素的數值就是顏色表數組的下標。而24位的BMP圖,每個像素的數值就是表示實際的像素值。
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
圖像數據
在8位BMP中,每個像素8位,存放的是顏色表的索引,24位每個像素24位,存放的是實際顏色的值,分爲三個通道BGR。
要注意兩點:
(1) 每一行的字節數必須是4的整倍數,如果不是,則需要補齊。也就是4字節對齊。
(2) bmp文件的數據從下到上,從左到右的。也就是說,從文件中最先讀到的是圖象最下面一行的左邊第一個像素,然後是左邊第二個像素……接下來是倒數第二行左邊第一個像素,左邊第二個像素……依次類推 ,最後得到的是最上面一行的最右一個像素。
具體實現
Github:https://github.com/qianqing13579/QQImageProcess
其中的Bmp.h和Bmp.cpp包含了讀寫BMP圖像的具體實現
可以先執行ImageProcessTest類中的TestReadAndWrite()測試用例,看一下使用方法
2017-1-10 18:35:33
非常感謝您的閱讀,如果您覺得這篇文章對您有幫助,歡迎掃碼進行讚賞。