【转】BMP图像文件格式
5.1? BMP圖像文件格式
BMP圖像文件格式是游戲中常用的圖像資源文件格式,BMP圖像文件起源早,程序員對BMP都比較熟悉,再加上BMP格式簡單,讀取和寫入非常容易實現,所以無論Windows的還是Driect X,都有支持讀取和寫入BMP文件格式的API函數。
針對BMP壓縮的算法比較成熟,壓縮效果也不差,而且都是無損壓縮編碼,即可以100%還原BMP圖像質量。
雖然JPG格式壓縮效果比較理想,但游戲編程人員一般極少使用,因為JPG要犧牲圖像的質量來換取大的壓縮率,加上JPG解碼速度較慢和格式復雜,所以游戲中使用JPG格式的圖像的情況不多(筆者目前只發現一款網絡游戲使用JPG格式作為游戲里的圖像格式,并且使用額外的數據保存了圖像中的透明通道信息來讓JPG支持透明色)。GIF格式雖然支持多幀動畫效果,但GIF最大僅支持256色,不能表達色彩豐富的圖像,所以對于對速度要求非常苛刻而且圖像質量要高的游戲來說,使用BMP格式存儲圖像是不錯的選擇。
5.1.1? BMP圖像文件介紹
BMP圖像文件格式是微軟公司發明的,BMP圖像文件的后綴名通常是.BMP,但也有少數是.DIP。不過單憑文件的后綴名并不能惟一確定是不是BMP圖像文件,要惟一確定BMP圖像文件還需要分析文件的存儲格式。
BMP圖像文件和GIF圖像文件不同,BMP圖像文件只能存儲一幅圖像,即一幀。GIF圖像文件能保存多幀圖像,從而可以實現動畫的效果。
BMP圖像文件支持單色、16色、256色和真彩色4種顏色的圖像。BMP圖像的數據即可壓縮也可以不壓縮,如果選擇了壓縮數據,那么根據顏色的不同,BMP使用不同的RLE壓縮方式。
RLE是一種無損壓縮方法,使用RLE壓縮的數據能完整還原。如果圖像是16色,則可以采用RLE4壓縮,如果圖像是256色,則可以采用RLE8壓縮,真彩色的圖像不使用壓縮。
BMP的圖像數據排列方式有點特別,BMP的圖像數據排列方式首先從圖像的左下角第一個像素開始存儲每一行數據,即BMP圖像數據存儲的最后一個像素等于實際圖像的右上角第一個像素。
5.1.2? BMP圖像文件存儲結構(1)
BMP文件存儲結構的格式可以在Windows中的WINGDI.h文件中找到定義。
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圖像來說,當顯卡不能夠顯示所有顏色時,此值將輔助驅動程序顯示顏色 |
?
5.1.2? BMP圖像文件存儲結構(2)
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位存放顏色索引。
5.1.3? 分析BMP圖像文件結構(1)
結合上面對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字節。
圖5-1? cat2.bmp圖像
圖5-2? cat1.bmp圖像
現在來分析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,是圖像數據的地址,即文件頭+信息頭+調色板的長度 |
5.1.3? 分析BMP圖像文件結構(2)
繼續分析接下來的數據,根據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.1.3? 分析BMP圖像文件結構(3)
圖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文件,會給分析未知文件格式帶來一定的困難。這時需要使用十六進制編輯器的文件比較功能,觀察兩個同類的未知文件格式尋找某些潛在的規律,如果實在觀察不出規律的,那只能使用白盒分析方法,對調用此未知文件格式的程序進行反匯編跟蹤調試了。當然,有時靈感和運氣也很重要。?
?
原文地址:http://book.51cto.com/art/200903/112705.htm
總結
以上是生活随笔為你收集整理的【转】BMP图像文件格式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 返回北京
- 下一篇: mysql varbinary blob