典型的BMP影像檔由四部分組成:
1:位元影像檔案頭資料結構,它包含BMP影像檔的類型、顯示內容等資訊;
2:位元影像資訊資料結構,它包含有BMP映像的寬、高、壓縮方法,以及定義顏色等資訊;
3:調色盤,這個部分是可選的,有些位元影像需要調色盤,有些位元影像,比如真彩色圖(24位的BMP)就不需要調色盤;
4:位元影像資料,這部分的內容根據BMP位元影像使用的位元不同而不同,在24位元影像中直接使用RGB,而其他的小於24位的使用調色盤中色彩索引值。
1:BMP檔案組成
BMP檔案由檔案頭、位元影像資訊頭、顏色資訊和圖形資料四部分組成。
2:BMP檔案頭(14位元組)
BMP檔案頭資料結構含有BMP檔案的類型、檔案大小和位元影像起始位置等資訊。
其結構定義如下:
typedef struct tagBITMAPFILEHEADER
{
WORDbf Type; // 位元影像檔案的類型,必須為BMP(0-1位元組)
DWORD bfSize; // 位元影像檔案的大小,以位元組為單位(2-5位元組)
WORD bfReserved1; // 位元影像檔案保留字,必須為0(6-7位元組)
WORD bfReserved2; // 位元影像檔案保留字,必須為0(8-9位元組)
DWORD bfOffBits; // 位元影像資料的起始位置,以相對於位元影像(10-13位元組)
// 檔案頭的位移量表示,以位元組為單位
} BITMAPFILEHEADER;
3:位元影像資訊頭(40位元組)
BMP位元影像資訊頭資料用於說明位元影像的尺寸等資訊。
typedef struct tagBITMAPINFOHEADER{
DWORD biSize; // 本結構所佔用位元組數(14-17位元組)
LONG biWidth; // 位元影像的寬度,以像素為單位(18-21位元組)
LONG biHeight; // 位元影像的高度,以像素為單位(22-25位元組)
WORD biPlanes; // 目標裝置的層級,必須為1(26-27位元組)
WORD biBitCount;// 每個像素所需的位元,必須是1(雙色),(28-29位元組)
// 4(16色),8(256色)或24(真彩色)之一
DWORD biCompression; // 位元影像壓縮類型,必須是 0(不壓縮),(30-33位元組)
// 1(BI_RLE8壓縮類型)或2(BI_RLE4壓縮類型)之一
DWORD biSizeImage; // 位元影像的大小,以位元組為單位(34-37位元組)
LONG biXPelsPerMeter; // 位元影像水平解析度,每米像素數(38-41位元組)
LONG biYPelsPerMeter; // 位元影像垂直解析度,每米像素數(42-45位元組)
DWORD biClrUsed;// 位元影像實際使用的顏色表中的顏色數(46-49位元組)
DWORD biClrImportant;// 位元影像顯示過程中重要的顏色數(50-53位元組)
} BITMAPINFOHEADER;
4:顏色表
顏色表用於說明位元影像中的顏色,它有若干個表項,每一個表項是一個RGBQUAD類型的結構,定義一種顏色。RGBQUAD結構的定義如下:
typedef struct tagRGBQUAD {
BYTE rgbBlue;// 藍色的亮度(值範圍為0-255)
BYTE rgbGreen; // 綠色的亮度(值範圍為0-255)
BYTE rgbRed; // 紅色的亮度(值範圍為0-255)
BYTE rgbReserved;// 保留,必須為0
} RGBQUAD;
顏色表中RGBQUAD結構資料的個數有biBitCount來確定:
當biBitCount=1,4,8時,分別有2,16,256個表項;
當biBitCount=24時,沒有顏色表項。
位元影像資訊頭和顏色表組成位元影像資訊,BITMAPINFO結構定義如下:
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader; // 位元影像資訊頭
RGBQUAD bmiColors[1]; // 顏色表
} BITMAPINFO;
5:位元影像資料
位元影像資料記錄了位元影像的每一個像素值,記錄順序是在掃描行內是從左至右,掃描行之間是從下到上。位元影像的一個像素值所佔的位元組數:
當biBitCount=1時,8個像素佔1個位元組;
當biBitCount=4時,2個像素佔1個位元組;
當biBitCount=8時,1個像素佔1個位元組;
當biBitCount=24時,1個像素佔3個位元組;
Windows規定一個掃描行所佔的位元組數必須是
4的倍數(即以long為單位),不足的以0填充,
biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) * bi.biHeight;
如果使用直讀檔案的方法去顯示BMP檔案,這裡要非常注意!在我寫的一個人機介面的配套圖片轉換工具時發現有這麼一個BUG:當讀取的BMP映像素為某些值時就可以正確顯示,而另一些值時則顯示不正常,經過仔細尋找,才發現原來是只有X座標為4的整數倍的圖片才可以正常顯示,就是上面這個原因導致顯示不正確。
具體資料舉例:
如某BMP檔案開頭:
4D42 4690 0000 0000 0000 4600 0000 2800 0000 8000 0000 9000 0000 0100*1000 0300 0000 0090 0000 A00F 0000 A00F 0000 0000 0000 0000 0000*00F8 0000 E007 0000 1F00 0000 0000 0000*02F1 84F1 04F1 84F1 84F1 06F2 84F1 06F2 04F2 86F2 06F2 86F2 86F2 .... ....
BMP檔案可分為四個部分:位元影像檔案頭、位元影像資訊頭、彩色板、映像資料陣列,在中已用*分隔。
一、影像檔頭
1)1:(這裡的數字代表的是"字",即兩個位元組,下同)影像檔頭。0x4D42=’BM’,表示是Windows支援的BMP格式。
2)2-3:整個檔案大小。4690 0000,為00009046h=36934。
3)4-5:保留,必須設定為0。
4)6-7:從檔案開始到位元影像資料之間的位移量。4600 0000,為00000046h=70,上面的檔案頭就是35字=70位元組。
二、位元影像資訊頭
5)8-9:位元影像圖資訊頭長度。
6)10-11:位元影像寬度,以像素為單位。8000 0000,為00000080h=128。
7)12-13:位元影像高度,以像素為單位。9000 0000,為00000090h=144。
8)14:位元影像的位面數,該值總是1。0100,為0001h=1。
9)15:每個像素的位元。有1(單色),4(16色),8(256色),16(64K色,高彩色),24(16M色,真彩色),32(4096M色,增強型真彩色)。1000為0010h=16。
10)16-17:壓縮說明:有0(不壓縮),1(RLE 8,8位RLE壓縮),2(RLE 4,4位RLE壓縮,3(Bitfields,位域存放)。RLE簡單地說是採用像素數+像素值的方式進行壓縮。T408採用的是位域存放方式,用兩個位元組表示一個像素,位域分配為r5b6g5。圖中0300 0000為00000003h=3。
11)18-19:用位元組數表示的位元影像資料的大小,該數必須是4的倍數,數值上等於(≥位元影像寬度的最小的4的倍數)×位元影像高度×每個像素位元。0090 0000為00009000h=80×90×2h=36864。
12)20-21:用象素/米表示的水平解析度。A00F 0000為0000 0FA0h=4000。
13)22-23:用象素/米表示的垂直解析度。A00F 0000為0000 0FA0h=4000。
14)24-25:位元影像使用的色彩索引數。設為0的話,則說明使用所有調色盤項。
15)26-27:對圖象顯示有重要影響的色彩索引的數目。如果是0,表示都重要。
三、彩色板
16)28-....(不確定):彩色板規範。對於調色盤中的每個表項,用下述方法來描述RGB的值:
1位元組用於藍色分量
1位元組用於綠色分量
1位元組用於紅色分量
1位元組用於填充符(設定為0)
對於24-位真彩色映像就不使用彩色板,因為位元影像中的RGB值就代表了每個象素的顏色。
如,彩色板為00F8 0000 E007 0000 1F00 0000 0000 0000,其中:
00FB 0000為FB00h=1111100000000000(二進位),是藍色分量的掩碼。
E007 0000為 07E0h=0000011111100000(二進位),是綠色分量的掩碼。
1F00 0000為001Fh=0000000000011111(二進位),是紅色分量的掩碼。
0000 0000總設定為0。
將掩碼跟像素值進行“與”運算再進行移位操作就可以得到各色分量值。看看掩碼,就可以明白事實上在每個像素值的兩個位元組16位中,按從高到低取5、6、5位分別就是r、g、b分量值。取出分量值後把r、g、b值分別乘以8、4、8就可以補齊第個分量為一個位元組,再把這三個位元組按rgb組合,放入儲存空間(同樣要反序),就可以轉換為24位標準BMP格式了。
四、映像資料陣列
17)27(無調色盤)-...:每兩個位元組表示一個像素。陣列中的第一個位元組表示位元影像左下角的象素,而最後一個位元組表示位元影像右上方的象素。
五、儲存演算法
BMP檔案通常是不壓縮的,所以它們通常比同一幅映像的壓縮影像檔格式要大很多。例如,一個800×600的24位幾乎佔據1.4MB空間。因此它們通常不適合在網際網路或者其它低速或者有容量限制的媒介上進行傳輸。 根據色彩深度的不同,映像上的一個像素可以用一個或者多個位元組表示,它由n/8所確定(n是位元深度,1位元組包含8個資料位元)。圖片瀏覽器等基於位元組的ASCII值計算像素的顏色,然後從調色盤中讀出相應的值。更為詳細的資訊請參閱下面關於位元影像檔案的部分。 n位2n種顏色的位元影像近似位元組數可以用下面的公式計算: BMP檔案大小約等於 54+4*2的n次方+(w*h*n)/8
,其中高度和寬度都是像素數。 需要注意的是上面公式中的54是位元影像檔案的檔案頭,是彩色調色盤的大小。另外需要注意的是這是一個近似值,對於n位的位元影像映像來說,儘管可能有最多2n中顏色,一個特定的映像可能並不會使用這些所有的顏色。由於彩色調色盤僅僅定義了映像所用的顏色,所以實際的彩色調色盤將小於。 如果想知道這些值是如何得到的,請參考下面檔案格式的部分。 由於儲存演算法本身決定的因素,根據幾個映像參數的不同計算出的大小與實際的檔案大小將會有一些細小的差別。