僅此一次對BMP檔案做詳細分析的機會,想了解的朋友千萬不能錯過

北亞資料恢復發表於2019-12-11
什麼是BMP?

BMP是一種與硬體裝置無關的影像檔案格式,使用非常廣。它採用位對映儲存格式,除了影像深度可選以外,不採用其他任何壓縮,因此,BblP檔案所佔用的空間很大。BMP檔案的影像深度可選lbit、4bit、8bit及24bit。BMP檔案儲存資料時,影像的掃描方式是按從左到右、從下到上的順序。
由於BMP檔案格式是Windows環境中交換與圖有關的資料的一種標準,因此在Windows環境中執行的圖形影像軟體都支援BMP影像格式。
典型的BMP影像檔案由三部分組成:點陣圖檔案頭資料結構,它包含BMP影像檔案的型別、顯示內容等資訊;點陣圖資訊資料結構,它包含有BMP影像的寬、高、壓縮方法,以及定義顏色等資訊
具體資料舉例:

如某BMP檔案開頭:

BMP檔案可分為四個部分:點陣圖檔案頭、點陣圖資訊頭、彩色板、影像資料陣列,在上圖中已用*分隔。
一、影像檔案頭 
1)1:影像檔案頭。424Dh=”BM”,表示是Windows支援的BMP格式。
2)2-3:整個檔案大小。4690 0000,為00009046h=36934。
3)4-5:保留,必須設定為0。
4)6-7:從檔案開始到點陣圖資料之間的偏移量。4600 0000,為00000046h=70,上面的檔案頭就是35字=70位元組。
5)8-9:點陣圖圖資訊頭長度。
6)10-11:點陣圖寬度,以畫素為單位。8000 0000,為00000080h=128。
7)12-13:點陣圖高度,以畫素為單位。9000 0000,為00000090h=144。
8)14:點陣圖的位面數,該值總是1。0100,為0001h=1。

二、點陣圖資訊頭 
9)15:每個畫素的位數。有1(單色),4(16色),8(256色),16(64K色,高彩色),24(16M色,真彩色),32(4096M色,增強型真彩色)。1000為0010h=16。
10)16-17:壓縮說明:有0(不壓縮),1(RLE 8,8位RLE壓縮),2(RLE 4,4位RLE壓縮,3(Bitfields,位域存放)。RLE簡單地說是採用畫素數+畫素值的方式進行壓縮。T408採用的是位域存放方式,用兩個位元組表示一個畫素,位域分配為r5b6g5。圖中0300 0000為00000003h=3。
11)18-19:用位元組數表示的點陣圖資料的大小,該數必須是4的倍數,數值上等於點陣圖寬度×點陣圖高度×每個畫素位數。0090 0000為00009000h=80×90×2h=36864。
12)20-21:用象素/米表示的水平解析度。A00F 0000為0000 0FA0h=4000。
13)22-23:用象素/米表示的垂直解析度。A00F 0000為0000 0FA0h=4000。
14)24-25:點陣圖使用的顏色索引數。設為0的話,則說明使用所有調色盤項。
15)26-27:對圖象顯示有重要影響的顏色索引的數目。如果是0,表示都重要。 三、彩色板 (非必有)

1 6)28-35: 彩色板規範。 對於調色盤中的每個表項,用下述方法來描述RGB的值:

1位元組用於藍色分量

1位元組用於綠色分量

1位元組用於紅色分量

1位元組用於填充符(設定為0)

對於24-位真彩色影像就不使用彩色板,因為點陣圖中的RGB值就代表了每個象素的顏色。

如,彩色板為00F8 0000 E007 0000 1F00 0000 0000 0000,其中:
00FB 0000為FB00h=1111100000000000(二進位制),是紅色分量的掩碼。
E007 0000為 07E0h=0000011111100000(二進位制),是綠色分量的掩碼。
1F00 0000為001Fh=0000000000011111(二進位制),是紅色分量的掩碼。
0000 0000總設定為0。 
      將掩碼跟畫素值進行“與”運算再進行移位操作就可以得到各色分量值。看看掩碼,就可以明白事實上在每個畫素值的兩個位元組16位中,按從高到低取5、6、5位分別就是r、g、b分量值。取出分量值後把r、g、b值分別乘以8、4、8就可以補齊第個分量為一個位元組,再把這三個位元組按rgb組合,放入儲存器(同樣要反序),就可以轉換為24位標準BMP格式了。

