BMP文件格式,又稱為Bitmap(位圖),或是DIB(Device-Independent Device,設備無關圖),是windows系統中廣泛使用的圖片文件格式,由於它可以不作任何變換地址保存圖像像素域的數據,因為稱為我們取得RAW數據的重要來源。Windows的圖像用戶界面也在他的內建圖像子系統GDI中對BMP格式提供了支持。
BMP文件的數據按照從文件頭開始的先后順序分為四部分:
- l bmp文件頭:提供文件的格式、大小等信息
- l 位圖信息頭:提供圖像數據的尺寸、位平面數、壓縮方式、顏色索引等信息
- l 調色板:可選,如使用索引來表示圖像
- l 位圖數據:圖像數據
一般圖像以24位圖像為主,即R、G、B三種顏色各8bit來表示,這樣的圖像稱之為真彩色,此時是不需要調色板的,也就是說位圖信息頭后緊跟着就是位圖數據了。所以位圖文件從文件頭開始偏移54個字節就是位圖數據了,這就是24位或者32位圖的情況。這也就解釋了我們按照這種程序寫出來的程序為什么對於某些圖文件沒有用了。
byte – 8字節
word – 16字節
int/unit/dword – 32字節
文件頭:
BMP的文件頭共14個字節
字節順序 |
數據結構 |
描述 |
1,2 |
word |
高8位位字母‘B,低8位為字母’M‘ |
3,4,5,6 |
unit |
文件尺寸 |
7,8 |
word |
保留字1 |
9,10 |
word |
保留字1 |
11,12,13,14 |
unit |
位圖數據部分相對於文件的起始偏移量 |
數據部分偏移量的存在,說明圖像數據部分並不一定要緊隨圖像參數或調色板之后放置,BMP圖片的制作者其實可以在調色板之后、數據部分之前填充任何內容,只要正確地設置偏移量即可。
圖像參數信息:
這一個數據塊共40字節或56字節。前40字節的內容如下:
字節順序 |
數據結構 |
描述 |
15,16,17,18 |
unit |
當前結構體的大小,通常是40或56 |
19,20,21,22 |
int |
圖像寬度(像素) |
23,24,25,26 |
int |
圖像高度(像素) |
27,28 |
word |
恆為1 |
29,30 |
word |
每個像素占用的位數即bpp |
31,32,33,34 |
unit |
壓縮方式 |
35,36,37,38 |
unit |
圖像的尺寸 |
39,40,41,42 |
int |
水平分辨率 |
43,44,45,46 |
int |
垂直分辨率 |
47,48,49,50 |
uint |
引用色彩數 |
51,52,53,54 |
uint |
關鍵色彩數 |
31-34字節表示圖像數據的壓縮方式,參數取值范圍是0,1,2,3等
0 – RGB方式
1 – 8bpp的run-length-encoding方式
2 – 4bpp的run-length-encoding方式
3 – bit-fields方式
只有壓縮方式選項被設置為bit-fileds時,當前結構體大小為56字節,否則,為40字節。
調色板
當bpp <= 8時,BMP使用調試版記錄色彩信息,調色板每條數據(即每條色彩值)都是一個uint型數據。當調色板存在時,圖像數據塊中存儲的只是各個像素的色彩在調色板中的索引值,必須通過在調色板中查表,才能獲取各個像素的只是顏色。若引入調色板,則調色板數據塊緊隨在圖像參數數據塊之后。
bpp == 1 時,調色板合法索引值只有0和1.因此調色板塊只有兩個色彩值,分別表示索引值為0和1的色彩信息。
bpp == 4或 bpp == 8 時,合法索引值范圍擴大為[0,15]和 [0,255]。但圖像不一定使用到了全部16種或256種顏色。第47-50字節存儲的uint型數據指出圖像種實際應用的色彩書,也即調色板種的色彩值數目。當然他不應該超出調色板的合法索引值范圍。
當bpp == 4 或bpp == 8時,可以采用Run-Length-Encoding方式壓縮 圖像的存儲空間,即壓縮方式選項的值為1或2,(當選項值為0時不壓縮)。這種編碼格式所要考慮的情況是,如4bpp或8bpp位圖尺寸較大時,由於色彩總數是非常有限的,所以圖像中必然會出現和諾顏色重復的像素,因此BMP圖像格式的設計者決定采用一種簡單的措施來挽回一些被浪費掉的存儲空間,這個簡單的措施就是RLE壓縮方法。
RLE—Run-Length-Encoding
先用一個字節來存儲重復色彩的數量,再用一個字節來存儲這個色彩的值,即用來個字節代表一段重復的像素並且,他們給這段重復色彩的數量起了一個名字,叫做Run-Length。由於runleng為0時是沒有意義,因此設計者把runleng=0作為每行的終止符。
如果一張位圖中沒有重復的像素,這種情況最好不要使用壓縮算法。(紅藍像素點陣),如果既有重復像素,又有點陣的情況的時候,就需要修改runlength=0時候的意義了。
設計者規定,如果遇到runlength=0時繼續讀取下一個字節,如果該字節值為n,意味着后面n個像素將采用逐字翻譯的方式來解析。也就是說n個像素前面沒有runlength這個字節。
上訴方法導致了runlength==0的作為行終止符的含義修改了。但是runlength==0之后的nage 字節值為0,1,2時仍然沒有意義,所以規定,當這個值為0時,表示行結束符;當這個值為1時,表示文件結束符;當這個值大於等於3時才逐字翻譯。
RGB和Bit-Fields
當圖像中引用的色彩數超過256時,我們就需要16bpp或更高的位圖,調色板不適合bpp較大的位圖,因此16bpp以上的位圖不適合使用調色板。不使用調色板的位圖圖像有兩種編碼格式:RGB和Bit-Fileds
RGB編碼是一種均分思想,使Red、Green、Blue三個顏色分包含的信息容量盡可能的一樣大。
16bpp-RGB:在每個像素所占的16bits種,低5位表示Blue分量;中5位表示Green分量;高5位表示Red分量;最高意味無意義。所以從低到高的順序實際上使B-G-R。
24bpp-RGB:24bpp的位圖又稱為真彩位圖,它通常只有一種的編碼格式,在24bits中,低8位表示Blue分量;中8位表示Green分量;高8位表示Red分量;
32bpp-RGB:在32bits中,低24位的編碼方式與24bpp位圖相同,最高八位用來表示Alpha分量。32bpp的位圖尺寸太大,一般只有在圖像處理的中間過程使用,對於需要半透過效果的圖像,更好的選擇使PNG格式。
BF編碼格式與RGB不同,他利用位域操作,認為的確定RGB三分量所包含的信息容量。在圖像參數信息模塊的介紹中提及,當壓縮方式選項設置位BF時,圖像參數結構將比平時多16字節。這16字節實際上時4個dword的位域掩碼。按照先后順序,他們分別是R、G、B、A四個分量的位域掩碼,如果沒有Alpha分量,則Alpha掩碼沒有實際意義。
位域掩碼的作用是:指出像素色彩中的RGB分量,就像子網掩碼指出子網網段一樣。
16-bpp-BF-565:這是BF編碼格式最著名和最普遍的應用。他的Red、Green、Blue分量的位掩碼分別是0xF800、0x07E0、0x001F。
圖像數據塊
圖像數據塊從頭文件中起始偏移量字段所指出的位置開始,其中存放着位圖圖像的數據,數據格式由圖像參數信息塊中的壓縮方式選項取值決定。操作圖像數據塊時,有一些注意事項:
當壓縮方式為RGB時,圖像數據塊以“行”為單位雙字對齊。
bpp<8時,每個字節將存放多個像素的色彩所以,則先出現的像素存放在高位。