BMP映像格式簡介嘟嘟 發表於 2006-1-17 22:05:00
簡介
BMP(Bitmap-File)圖形檔案是Windows採用的圖形檔案格式,在Windows環境下啟動並執行所有圖象處理軟體都支援BMP圖象檔案格式。Windows系統內部各映像繪製操作都是以BMP為基礎的。Windows 3.0以前的BMP圖檔案格式與顯示裝置有關,因此把這種BMP圖象檔案格式稱為裝置相關位元影像DDB(device-dependent bitmap)檔案格式。Windows 3.0以後的BMP圖象檔案與顯示裝置無關,因此把這種BMP圖象檔案格式稱為裝置無關位元影像DIB(device-independent bitmap)格式(註:Windows 3.0以後,在系統中仍然存在DDB位元影像,象BitBlt()這種函數就是基於DDB位元影像的,只不過如果你想將映像以BMP格式儲存到磁碟檔案中時,微軟極力推薦你以DIB格式儲存),目的是為了讓Windows能夠在任何類型的顯示裝置上顯示所儲存的圖象。BMP位元影像檔案預設的副檔名是BMP或者bmp(有時它也會以.DIB或.RLE作副檔名)。
6.1.2 檔案結構
位元影像檔案可看成由4個部分組成:位元影像檔案頭(bitmap-file header)、位元影像資訊頭(bitmap-information header)、彩色表(color table)和定義位元影像的位元組陣列,它具有如下所示的形式。
位元影像檔案的組成 |
結構名稱 |
符號 |
| 位元影像檔案頭(bitmap-file header) |
BITMAPFILEHEADER |
bmfh |
| 位元影像資訊頭(bitmap-information header) |
BITMAPINFOHEADER |
bmih |
| 彩色表(color table) |
RGBQUAD |
aColors[] |
| 圖象資料陣列位元組 |
BYTE |
aBitmapBits[] |
位元影像檔案結構可綜合在表6-01中。
表01 位元影像檔案結構內容摘要
| |
位移量 |
域的名稱 |
大小 |
內容 |
| 圖象檔案 頭 |
0000h |
檔案標識 |
2 bytes |
兩位元組的內容用來識別位元影像的類型: ‘BM’ : Windows 3.1x, 95, NT, … ‘BA’ :OS/2 Bitmap Array ‘CI’ :OS/2 Color Icon ‘CP’ :OS/2 Color Pointer ‘IC’ : OS/2 Icon ‘PT’ :OS/2 Pointer 註:因為OS/2系統並沒有被普及開,所以在編程時,你只需判斷第一個標識“BM”就行。 |
| |
0002h |
File Size |
1 dword |
用位元組表示的整個檔案的大小 |
| |
0006h |
Reserved |
1 dword |
保留,必須設定為0 |
| |
000Ah |
Bitmap Data Offset |
1 dword |
從檔案開始到位元影像資料開始之間的資料(bitmap data)之間的位移量 |
| |
000Eh |
Bitmap Header Size |
1 dword |
位元影像資訊頭(Bitmap Info Header)的長度,用來描述位元影像的顏色、壓縮方法等。下面的長度表示: 28h - Windows 3.1x, 95, NT, … 0Ch - OS/2 1.x F0h - OS/2 2.x 註:在Windows95、98、2000等作業系統中,位元影像資訊頭的長度並不一定是28h,因為微軟已經制定出了新的BMP檔案格式,其中的資訊頭結構變化比較大,長度加長。所以最好不要直接使用常數28h,而是應該從具體的檔案中讀取這個值。這樣才能確保程式的相容性。 |
| |
0012h |
Width |
1 dword |
位元影像的寬度,以象素為單位 |
| |
0016h |
Height |
1 dword |
位元影像的高度,以象素為單位 |
| |
001Ah |
Planes |
1 word |
位元影像的位面數(註:該值將總是1) |
| 圖象 資訊 頭 |
001Ch |
Bits Per Pixel |
1 word |
每個象素的位元 1 - 單色位元影像(實際上可有兩種顏色,預設情況下是黑色和白色。你可以自己定義這兩種顏色) 4 - 16 色位元影像 8 - 256 色位元影像 16 - 16bit 高彩色位元影像 24 - 24bit 真彩色位元影像 32 - 32bit 增強型真彩色位元影像 |
| |
001Eh |
Compression |
1 dword |
壓縮說明: 0 - 不壓縮 (使用BI_RGB表示) 1 - RLE 8-使用8位RLE壓縮方式(用BI_RLE8表示) 2 - RLE 4-使用4位RLE壓縮方式(用BI_RLE4表示) 3 - Bitfields-位域存放方式(用BI_BITFIELDS表示) |
| |
0022h |
Bitmap Data Size |
1 dword |
用位元組數表示的位元影像資料的大小。該數必須是4的倍數 |
| |
0026h |
HResolution |
1 dword |
用象素/米表示的水平解析度 |
| |
002Ah |
VResolution |
1 dword |
用象素/米表示的垂直解析度 |
| |
002Eh |
Colors |
1 dword |
位元影像使用的顏色數。如8-位元/象素表示為100h或者 256. |
| |
0032h |
Important Colors |
1 dword |
指定重要的顏色數。當該域的值等於顏色數時(或者等於0時),表示所有顏色都一樣重要 |
| 調色盤資料 |
根據BMP版本的不同而不同 |
Palette |
N * 4 byte |
調色盤規範。對於調色盤中的每個表項,這4個位元組用下述方法來描述RGB的值:
|
1位元組用於藍色分量 |
|
1位元組用於綠色分量 |
|
1位元組用於紅色分量 |
|
1位元組用於填充符(設定為0) |
|
| 圖象資料 |
根據BMP版本及調色盤尺寸的不同而不同 |
Bitmap Data |
xxx bytes |
該域的大小取決於壓縮方法及映像的尺寸和映像的位元深度,它包含所有的位元影像資料位元組,這些資料可能是彩色調色盤的索引號,也可能是實際的RGB值,這將根據映像資訊頭中的位元深度值來決定。 |
構件詳解
1. 位元影像檔案頭
位元影像檔案頭包含有關於檔案類型、檔案大小、存放位置等資訊,在Windows 3.0以上版本的位元影像檔案中用BITMAPFILEHEADER結構來定義:
typedef struct tagBITMAPFILEHEADER { /* bmfh */
UINT bfType;
DWORD bfSize;
UINT bfReserved1;
UINT bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
其中:
bfType
|
說明檔案的類型.(該值必需是0x4D42,也就是字元'BM'。我們不需要判斷OS/2的位元影像標識,這麼做現在來看似乎已經沒有什麼意義了,而且如果要支援OS/2的位元影像,程式將變得很繁瑣。所以,在此只建議你檢察'BM'標識)
|
bfSize
|
說明檔案的大小,用位元組為單位
|
bfReserved1
|
保留,必須設定為0
|
bfReserved2
|
保留,必須設定為0
|
bfOffBits
|
說明從檔案頭開始到實際的圖象資料之間的位元組的位移量。這個參數是非常有用的,因為位元影像資訊頭和調色盤的長度會根據不同情況而變化,所以你可以用這個位移值迅速的從檔案中讀取到位元據。
|
2. 位元影像資訊頭
位元影像資訊用BITMAPINFO結構來定義,它由位元影像資訊頭(bitmap-information header)和彩色表(color table)組成,前者用BITMAPINFOHEADER結構定義,後者用RGBQUAD結構定義。BITMAPINFO結構具有如下形式:
typedef struct tagBITMAPINFO { /* bmi */
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO;
其中:
bmiHeader
|
說明BITMAPINFOHEADER結構,其中包含了有關位元影像的尺寸及位格式等資訊
|
bmiColors
|
說明彩色表RGBQUAD結構的陣列,其中包含索引映像的真實RGB值。
|
BITMAPINFOHEADER結構包含有位元影像檔案的大小、壓縮類型和顏色格式,其結構定義為:
typedef struct tagBITMAPINFOHEADER { /* bmih */
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結構所需要的字數。註:這個值並不一定是BITMAPINFOHEADER結構的尺寸,它也可能是 sizeof(BITMAPV4HEADER)的值,或是sizeof(BITMAPV5HEADER)的值。這要根據該位元影像檔案的格式版本來決定,不過,就現在的情況來看,絕大多數的BMP映像都是BITMAPINFOHEADER結構的(可能是後兩者太新的緣故吧:-)。
|
biWidth
|
說明圖象的寬度,以象素為單位
|
biHeight
|
說明圖象的高度,以象素為單位。註:這個值除了用於描述映像的高度之外,它還有另一個用處,就是指明該映像是倒向的位元影像,還是正向的位元影像。如果該值是一個正數,說明映像是倒向的,如果該值是一個負數,則說明映像是正向的。大多數的BMP檔案都是倒向的位元影像,也就是時,高度值是一個正數。(註:當高度值是一個負數時(正向映像),映像將不能被壓縮(也就是說biCompression成員將不能是BI_RLE8或BI_RLE4)。
|
biPlanes
|
為目標裝置說明位面數,其值將總是被設為1
|
biBitCount
|
說明位元數/象素,其值為1、4、8、16、24、或32
|
biCompression
|
說明圖象資料壓縮的類型。其值可以是下述值之一:
|
BI_RGB:沒有壓縮;
|
|
BI_RLE8:每個象素8位元的RLE壓縮編碼,壓縮格式由2位元組組成(重複象素計數和色彩索引);
|
|
BI_RLE4:每個象素4位元的RLE壓縮編碼,壓縮格式由2位元組組成
|
|
BI_BITFIELDS:每個象素的位元由指定的掩碼決定。
|
|
biSizeImage
|
說明圖象的大小,以位元組為單位。當用BI_RGB格式時,可設定為0 |
biXPelsPerMeter
|
說明水平解析度,用象素/米表示 |
biYPelsPerMeter
|
說明垂直解析度,用象素/米表示 |
biClrUsed
|
說明位元影像實際使用的彩色表中的色彩索引數(設為0的話,則說明使用所有調色盤項) |
biClrImportant
|
說明對圖象顯示有重要影響的色彩索引的數目,如果是0,表示都重要。
|
現就BITMAPINFOHEADER結構作如下說明:
(1) 彩色表的定位
應用程式可使用儲存在biSize成員中的資訊來尋找在BITMAPINFO結構中的彩色表,如下所示:
pColor = ((LPSTR) pBitmapInfo + (WORD) (pBitmapInfo->bmiHeader.biSize))
(2) biBitCount
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 表示位元影像最多有216種顏色。每個色素用16位(2個位元組)表示。這種格式叫作高彩色,或叫增強型16位色,或64K色。它的情況比較複雜,當 biCompression成員的值是BI_RGB時,它沒有調色盤。16位中,最低的5位表示藍色分量,中間的5位表示綠色分量,高的5位表示紅色分量,一共佔用了15位,最高的一位保留,設為0。這種格式也被稱作555 16位位元影像。如果biCompression成員的值是BI_BITFIELDS,那麼情況就複雜了,首先是原來調色盤的位置被三個DWORD變數佔據,稱為紅、綠、藍掩碼。分別用於描述紅、綠、藍分量在16位中所佔的位置。在Windows 95(或98)中,系統可接受兩種格式的位域:555和565,在555格式下,紅、綠、藍的掩碼分別是:0x7C00、0x03E0、0x001F,而在565格式下,它們則分別為:0xF800、0x07E0、0x001F。你在讀取一個像素之後,可以分別用掩碼“與”上像素值,從而提取出想要的顏色分量(當然還要再經過適當的左右移操作)。在NT系統中,則沒有格式限制,只不過要求掩碼之間不能有重疊。(註:這種格式的映像使用起來是比較麻煩的,不過因為它的顯示效果接近於真彩,而映像資料又比真彩映像小的多,所以,它更多的被用於遊戲軟體)。
biBitCount=24 表示位元影像最多有224種顏色。這種位元影像沒有調色盤(bmiColors成員尺寸為0),在位元組中,每3個位元組代表一個象素,分別對應於顏色R、G、B。
biBitCount=32 表示位元影像最多有232種顏色。這種位元影像的結構與16位位元影像結構非常類似,當biCompression成員的值是BI_RGB時,它也沒有調色盤,32位中有24位用於存放RGB值,順序是:最高位—保留,紅8位、綠8位、藍8位。這種格式也被成為888 32位元影像。如果 biCompression成員的值是BI_BITFIELDS時,原來調色盤的位置將被三個DWORD變數佔據,成為紅、綠、藍掩碼,分別用於描述紅、綠、藍分量在32位中所佔的位置。在Windows 95(or 98)中,系統只接受888格式,也就是說三個掩碼的值將只能是:0xFF0000、0xFF00、0xFF。而在NT系統中,你只要注意使掩碼之間不產生重疊就行。(註:這種映像格式比較規整,因為它是DWORD對齊的,所以在記憶體中進行影像處理時可進行彙編級的代碼最佳化(簡單))。
(3) ClrUsed
BITMAPINFOHEADER結構中的成員ClrUsed指定實際使用的顏色數目。如果ClrUsed設定成0,位元影像使用的顏色數目就等於 biBitCount成員中的數目。請注意,如果ClrUsed的值不是可用顏色的最大值或不是0,則在編程時應該注意調色盤尺寸的計算,比如在4位位元影像中,調色盤的預設尺寸應該是16*sizeof(RGBQUAD),但是,如果ClrUsed的值不是16或者不是0,那麼調色盤的尺寸就應該是 ClrUsed*sizeof(RGBQUAD)。
(4) 圖象資料壓縮
① BI_RLE8:每個象素為8位元的RLE壓縮編碼,可使用編碼方式和絕對方式中的任何一種進行壓縮,這兩種方式可在同一幅圖中的任何地方使用。
編碼方式:由2個位元組組成,第一個位元組指定使用相同顏色的象素數目,第二個位元組指定使用的色彩索引。此外,這個位元組對中的第一個位元組可設定為0,聯合使用第二個位元組的值表示:
|
第二個位元組的值為0:行的結束。
|
|
第二個位元組的值為1:圖象結束。
|
|
第二個位元組的值為2:其後的兩個位元組表示下一個象素從當前開始的水平和垂直位置的位移量。
|
絕對方式:第一個位元組設定為0,而第二個位元組設定為0x03~0xFF之間的一個值。在這種方式中,第二個位元組表示跟在這個位元組後面的位元組數,每個位元組包含單個象素的色彩索引。壓縮資料格式需要字邊界(word boundary)對齊。下面的例子是用16進位表示的8-位壓縮圖象資料:
03 04 05 06 00 03 45 56 67 00 02 78 00 02 05 01 02 78 00 00 09 1E 00 01
這些壓縮資料可解釋為 :
壓縮資料 |
擴充資料 |
| 03 04 |
04 04 04 |
| 05 06 |
06 06 06 06 06 |
| 00 03 45 56 67 00 |
45 56 67 |
| 02 78 |
78 78 |
| 00 02 05 01 |
從當前位置右移5個位置後向下移一行 |
| 02 78 |
78 78 |
| 00 00 |
行結束 |
| 09 1E |
1E 1E 1E 1E 1E 1E 1E 1E 1E |
| 00 01 |
RLE編碼圖象結束 |
② BI_RLE4:每個象素為4位元的RLE壓縮編碼,同樣也可使用編碼方式和絕對方式中的任何一種進行壓縮,這兩種方式也可在同一幅圖中的任何地方使用。這兩種方式是:
編碼方式:由2個位元組組成,第一個位元組指定象素數目,第二個位元組包含兩種色彩索引,一個在高4位,另一個在低4位。第一個象素使用高4位的色彩索引,第二個使用低4位的色彩索引,第3個使用高4位的色彩索引,依此類推。
絕對方式:這個位元組對中的第一個位元組設定為0,第二個位元組包含有色彩索引數,其後續位元組包含有色彩索引,色彩索引存放在該位元組的高、低4位中,一個色彩索引對應一個象素。此外,BI_RLE4也同樣聯合使用第二個位元組中的值表示:
|
第二個位元組的值為0:行的結束。
|
|
第二個位元組的值為1:圖象結束。
|
|
第二個位元組的值為2:其後的兩個位元組表示下一個象素從當前開始的水平和垂直位置的位移量。
|
下面的例子是用16進位數表示的4-位壓縮圖象資料:
03 04 05 06 00 06 45 56 67 00 04 78 00 02 05 01 04 78 00 00 09 1E 00 01
這些壓縮資料可解釋為 :
壓縮資料 |
擴充資料 |
| 03 04 |
0 4 0 |
| 05 06 |
0 6 0 6 0 |
| 00 06 45 56 67 00 |
4 5 5 6 6 7 |
| 04 78 |
7 8 7 8 |
| 00 02 05 01 |
從當前位置右移5個位置後向下移一行 |
| 04 78 |
7 8 7 8 |
| 00 00 |
行結束 |
| 09 1E |
1 E 1 E 1 E 1 E 1 |
| 00 01 |
RLE圖象結束 |
3. 彩色表
彩色表包含的元素與位元影像所具有的顏色數相同,象素的顏色用RGBQUAD結構來定義。對於24-位真彩色圖象就不使用彩色表(同樣也包括16位、和 32位位元影像),因為位元影像中的RGB值就代表了每個象素難丈2噬碇械難丈囪丈鬧匾耘判潁飪梢願ㄖ允廄絛蛭荒芟允咀愎歡嘌丈南允舊璞趕允靜噬枷蟆GBQUAD結構描述由R、G、B相對強度組成的顏色,定義如下:
typedef struct tagRGBQUAD { /* rgbq */
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
其中:
rgbBlue
|
指定藍色強度
|
rgbGreen
|
指定綠色強度
|
rgbRed
|
指定紅色強度
|
rgbReserved
|
保留,設定為0
|
4. 位元影像資料
緊跟在彩色表之後的是圖象資料位元組陣列。圖象的每一掃描行由表示圖象象素的連續的位元組組成,每一行的位元組數取決於圖象的顏色數目和用象素表示的圖象寬度。掃描行是由底向上儲存的,這就是說,陣列中的第一個位元組表示位元影像左下角的象素,而最後一個位元組表示位元影像右上方的象素。(只針對與倒向DIB,如果是正向DIB,則掃描行是由頂向下儲存的),倒向DIB的原點在映像的左下角,而正向DIB的原點在映像的左上方。同時,每一掃描行的位元組數必需是4的整倍數,也就是DWORD對齊的。如果你想確保映像的掃描行DWORD對齊,可使用下面的代碼:
(((width*biBitCount)+31)>>5)<<2
5. 參考書目
《圖象檔案格式(上、下)—Windows編程》
《影像檔格式大全》
《Programming Windows by Charles Petzold》
6. 相關網站
各種格式:http://www.wotsit.org/
各種格式:http://www.csdn.net/
位元影像格式:http://www.cica.indiana.edu/graphics/image_specs/bmp.format.txt
〈完〉