四、影像資料陣列 
17)17-...:每兩個位元組表示一個畫素。陣列中的第一個位元組表示點陣圖左下角的象素,而最後一個位元組表示點陣圖右上角的象素。

下面用winhex開啟一個bmp檔案,察看其16進位制資料。

一個bmp檔案以BITMAPFILEHEADER結構體開始,BITMAPFILEHEADER的第1個屬性是bfType(2位元組),這裡恆定等於0x4D42。由於記憶體中的資料排列高位在左,低位在右,所以記憶體中從左往右看就顯示成(42 4D),所以在winhex中頭兩個 位元組顯示為(42 4D)就是這樣形成的,以後的資料都是這個特點,不再作重複說明。

1、BITMAPFILEHEADER的第2個屬性是bfSize(4位元組),表示整個bmp檔案的大小,這裡等於0x000004F8=1272位元組。

2、BITMAPFILEHEADER的第3個、第4個屬性分別是bfReserved1、bfReserved2(各2位元組),這裡是2個保留屬性,都為0,這裡等於&H0000、0×0000。

3、BITMAPFILEHEADER的第5個屬性是bfOffBits(4位元組),表示DIB資料區在bmp檔案中的位置偏移量,這裡等於0×00000076=118,表示資料區從檔案開始往後數的118位元組開始。

4、BITMAPFILEHEADER結構體這裡就講完了,大家會發現BITMAPFILEHEADER只佔了bmp檔案開始的14位元組長度,但需要 特別說明的是在vb中定義一個BITMAPFILEHEADER結構體變數,其長度佔了16個位元組,原因就是第1個屬性本來應該只分配2個位元組,但實際被 分配了4個位元組,多出來2個位元組,所以如果想儲存一張bmp圖片,寫入BITMAPFILEHEADER結構體時一定要注意這一點。


接下來是BITMAPINFO結構體部分。BITMAPINFO段由兩部分組成:BITMAPINFOHEADER結構體和RGBQUAD結構 體。其中RGBQUAD結構體表示圖片的顏色資訊,有些時候可以省略,一般的24點陣圖片和32點陣圖片都不帶RGBQUAD結構體,因為DIB資料區直接表 示的RGB值,一般4點陣圖片和8點陣圖片才帶有RGBQUAD結構體。(多少位的圖片就是用多少位來表示一個顏色資訊,例如4點陣圖片表示用4個bit來表示 一個顏色資訊。)一個bmp檔案中有沒有RGBQUAD結構體,可以根據前面BITMAPFILEHEADER結構體的第5個屬性bfOffBits來判 斷,因為BITMAPINFOHEADER結構體長度為40bit,如果BITMAPINFOHEADER結構體結束後還未到DIB資料區的偏移量,就說 明接下來的資料是RGBQUAD結構體部分。這裡講的C:\WINDOWS\Blue Lace 16.bmp是一個4bit圖片,所以它帶有 RGBQUAD結構體。

下面進入正題BITMAPINFOHEADER部分。

1、BITMAPINFOHEADER的第1個屬性是biSize(4位元組),表示BITMAPINFOHEADER結構體的長度,最常見的長度是40位元組,UltraEdit中可以看到緊接著的4個位元組等於0×00000028=40位元組。

2、BITMAPINFOHEADER的第2個屬性是biWidth(4位元組),表示bmp圖片的寬度,這裡等於0×00000030=48畫素。

3、BITMAPINFOHEADER的第3個屬性是biHeight(4位元組),表示bmp圖片的高度,這裡等於0×00000030=48畫素。

4、BITMAPINFOHEADER的第4個屬性是biPlanes(2位元組),表示bmp圖片的平面屬,顯然顯示器只有一個平面,所以恆等於1,這裡等於0×0001。

5、BITMAPINFOHEADER的第5個屬性是biBitCount(2位元組),表示bmp圖片的顏色位數,即24點陣圖、32點陣圖等等。這裡等於0×0004,表示該圖片為4點陣圖。

