標籤:
BMP圖片,是Bitmap(位元影像)的簡稱,它是windows顯示圖片的基本格式。在windows下,任何格式的圖片檔案(包括視頻播放)都要轉化為位元影像才能顯示出來。各種格式的圖片檔案也都是在位元影像格式的基礎上採用不同的壓縮演算法產生的。
位元影像檔案主要分為如下3個部分:
塊名稱 |
對應Window結構定義 |
大小(yte) |
位元影像檔案頭 |
BITMAPFILEHEADER |
14 |
位元影像資訊頭 |
BITMAPINFOHEADER |
40 |
RGB顏色陣列 |
BYTE* |
由映像長寬尺寸決定 |
(1)位元影像檔案頭BITMAPFILEHEADER
結構體定義如下:
typedef struct tagBITMAPFILEHEADER
{
UINT bfType;
DWORD bfSize;
UINT bfReserved1;
UINT bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
其中:
bfType |
說明檔案的類型,該值必需是0x4D42(十六進位ASCII碼4D代表“B”,42代表“M”),也就是字元‘BM‘。 |
bfSize |
說明該位元影像檔案的大小,用位元組為單位 |
bfReserved1 |
保留,必須設定為0 |
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;
其中:
biSize |
說明BITMAPINFOHEADER結構所需要的字數,不是位元組數。 |
biWidth |
說明圖象的寬度,以象素個數為單位。 |
biHeight |
說明圖象的高度,以象素個數為單位。註:這個值除了用於描述映像的高度之外,它還有另一個用處,就是指明該映像是倒向的位元影像,還是正向的位元影像。如果該值是一個正數,說明映像是倒向的,如果該值是一個負數,則說明映像是正向的。大多數的BMP檔案都是倒向的位元影像,也就是說,高度值是一個正數。 |
biPlanes |
為目標裝置說明位面數,其值將總是被設為1。 |
biBitCount |
說明位元數/象素,其值為1、4、8、16、24、或32。我們平時用到的映像絕大部分是24位和32位的 |
biCompression |
說明圖象資料壓縮的類型,同樣我們只討論沒有壓縮的類型:BI_RGB。 |
biSizeImage |
說明圖象的大小,以位元組為單位。當用BI_RGB格式時,可設定為0。 |
biXPelsPerMeter |
說明水平解析度,用象素/米表示。 |
biYPelsPerMeter |
說明垂直解析度,用象素/米表示。 |
biClrUsed |
說明位元影像實際使用的彩色表中的色彩索引數(設為0的話,則說明使用所有調色盤項)。 |
biClrImportant |
說明對圖象顯示有重要影響的色彩索引的數目,如果是0,表示都重要。 |
(3) RGB色彩通道
在windows下面,RGB顏色矩陣的儲存格式是BGR。也就是說,對於24 位RGB位元影像來說,資料格式為:…。對於32位的RGB位元影像來說,資料格式為:…。這裡,Alpha通道也稱為透明通道,該值是該像素點的透明屬性,取值在0(全透明)------255(不透明)之間。對於24位的映像來說,因為沒有Alpha通道,故整個映像都不透明。顏色資料區記錄著每個像素對應的顏色值。其記錄方式隨著顏色模式的不同而不同。
biBitCount=1
表示位元影像最多有兩種顏色,預設情況下是黑色和白色,你也可以自己定義這兩種顏色。映像資訊頭調色盤中將有兩個調色盤項,稱為索引0和索引1。圖象資料陣列中的每一位表示一個象素。如果一個位是0,顯示時就使用索引0的RGB值,如果位是1,則使用索引1的RGB值。
biBitCount=4
表示位元影像最多有16種顏色。每個象素用4位表示,並用這4位作為彩色表的表項來尋找該象素的顏色。例如,如果位元影像中的第一個位元組為0x1F,它表示有兩個象素,第一象素的顏色就在彩色表的第2表項中尋找,而第二個象素的顏色就在彩色表的第16表項中尋找。此時,調色盤中預設情況下會有16個RGB項。對應於索引0到索引15。
biBitCount=8
表示位元影像最多有256種顏色。每個象素用8位表示,並用這8位作為彩色表的表項來尋找該象素的顏色。例如,如果位元影像中的第一個位元組為0x1F,這個象素的顏色就在彩色表的第32表項中尋找。此時,預設情況下,調色盤中會有256個RGB項,對應於索引0到索引255。
biBitCount=16
表示位元影像最多有65536種顏色。每個色素用16位(2個位元組)表示。這種格式叫作高彩色,或叫增強型16位色,或64K色。它的情況比較複雜,當 biCompression成員的值是BI_RGB時,它沒有調色盤。16位中,最低的5位表示藍色分量,中間的5位表示綠色分量,高的5位表示紅色分量,一共佔用了15位,最高的一位保留,設為0。這種格式也被稱作555 16位位元影像。
如果biCompression成員的值是BI_BITFIELDS,那麼情況就複雜了,首先是原來調色盤的位置被三個DWORD變數佔據,稱為紅、綠、藍掩碼。分別用於描述紅、綠、藍分量在16位中所佔的位置。在Windows95(或98)中,系統可接受兩種格式的位域:555和565,在555格式下,紅、綠、藍的掩碼分別是:0x7C00、0x03E0、0x001F,而在565格式下,它們則分別為:0xF800、0x07E0、0x001F。你在讀取一個像素之後,可以分別用掩碼“與”上像素值,從而提取出想要的顏色分量(當然還要再經過適當的左右移操作)。在NT系統中,則沒有格式限制,只不過要求掩碼之間不能有重疊。(註:這種格式的映像使用起來是比較麻煩的,不過因為它的顯示效果接近於真彩,而映像資料又比真彩映像小的多,所以,它更多的被用於遊戲軟體)。
biBitCount=24
表示位元影像最多有2的24次方,大約1670萬種顏色。這種位元影像沒有調色盤(bmiColors成員尺寸為0),在位元組中,每3個位元組代表一個象素,分別對應於顏色R、G、B。
biBitCount=32
表示位元影像最多有2的32次方種顏色。這種位元影像的結構與16位位元影像結構非常類似,當biCompression成員的值是BI_RGB時,它也沒有調色盤,32位中有24位用於存放RGB值,順序是:最高位—保留,紅8位、綠8位、藍8位。這種格式也被成為888 32位位元影像。
如果biCompression成員的值是BI_BITFIELDS時,原來調色盤的位置將被三個DWORD變數佔據,成為紅、綠、藍掩碼,分別用於描述紅、綠、藍分量在32位中所佔的位置。在Windows95(or 98)中,系統只接受888格式,也就是說三個掩碼的值將只能是:0xFF0000、0xFF00、0xFF。而在NT系統中,你只要注意使掩碼之間不產生重疊就行。(註:這種映像格式比較規整,因為它是DWORD對齊的,所以在記憶體中進行影像處理時可進行彙編級的代碼最佳化(簡單))。
BMP映像資料區在儲存時,2色映像每點佔1位(8位為1位元組);16色映像每點佔4位(半位元組);256色映像每點佔8位(1位元組);真彩色映像每點佔24位(3位元組)。所以,整個資料區的大小也會隨之變化。究其規律而言,可的出如下計算公式:映像資料資訊大小=(映像寬度*映像高度*記錄影素的位元)/8。
然而,未壓縮的映像資訊區的大小。除了真彩色模式外,其餘的均大於或等於資料資訊的大小。這是為什麼呢?原因有兩個:
1.BMP檔案記錄一行映像是以位元組為單位的。因此,就不存在一個位元組中的資料位元資訊表示的點在不同的兩行中。也就是說,設顯示模式為16色,在每個位元組分配兩個點資訊時,如果映像的寬度位奇數,那麼最後一個像素點的資訊將獨佔一個位元組,這個位元組的後4位將沒有意義。接下來的一個位元組將開始記錄下一行的資訊。
2.為了顯示的方便,除了真彩色外,其他的每種顏色模式的行位元組數要用資料“00”補齊為4的整數倍,4位元組對齊。如果顯示模式為16色,當映像寬為19時,儲存時每行則要補充4-(19/2+1)%4=2個位元組(加1是因為裡面有一個像素點要獨佔了一位元組)。如果顯示模式為256色,當映像寬為19時,每行也要補充4-19%4=1個位元組。
BMP映像資料區在讀取時,位元影像資料的位移量為sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)。
由於Windows在進行行掃描的時候最小的單位為4個位元組,所以當圖片寬 X 每個像素的位元組數 != 4的整數倍時要在每行的後面補上缺少的位元組,以0填充(一般來說當映像寬度為2的冪時不需要對齊)。位元影像檔案裡的資料在寫入的時候已經進行了行對齊,也就是說載入的時候不需要再做行對齊。但是這樣一來圖片資料的長度就不是:寬 X 高 X 每個像素的位元組數了,我們需要通過下面的方法計算正確的資料長度
//Calculate the image data size
//widthstep,每行所佔的實際位元組數
int iLineByteCnt = (((m_iImageWidth*m_iBitsPerPixel) + 31) >> 5) << 2;
m_iImageDataSize = iLineByteCnt * m_iImageHeight;
windows中BMP位元影像格式介紹