BMP文件格式分析
本來不想寫這篇東西,因為介紹BMP文件結構的資料太多了,都有些濫了。但剛寫完BMP的讀寫模塊,又不想不留下點什么,所以就寫了,全當是學習筆記吧。自己以后查資料時也方便一些,也許對某些初哥還會有點用^_^
簡介
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的值:
|
||||||||
圖象數據 | 根據BMP版本及調色板尺寸的不同而不同 | Bitmap Data | xxx bytes | 該域的大小取決于壓縮方法及圖像的尺寸和圖像的位深度,它包含所有的位圖數據字節,這些數據可能是彩色調色板的索引號,也可能是實際的RGB值,這將根據圖像信息頭中的位深度值來決定。 |
構件詳解
1. 位圖文件頭
位圖文件頭包含有關于文件類型、文件大小、存放位置等信息,在Windows 3.0以上版本的位圖文件中用BITMAPFILEHEADER結構來定義:
typedef struct tagBITMAPFILEHEADER { /* bmfh */
UINT bfType;} BITMAPFILEHEADER;
DWORD bfSize;
UINT bfReserved1;
UINT bfReserved2;
DWORD bfOffBits;
?
其中:
?
|
|
|
|
|
|
|
|
|
|
2. 位圖信息頭
位 圖信息用BITMAPINFO結構來定義,它由位圖信息頭(bitmap-information header)和彩色表(color table)組成,前者用BITMAPINFOHEADER結構定義,后者用RGBQUAD結構定義。BITMAPINFO結構具有如下形式:
typedef struct tagBITMAPINFO { /* bmi */
BITMAPINFOHEADER bmiHeader;} BITMAPINFO;
RGBQUAD bmiColors[1];
?
其中:
?
|
|
|
|
BITMAPINFOHEADER結構包含有位圖文件的大小、壓縮類型和顏色格式,其結構定義為:
typedef struct tagBITMAPINFOHEADER { /* bmih */
DWORD biSize;} BITMAPINFOHEADER;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
?
其中:
?
|
|
||||||||
|
|
||||||||
|
|
||||||||
|
|
||||||||
|
|
||||||||
|
說明圖象數據壓縮的類型。其值可以是下述值之一:
|
||||||||
|
說明圖象的大小,以字節為單位。當用BI_RGB格式時,可設置為0 | ||||||||
|
說明水平分辨率,用象素/米表示 | ||||||||
|
說明垂直分辨率,用象素/米表示 | ||||||||
|
說明位圖實際使用的彩色表中的顏色索引數(設為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:
編碼方式:由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值就代表了每個象素的顏色。彩色表中的顏色按顏色的重要性排序,這可以輔助顯示驅動程序為不能顯示足夠多顏色數的顯示設備顯示彩 色圖象。RGBQUAD結構描述由R、G、B相對強度組成的顏色,定義如下:
typedef struct tagRGBQUAD { /* rgbq */
BYTE rgbBlue;} RGBQUAD;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
?
其中:
?
|
|
|
|
|
|
|
|
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
〈完〉
YZ 2000-8-13 13:11
posted on 2007-09-21 10:09 藍色幽默 閱讀(710) 評論(1) 編輯 收藏 所屬分類: Java