6、BITMAPINFOHEADER的第6個屬性是biCompression(4位元組),表示圖片的壓縮屬性,bmp圖片是不壓縮的,等於0,所以這裡為0×00000000。

7、BITMAPINFOHEADER的第7個屬性是biSizeImage(4位元組),表示bmp圖片資料區的大小,當上一個熟悉biCompression等於0時,這裡的值可以省略不填,所以這裡等於0×00000000。

8、BITMAPINFOHEADER的第8個屬性是biXPelsPerMeter(4位元組),表示圖片X軸每米多少畫素,可省略,這裡等於0x00000EC3=3779畫素/米。

9、BITMAPINFOHEADER的第9個屬性是biYPelsPerMeter(4位元組),表示圖片Y軸每米多少畫素,可省略,這裡等於0x00000EC3=3779畫素/米。

10、BITMAPINFOHEADER的第10個屬性是biClrUsed(4位元組),表示使用了多少個顏色索引表,一般biBitCount屬性小於16才會用到,等於0時表示有2^biBitCount個顏色索引表,所以這裡仍等於0×00000000。

11、BITMAPINFOHEADER的第11個屬性是biClrImportant(4位元組),表示有多少個重要的顏色,等於0時表示所有顏色都很重要,所以這裡等於0×00000000。

至此BITMAPINFOHEADER結構體結束。

由於這個圖片到這裡還未到達DIB資料區的偏移量,所以接下來的部分是RGBQUAD結構體。RGBQUAD結構體由4個位元組型資料組成,所以一 個RGBQUAD結構體只佔用4位元組空間,從左到右每個位元組依次表示(藍色,綠色,紅色,未使用)。舉例的這個圖片我數了數總共有16個RGBQUAD結 構體,由於該圖片是4點陣圖,2^4正好等於16,所以它把16種顏色全部都列舉出來了,這些顏色就是一個顏色索引表。顏色索引表編號從0開始,總共16個 顏色,所以編號為0-15。從winhex中可以看到按照順序,這16個RGBQUAD結構體依次為:

編號:(藍,綠,紅,空)

0號:(00,00,00,00)

1號:(00,00,80,00)

2號:(00,80,00,00)

3號:(00,80,80,00)

4號:(80,00,00,00)

5號:(80,00,80,00)

6號:(80,80,00,00)

7號:(80,80,80,00)

8號:(C0,C0,C0,00)

9號:(00,00,FF,00)

10號:(00,FF,00,00)

11號:(00,FF,FF,00)

12號:(FF,00,00,00)

13號:(FF,00,FF,00)

14號:(FF,FF,00,00)

15號:(FF,FF,FF,00)


到這裡,正好滿足DIB資料區的偏移量,所以後面的位元組就是圖片內容了。這裡需要提醒的是所有的DIB資料掃描行是上下顛倒的,也就是說一幅圖片先繪製底部的畫素,再繪製頂部的畫素,所以這些DIB資料所表示的畫素點就是從圖片的左下角開始,一直表示到圖片的右上角。
由於這裡的圖片是4點陣圖片,也就是說4bit就表示一個畫素,一個位元組有8個bit,所以一個位元組能表示2個畫素。
從winhex中可以看到,DIB資料區第一個位元組是0×44,16進位制正好是將2進位制數每4個一組書寫的,跟4bit圖片正好吻 合,所以0×44表示兩個畫素,高位的4表示第一個畫素,低位的4表示第二個畫素。這裡的4不是表示RGB顏色,而是表示顏色索引號為4,由於索 引號從0開始編號的,所以4表示索引表中第5個顏色,從附圖中可以看到索引號為4的是藍色。這是第一位元組,表示的是圖片左下角開始2個畫素,如果有 PhotoShop開啟這個圖片可以看到,左下角2個畫素取出來的顏色RGB值正好等於索引表中第5個顏色的RGB值。後面的DIB資料以此類推。
至此一個bmp圖片就全部解析完了,根據這些資訊就可以完整的繪製一張bmp圖片來。當然也可以簡單手工修復一個破壞不算嚴重的BMP檔案!


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31380569/viewspace-2668037/,如需轉載,請註明出處,否則將追究法律責任。

相關文章