位元影像BITMAPINFOHEADER 與BITMAPFILEHEADER:
先來看BITMAPINFOHEADER,唯寫幾個主要的
biSize包含的是這個結構體的大小(包括顏色表)
biWidth和biHeight分別是圖片的長寬
biPlanes是目標繪圖裝置包含的層數,必須設定為1
biBitCount是映像的位元,例如24位,8位等
biXPelsPerMeter, biYPelsPerMeter 是現實世界中每米包含的像素數 設為3780即可
biSizeImage 映像資料的大小 = biWidth X biHeight X biBitCount
---------------------------------------------------------------------------------
再看 BITMAPFILEHEADER
bfType 圖片的類型 必須是BM 填0x4d42即十進位的19778
bfOffBits 從檔案頭開始到顏色資料的位移量 54+sizeof(RGBQUAD)*256
bfSize 圖片的大小,bfOffBits + 長 X 寬 X 位元 例如對於128X128X24位的映像 bfSize=128X128X24 + 54+sizeof(RGBQUAD)*256
bfReserved1和bfReserved1必須為0
BMP檔案結構及其存取
數位影像在外儲存空間裝置中的儲存形式是影像檔,映像必須按照某個已知的、公認的資料存放區順序和結構進行儲存,才能使不同的程式對影像檔順利進行開啟或存檔操作,實現資料共用。映像資料在檔案中的儲存順序和結構稱為影像檔格式。目前廣為流傳的影像檔格式有許多種,常見的格式包括BMP、 GIF、JPEG、TIFF、PSD、DICOM、MPEG等。在各種影像檔格式中,一部分是由某個軟硬體廠商提出並被廣泛接受和採用的格式,例如 BMP、GIF和PSD格式;另一部分是由各種國際標準組織提出的格式,例如JPEG、TIFF和DICOM,其中JPEG是國際靜止映像壓縮標準組織提出的格式,TIFF是由部分廠商組織提出的格式,DICOM是醫學映像國際標準組織提出的醫學映像專用格式。
BMP檔案是Windows作業系統所推薦和支援的影像檔格式,是一種將記憶體或顯示器的映像資料不經過壓縮而直接按位存檔的檔案格式,所以稱為位元影像(bitmap)檔案,因其副檔名為BMP,故稱為BMP檔案格式,簡稱BMP檔案。本書對映像的演算法編程都是針對BMP影像檔的,因此在本章中我們詳細介紹BMP檔案結構及其讀寫操作,以加深對映像資料的理解。
BMP檔案總體上由4部分組成,分別是位元影像檔案頭、位元影像資訊頭、調色盤和映像資料,如表5-1所示。 表5-1 BMP檔案的組成結構
位元影像檔案頭(bitmap-file header) |
位元影像資訊頭(bitmap-information header) |
彩色表/調色盤(color table) |
位元影像資料(bitmap-data) |
下面來詳細看一下每個組成部分的細節。 1.位元影像檔案頭(bitmap-file header) 位元影像檔案頭(bitmap-file header)包含了映像類型、映像大小、映像資料存放地址和兩個保留未使用的欄位。 開啟WINGDI.h檔案,搜尋"BITMAPFILEHEADER"就可以定位到BMP檔案的位元影像檔案頭的資料結構定義。
typedef struct tagBITMAPFILEHEADER { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER; |
表5-2列出了tagBITMAPFILEHEADER中各欄位的含義。 表5-2 tagBITMAPFILEHEADER結構
字 段 名 |
大小(單位:位元組) |
描 述 |
bfType |
2 |
位元影像類別,根據不同的操作 系統而不同,在Windows 中,此欄位的值總為‘BM’ |
bfSize |
4 |
BMP影像檔的大小 |
bfReserved1 |
2 |
總為0 |
bfReserved2 |
2 |
總為0 |
bfOffBits |
4 |
BMP映像資料的地址 |
2.位元影像資訊頭(bitmap-information header) 位元影像資訊頭(bitmap-information header)包含了位元影像資訊頭的大小、映像的寬高、映像的色深、壓縮說明映像資料的大小和其他一些參數。 開啟WINGDI.h檔案,搜尋"tagBITMAPINFOHEADER"就可以定位到BMP檔案的位元影像資訊頭的資料結構定義。
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, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER; |
表5-3列出了tagBITMAPFILEHEADER中各欄位的含義。 表5-3 tagBITMAPFILEHEADER結構
字 段 名 |
大小 (單位: 位元組) |
描 述 |
biSize |
4 |
本結構的大小,根據不同的作業系統而不同,在Windows中,此欄位的值總為28h位元組=40位元組 |
biWidth |
4 |
BMP映像的寬度,單位像素 |
biHeight |
4 |
總為0 |
biPlanes |
2 |
總為0 |
biBitCount |
2 |
BMP映像的色深,即一個像素用多少位表示,常見有1、4、8、16、24和32,分別對應單色、16色、256色、16位高彩色、24位真彩色和32位增強型真彩色 |
biCompression |
4 |
壓縮方式,0表示不壓縮,1表示RLE8壓縮,2表示RLE4壓縮,3表示每個像素值由指定的掩碼決定 |
biSizeImage |
4 |
BMP映像資料大小,必須是4的倍數,映像資料大小不是4的倍數時用0填充補足 |
biXPelsPerMeter |
4 |
水平解析度,單位像素/m |
biYPelsPerMeter |
4 |
垂直解析度,單位像素/m |
biClrUsed |
4 |
BMP映像使用的顏色,0表示使用全部顏色,對於256色位元影像來說,此值為100h=256 |
biClrImportant |
4 |
重要的顏色數,此值為0時所有顏色都重要,對於使用調色盤的BMP映像來說,當顯卡不能夠顯示所有顏色時,此值將輔助驅動程式顯示顏色 |
|
3.彩色表/調色盤(color table) 彩色表/調色盤(color table)是單色、16色和256色影像檔所特有的,相對應的調色盤大小是2、16和256,調色盤以4位元組為單位,每4個位元組存放一個顏色值,映像 的資料是指向調色盤的索引。 可以將調色盤想象成一個數組,每個數組元素的大小為4位元組,假設有一256色的BMP映像的調色盤資料為:
調色盤[0]=黑、調色盤[1]=白、調色盤[2]=紅、調色盤[3]=藍…調色盤[255]=黃 |
映像資料01 00 02 FF表示調用調色盤[1]、調色盤[0]、調色盤[2]和調色盤[255]中的資料來顯示映像顏色。 在早期的電腦中,顯卡相對比較落後,不一定能保證顯示所有顏色,所以在調色盤中的顏色資料應儘可能將映像中主要的顏色按順序排列在前面,位元影像資訊 頭的biClrImportant欄位指出了有多少種顏色是重要的。 每個調色盤的大小為4位元組,按藍、綠、紅儲存一個顏色值。 開啟WINGDI.h檔案,搜尋"tagRGBTRIPLE"就可以定位到BMP檔案的調色盤的資料結構定義。
typedef struct tagRGBQUAD { BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; BYTE rgbReserved; } RGBQUAD; |
表5-4列出了tagRGBTRIPLE中各欄位的含義。 表5-4 tagRGBTRIPLE結構
字 段 名 |
大小(單位:位元組) |
描 述 |
rgbBlue |
1 |
藍色值 |
rgbGreen |
1 |
綠色值 |
rgbRed |
1 |
紅色值 |
rgbReserved |
1 |
保留,總為0 |
4.位元影像資料(bitmap-data) 如果映像是單色、16色和256色,則緊跟著調色盤的是位元影像資料,位元影像資料是指向調色盤的索引序號。 如果位元影像是16位、24位和32位色,則影像檔中不保留調色盤,即不存在調色盤,映像的顏色直接在位元影像資料中給出。 16位元影像像使用2位元組儲存顏色值,常見有兩種格式:5位紅5位綠5位藍和5位紅6位綠5位藍,即555格式和565格式。555格式只使用了15 位,最後一位保留,設為0。 24位元影像像使用3位元組儲存顏色值,每一個位元組代表一種顏色,按紅、綠、藍排列。 32位元影像像使用4位元組儲存顏色值,每一個位元組代表一種顏色,除了原來的紅、綠、藍,還有Alpha通道,即透明色。 如果映像帶有調色盤,則位元影像資料可以根據需要選擇壓縮與不壓縮,如果選擇壓縮,則根據BMP映像是16色或256色,採用RLE4或RLE8壓縮算 法壓縮。 RLE4是壓縮16色映像資料的,RLE4採用表5-5所示方式壓縮資料。 表5-5 RLE4壓縮方法
方 案 |
1位元組 |
2位元組 |
3位元組 |
4位元組 |
N位元組 |
A |
重複次數 |
色彩索引 |
|
|
|
B |
設為0 |
後面有效 色彩索引數 |
色彩索引 |
色彩索引 |
色彩索引… |
假設有如下16色位元影像資料,共20位元組,資料使用了RLE4壓縮:
05 00 04 05 00 08 09 05 04 00 04 05 08 09 04 08 07 01 00 00 |
資料解壓時首先讀取05,因為05不等於0,所以選擇A方案,根據A方案,05表示後面資料重複的次數,接著讀取00,00表示有兩個色彩索引,每 個索引佔4位,第一個像素在高4位,第二個像素在低4位,即在一個位元組中低像素在高位,高像素在低位。05 00解壓後等於00 00 0。 讀取04,選擇A方案,按照上面的操作解析,04是後面資料重複的次數,05是兩個色彩索引,第3個色彩索引為5,第4個色彩索引為0。04 05解壓後等於05 05。 讀取00,選擇B方案,讀取08,08表示後面有效色彩索引數。00 08解壓後等於09 05 04 00。 讀取04,選擇A方案,按照上面的操作解析,04是後面資料重複的次數,05是兩個色彩索引。04 05解壓後等於05 05。 讀取08,選擇A方案,按照上面的操作解析,08是後面資料重複的次數,09是兩個色彩索引。08 09解壓後等於09 09 09 09。 讀 取04,選擇A方案,按照上面的操作解析,04是後面資料重複的次數,08是兩個色彩索引。04 08解壓後等於08 08。 讀取07,選擇A方案,按照上面的操作解析,07是後面資料重複的次數,01是兩個色彩索引。07 01解壓後等於01 01 01 0。 讀取00,選擇B方案,讀取00,00表示後面有效色彩索引數,0表示無,即解壓完一行資料。 綜合上面的操作,解壓後的資料為:
00 00 00 50 50 90 50 40 00 50 50 90 90 90 90 80 80 10 10 10 |
看上去和原來的資料大小一樣,沒有體現到壓縮效果,這是因為上面的例子只選擇了20位元組資料,而且這20位元組資料中重複的資料不多,使用RLE壓縮 重複資料不多的資料時,有時可能壓縮後的大小反而比原來的資料還大。其實一般情況下當資料比較多而且重複的時候,使用RLE壓縮效果還是比較理想的。 RLE8的壓縮方式可以參考上面的RLE4解壓方法,惟一的區別是RLE8使用1個位元組存放色彩索引,而RLE4使用4位存放色彩索引。 結合上面對BMP檔案的分析,下面分別對256色和24位色的BMP映像進行十六進位分析,通過在十六進位編輯器中分析檔案結構,能夠增加分析檔案 的經驗。 5-1和圖5-2所示,分別為256色BMP映像cat2.bmp和24位色BMP映像cat1.bmp。其中cat2.bmp映像的解析度為 200×153,檔案大小為31 680位元組。cat1.bmp映像的解析度為200×150,檔案大小為90 056位元組。
現 在來分析cat2.bmp的影像檔,在Winhex中開啟cat2.bmp,5-3所示。
|
(點擊查看大圖)圖5-3 在Winhex中開啟cat2.bmp影像檔 |
首先分析位元影像檔案頭的結構,5-4所示。根據 BMP檔案的位元影像檔案頭結構定義分析出cat2.bmp映像的位元影像檔案頭中各欄位的含義,如表5-6所示。
|
(點擊查看大圖)圖5-4 cat2.bmp影像檔的位元影像檔案頭 |
表5-6 cat2.bmp影像檔中位元影像檔案頭各欄位的含義
十六進位值 |
描 述 |
42 4D: |
BM的ASCII值,在Windows中的BMP檔案標識符 |
C0 7B 00 00 |
7B C0h=31680,是cat2檔案的大小 |
00 00 00 00 |
保留值,總為0 |
36 04 00 |
436h=1078,是映像資料的地址,即檔案頭+資訊頭+調色盤的長度 |
|
繼續分析接下來的資料,根據BMP檔案結構的定義,接下來的資料是位元影像資訊頭,cat2.bmp影像檔的位元影像資訊頭的內容5-5所示。
|
(點擊查看大圖)圖5-5 cat2.bmp映像的位元影像資訊頭 |
表5-7所示為cat2.bmp影像檔中位元影像資訊頭各欄位的含義。
表5-7 cat2.bmp影像檔中位元影像資訊頭各欄位的含義
十六進位值 |
描 述 |
28 00 00 00: |
cat2.bmp映像的位元影像資訊頭大小 |
C8 00 00 00 |
00 00 00 C8 = 200,是cat2映像的寬度,單位像素 |
99 00 00 00 |
00 00 00 99 = 153,是cat2映像的高度,單位像素 |
01 00 |
總是1 |
08 00 |
00 08 = 8,cat2映像的色深,即2的8次等冪於256色 |
00 00 00 00 |
壓縮方式,0表示不壓縮 |
8A 77 00 00 |
00 00 77 8A = 30602,是cat2映像的映像資料大小,單位位元組 |
12 0B 00 00 |
00 00 0B 12 = 2834,cat2映像的水平解析度,單位像素/m |
12 0B 00 00 |
00 00 0B 12 = 2834,cat2映像的垂直 解析度,單位像素/m |
00 00 00 00 |
cat2映像使用的顏色數,0表示使用全部顏色 |
00 00 00 00 |
cat2映像中重要的顏色數,0表示所有顏色都重要 |
繼續分析接下來的資料,根據BMP檔案結構的定義,因為cat2.bmp映像是256色的位元影像,所以應該有256個調色盤,每個調色盤佔4位元組,整 個調色盤一共1024位元組大小。 cat2.bmp影像檔的調色盤資料5-6和圖5-7所示。
|
(點擊查看大圖)圖5-6 cat2.bmp映像的調色盤地址從00000036h開始儲存 |
|
(點擊查看大圖)圖5-7 cat2.bmp映像的調色盤資料結束位址是00000435h |
從圖5-6和圖5-7中可以看出,cat2.bmp映像的調色盤地址從00000036h開始到00000435h結束,即00000435h - 00000036h + 1 =400h = 1024。
如果想查看cat2映像的調色盤對應的實際顯示顏色,可以使用Adobe Photoshop CS開啟cat2.bmp,在Adobe Photoshop CS的功能表列中選擇"映像"→"模式"→"顏色表",即可觀看cat2的調色盤,5-8所示。
|
圖5-8 在Adobe Photoshop CS中查看cat2的調色盤 |
圖5-8所示cat2.bmp的調色盤顏色和圖5-6中的十六進位資料是一一對應的。在Adobe Photoshop CS的調色盤上單擊任何一個像素的顏色即可彈出一個拾色器對話方塊顯示該像素顏色的詳細組成資訊。cat2.bmp調色盤和cat2.bmp的十六進位資料 的對應關係5-9所示。
繼續分析接下來的資料,根據BMP檔案結構的定義,如果一個映像有調色盤,那麼緊跟在調色盤後面的是映像的資料,這些資料不是實際的顏色值,而是指 向調色盤數組的索引,根據索引來擷取調色盤中的顏色,5-10所示。
|
(點擊查看大圖)圖5-9 cat2.bmp調色盤和cat2.bmp的十六進位資料的對應關係 |
|
(點擊查看大圖)圖5-10 cat2.bmp的映像資料 |
因為cat2.bmp是256色的位元影像,即採用了8位色深作為指向調色盤數組的索引,所以根據圖5-10中顯示的資料可以得知:49 49 49 B1 49 49 49 49 49 99表示cat2.bmp位元影像左下角第1個像素的顏色等於調色盤[49],第2個像素的顏色等於調色盤[49] ,第3個像素的顏色等於調色盤[49] ,第4個像素的顏色等於調色盤[B1]……依此類推。分析完cat2.bmp映像之後,接下來分析的是cat1.bmp。
cat1.bmp映像是24位色映像,根據BMP檔案結構定義得知,cat1.bmp映像沒有調色盤,映像資料存放區的是實際的顏色資料,每個像素用 3位元組表示,分別是紅綠藍。由於cat1.bmp和cat2.bmp的位元影像檔案頭和位元影像資訊頭結構一樣,所以cat1.bmp的位元影像檔案頭和位元影像資訊頭可 以參考上面對cat2.bmp的分析,下面從cat1.bmp的位元影像資訊頭結束的位置開始分析,5-11所示。
|
(點擊查看大圖)圖5-11 cat1.bmp映像的映像資料 |
從圖5-11可以看到表示每個像素的紅綠藍三色的值,實際存放的時候是倒過來存放的,在分析BMP映像格式時需要注意這點。
通過上面對BMP檔案儲存體結構的分析發現,BMP檔案的位元影像檔案頭和位元影像資訊頭存在著大量的重複資料。如果儲存大量同一色深的BMP位元影像,必然會浪 費大量儲存空間,所以很多時候遊戲編程人員都會去掉BMP檔案頭和資訊頭,只保留幾個必要的資訊和映像資料,那麼BMP檔案頭和資訊頭中哪幾個欄位是必須 保留的呢?
使用Winhex的檔案比較功能比較兩個24位色深的BMP影像檔,觀察兩個檔案的檔案頭和資訊頭有什麼不同的地方,5-12所示。
|
(點擊查看大圖)圖5-12 使用Winhex比較兩個24位色深的BMP影像檔 |
從圖5-12可以看出,兩個色深相同的BMP映像的檔案頭和資訊頭一共有4處不同的地方,分別是檔案頭的檔案大小、資訊頭的映像寬度、映像高度和圖 像資料大小。
所以很多時候,遊戲編程人員只保留影像檔的檔案大小、映像寬度、映像高度和映像資料大小資訊,甚至有時不需要保留檔案大小這個數值,使用映像資料大小數值即可。
在分析未知檔案儲存體格式時,如果遇到去掉了檔案頭的檔案時,如上面所說的BMP檔案,會給分析未知檔案格式帶來一定的困難。這時需要使用十六進位編 輯器的檔案比較功能,觀察兩個同類的未知檔案格式尋找某些潛在的規律,如果實在觀察不出規律的,那隻能使用白盒分析方法,對調用此未知檔案格式的程式進行反組譯碼跟蹤調試了。當然,有時靈感和運氣也很重要。
類似資料:
1、http://www.cnblogs.com/lzlsky/archive/2012/08/16/2641698.html
2、http://hi.baidu.com/xiaozhiwen2008/item/0a73bbfd0e90586e3d14854a
3、http://blog.sina.com.cn/s/blog_676cdfb10100sx0q.html