本文轉載自【微信公眾號:strongerHuang,ID:strongerHuang】經微信公眾號授權轉載,如需轉載與原文作者聯繫
BMP文件的結構其實非常簡單,就是兩個結構體+一個可選的調色板+位圖數據。
第一個結構體是BITMAPFILEHEADER,第二個結構體是BITMAPINFOHEADER。然後就是可選的調色板(RGBQUAD數組)。最後是位圖數據。
1
第一個結構體
這裡先講講第一個結構體位圖文件頭結構:BITMAPFILEHEADER 的詳細結構。
先看看代碼原型:
typedef struct tagBITMAPFILEHEADER
{
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
其中:
bfType:文件的標識,值必須是0x4D42(也就是「BM」兩個字符,注意是Little-Endian)
bfSize:是整個文件的大小
bfReserved1和bfReserved2必須是0.
bfOffBits:是位圖數據在文件中的偏移。
2
第二個結構體
位圖信息頭:BITMAPINFOHEADER。
typedef struct tagBITMAPINFOHEADER
{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
biSize:
BITMAPINFOHEADER這個結構體的大小。必須為40(字節)。
biWidth:
BMP位圖的寬度。
biHeight:
BMP位圖的寬度。
這裡需要說明一下的是,BMP位圖數據有兩種存儲方式,通常是「底到上型」,也就是BMP位圖數據的第一行其實是這個圖片的最後一行。一種是「頂到下型」,BMP位圖數據的第一行就是圖片的第一行。
如果位圖是「頂到下型」,那麼biHeight的值是負的,位圖的實際高度其實是(-biHeight),也就是它的相反數。
只有「底到上型」位圖支持壓縮。「底到上型」是目前最常見的位圖類型。
PhotoShop在保存位圖文件的時候,你可以設置讓它輸出「底到上型」或「頂到下型」。「頂到下型」就是「逆行序」。
biPlanes:
位圖的「位面數」。這個值必須為1.
biBitCount:
位圖的「顏色位數」。表示位圖數據中,幾個二進位位表示一個像素。
顏色位數為1表示單色(其實是「雙色」,通常是黑白,也可以是別的兩個顏色。)
為2表示四色,也就是四種顏色。為4表示16種顏色。為8表示有256種顏色。
在表示256色以內的顏色數量的時候,這個BMP文件其實是作為使用調色板顏色的圖像,因此在BITMAPINFOHEADER結構體的後面還有個調色板。
所謂調色板其實就是RGBQUAD結構體的數組。它的元素個數就是顏色數。
biCompression:
位圖的壓縮格式,值可以是BI_RGB(未壓縮),BI_RLE8(8位RLE壓縮),BI_RLE4(4位RLE壓縮),BI_BITFIELDS(表示顏色表中,每個像素有3個DWORD的屏蔽位數據來指示紅綠藍成分。16位和32位位圖可以使用這個。),BI_JPEG(位圖數據其實是JPG格式的),BI_PNG(位圖數據其實是PNG格式的)
當biCompression值為BI_RLE8的時候,biBitCount必須為8,表示這是個8位的256色索引顏色位圖(有256個調色板),位圖數據按照如下算法壓縮:
·位圖數據是每兩個字節組成一個元素,這樣的元素組成了一個數組。
·每個元素,第一個字節表示重複的像素的數量,第二個字節是8位的調色板顏色索引。
·如果元素的第一個字節為0,那麼第二個字節有特殊的含義:
0:這行已經結束了。
1:這個位圖已經結束了。
2:設置下一個像素的位置,後面的兩個無符號字節分別指定了下一個像素的X、Y偏移。注意是無符號字節,意思是說,偏移只能是往後。
3到0xFF:表示後面有一段沒有壓縮的數據的長度,也就是連續的8位像素顏色索引數據的長度。但是數據必須是2位元組對齊的。biCompression值為BI_RLE4的時候,biBitCount必須為4,表示這是個4位的16色索引顏色位圖(有16個調色板)。
和BI_RLE8的區別只是每個元素的第二個字節如果表示顏色索引,它表示的是兩個像素的顏色索引。第一個字節表示重複的數量,第二個字節表示兩個像素的顏色。
舉個例,假設調色板第0號色是黑色,第1號色是白色,元素的值是0x05,0x01,那麼它表示「黑白黑白黑白黑白黑白」共10個像素出現在1行。
biSizeImage:
位圖數據塊的大小。以字節為單位。如果你的位圖沒有經過壓縮,這個值可以是0.
biXPelsPerMeter:
表示橫向的每米的像素數。可以為0.
biYPelsPerMeter:
表示縱向的每米的像素數。可以為0.
biClrUsed:
位圖實際使用過的調色板的顏色數。如果這個值為0,表示這個位圖使用了整個調色板。只有8位以及8位以下的索引顏色位圖才需要考慮這個值。對於16位以及16位以上的位圖,無視這個值。biClrImportant表示重要的顏色數。如果為0,表示顏色都重要。通常它的值等於biClrUsed,或者等於0.
如果位圖是8位以及8位以下的位圖,後面是位圖的調色板數據。否則沒有調色板數據。
調色板就是簡單的RGBQUAD數組。
後面就是位圖數據了。如果位圖是沒有經過壓縮的,那麼位圖數據的存儲就是一行一行的,每行都是每XX個字節一個像素,取決於位圖的位數(biBitCount),每一行都是4位元組對齊的!多出來的部分用0補齊。這裡必須注意。
因此,每行佔用的字節數要按照以下公式計算:(其中的biBitCount指的是位圖的位數,也就是BITMAPINFOHEADER的成員)
每行字節數 = ((圖像寬度 - 1) * biBitCount / 32 + 1) * 4;
如果你是用VB編寫讀取位圖的話,是這樣寫的:
每行字節數 = ((圖像寬度 - 1) * biBitCount \ 32 + 1) * 4
這裡還要注意的是「底到上型」位圖和「頂到下型」位圖,如果BITMAPINFOHEADER的biHeight成員大於零,那麼這個位圖就是「底到上型」,否則就是「頂到下型」。「底到上型」的位圖,它的行序是從下到上排列的,也就是逆行序。「頂到下型」位圖行序是從上到下排列的。
3
位圖顏色表
位圖顏色表就比較簡單了:
typedef struct tagRGBQUAD
{
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
紅祿藍三種顏色,然後還有保留一個字節。
最後,還有位圖數據,這裡就不描述了。
免責聲明:本文部分素材來源網絡,版權歸原作者所有。如涉及作品版權問題,請與我聯繫刪除