1. 程式人生 > >BMP文件格式具體解釋

BMP文件格式具體解釋

-h 缺省 5.5 調色板 lan lib 對齊 edi 對比文件

BMP文件格式具體解釋(BMP file format)

BMP文件格式,又稱為Bitmap(位圖)或是DIB(Device-Independent Device,設備無關位圖),是Windows系統中廣泛使用的圖像文件格式。由於它能夠不作不論什麽變換地保存圖像像素域的數據。因此成為我們取得RAW數據的重要來源。Windows的圖形用戶界面(graphical user interfaces)也在它的內建圖像子系統GDI中對BMP格式提供了支持。

以下以Notepad++為分析工具,結合Windows的位圖數據結構對BMP文件格式進行一個深度的剖析。

BMP文件的數據依照從文件頭開始的先後順序分為四個部分:

? bmp文件頭(bmp file header)提供文件的格式、大小等信息

? 位圖信息頭(bitmap information)提供圖像數據的尺寸、位平面數、壓縮方式、顏色索引等信息

? 調色板(color palette)可選。如使用索引來表示圖像。調色板就是索引與其相應的顏色的映射表

? 位圖數據(bitmap data)就是圖像數據啦^_^

以下結合Windows結構體的定義。通過一個表來分析這四個部分。

技術分享

我們一般見到的圖像以24位圖像為主。即RGB三種顏色各用8bit來表示,這樣的圖像我們稱為真彩色。這樣的情況下是不須要調色板的。也就是所位圖信息頭後面緊跟的就是位圖數據了。因此,我們經常見到有這樣一種說法:位圖文件從文件頭開始偏移54

個字節就是位圖數據了,這事實上說的是2432位圖的情況。這也就解釋了我們依照這樣的程序寫出來的程序為什麽對某些位圖文件沒用了。

以下針對一幅特定的圖像進行分析,來看看在位圖文件裏這四個數據段的排布以及組成。

我們使用的圖像顯演示樣例如以下:

技術分享

這是一幅16位的位圖文件。因此它是含有調色板的。

在拉出圖像數據進行分析之前,我們首先進行幾個約定:

1. BMP文件裏,假設一個數據須要用幾個字節來表示的話,那麽該數據的存放字節順序為“低地址村存放低位數據。高地址存放高位數據”。如數據0x1756在內存中的存儲順序為:

技術分享

這樣的存儲方式稱為小端方式(little endian) , 與之相反的是大端方式(big endian)。對兩者的使用情況有興趣的能夠深究一下,當中還是有學問的。

2. 以下所有分析均以字節為序號單位進行。

以下我們對從文件裏拉出來的數據進行剖析:

技術分享

一、bmp文件頭
Windowsbmp文件頭定義了例如以下結構體:

技術分享typedef struct tagBITMAPFILEHEADER
{
UINT16 bfType;
DWORD bfSize;
UINT16 bfReserved1;
UINT16 bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
技術分享

當中:

技術分享

對比文件數據我們看到:

技術分享

1-2 424dh = ‘BM‘,表示這是Windows支持的位圖格式。有非常多聲稱開頭兩個字節必須為‘BM‘才是位圖文件,從上表來看應為開頭兩個字節必須為‘BM‘才是Windows位圖文件。

3-5 00010436h = 66614 B = 65.05 kB。通過查詢文件屬性發現一致。

6-9 :這是兩個保留段。為0

A-D00000436h = 1078

即從文件頭到位圖數據需偏移1078字節。我們稍後將驗證這個數據。

共同擁有14個字節。

二、位圖信息頭
相同地,Windows為位圖信息頭定義了例如以下結構體:

技術分享代碼

技術分享

對比數據文件:

技術分享

0E-1100000028h = 40,這就是說我這個位圖信息頭的大小為40個字節。

前面我們已經說過位圖信息頭一般有40個字節。既然是這樣,為什麽這裏還要給一個字段來說明呢?這裏涉及到一些歷史,事實上位圖信息頭原本有非常多大小的版本號的。

我們看一下下表:

技術分享

於兼容性的考慮,大多數應用使用了舊版的位圖信息頭來保存文件。

OS/2 已經過時了,因此如今最經常使用的格式就僅有V3 header了。因此,我們在前面說位圖信息頭的大小為40字節。

12-1500000100h = 256,圖像寬為255像素。與文件屬性一致。

16-1900000100h = 256。圖像高為255像素,與文件屬性一致。這是一個正數,說明圖像數據是從圖像左下角到右上角排列的。

1A-1B0001h, 該值總為1

1C-1D0008h = 8, 表示每一個像素占8個比特,即該圖像共同擁有256種顏色。

1E-2100000000hBI_RGB 說明本圖像不壓縮。

22-2500000000h。圖像的大小。由於使用BI_RGB,所以設置為0

26-2900000000h,水平分辨率。缺省。

2A-2D00000000h,垂直分辨率。缺省。

2E-3100000100h = 256,說明本位圖實際使用的顏色索引數為256,與1C-ID得到的結論一致。

32-3500000100h = 256,說明本位圖重要的顏色索引數為256,與前面得到的結論一致。

三、調色板
以下的數據就是調色板了。前面也已經提過。調色板事實上是一張映射表,標識顏色索引號與其代表的顏色的相應關系。它在文件裏的布局就像一個二維數組palette[N][4],當中N表示總的顏色索引數,每行的四個元素分別表示該索引相應的BGRAlpha的值,每一個分量占一個字節。如不設透明通道時。Alpha0。由於前面知道,本圖有256個顏色索引,因此N = 256

索引號就是所在行的行號,相應的顏色就是所在行的四個元素。

這裏截取一些數據來說明:

技術分享

索引:(藍。綠,紅,Alpha)

0號:(fefafd00)

1號:(fdf3fc00)

2號:(f4f3fc00)

3號:(fcf2f400)

4號:(f6f2f200)

5號:(fbf9f600) 等等。

一共同擁有256種顏色,每一個顏色占用4個字節。就是一共1024個字節,再加上前面的文件信息頭和位圖信息頭的54個字節加起來一共是1078個字節。也就是說在位圖數據出現之前一共同擁有1078個字節,與我們在文件信息頭得到的信息:文件頭到文圖數據區的偏移為1078個字節一致!

四、位圖數據

以下就是位圖數據了。每一個像素占一個字節。取得這個字節後。以該字節為索引查詢相應的顏色,並顯示到相應的顯示設備上就能夠了。

註意:由於位圖信息頭中的圖像高度是正數,所以位圖數據在文件裏的排列順序是從左下角到右上角。以行為主序排列的。

技術分享

也即我們見到的第一個像素60是圖像最左下角的數據。第二個人像素60為圖像最後一行第二列的數據。…一直到最後一行的最後一列數據,後面緊接的是倒數第二行的第一列的數據,依此類推。

假設圖像是24位或是32位數據的位圖的話,位圖數據區就不是索引而是實際的像素值了。以下說明一下,此時位圖數據區的每一個像素的RGB顏色陣列排布:

24RGB依照BGR的順序來存儲每一個像素的各顏色通道的值,一個像素的所有顏色分量值都存完後才存下一個下一個像素,不進行交織存儲。

32位數據依照BGRA的順序存儲,其余與24位位圖的方式一樣。

像素的排布規則與前述一致。

對齊規則

講完了像素的排列規則以及各像素的顏色分量的排列規則,最後我們談談數據的對齊規則。

我們知道Windows默認的掃描的最小單位是4字節,假設數據對齊滿足這個值的話對於數據的獲取速度等都是有非常大的增益的。

因此,BMP圖像順應了這個要求,要求每行的數據的長度必須是4的倍數,假設不夠須要進行比特填充(以0填充),這樣能夠達到按行的高速存取。

這時。位圖數據區的大小就未必是 圖片寬×每像素字節數×圖片高 能表示的了,由於每行可能還須要進行比特填充。

填充後的每行的字節數為:

技術分享,當中BPPBits Per Pixel)為每像素的比特數。

在程序中,我們能夠表示為:

int iLineByteCnt = (((m_iImageWidth * m_iBitsPerPixel) + 31) >> 5) << 2;

這樣。位圖數據區的大小為:

m_iImageDataSize = iLineByteCnt * m_iImageHeight;

我們在掃描完一行數據後。也可能接下來的數據並非下一行的數據,可能須要跳過一段填充數據:

skip = 4 - ((m_iImageWidth * m_iBitsPerPixel)>>3) & 3;

五、拾遺

至此,我們通過分析一個具體的位圖文件樣例具體地剖析了位圖文件的組成。須要註意的是:我們講的主要是PC機上的位圖文件的構成,對於嵌入式平臺,可能在調色板數據段與PC機的不同。如在嵌入式平臺上常見的16r5g6b5位圖實際上採用的掩模的方式而不是索引的方式來表示圖像。此時,在調色板數據段共同擁有四個部分,每一個部分為四個字節,實際表示的是彩色版規範。即:

第一個部分是紅色分量的掩模

第二個部分是綠色分量的掩模

第三個部分是藍色分量的掩模

第四個部分是Alpha分量的掩模(缺省為0

典型的調色板規範在文件裏的順序為為:

00F8 0000 E007 0000 1F00 0000 0000 0000

當中

00F8 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就能夠補齊每一個分量為一個字節,再把這三個字節按BGR組合,放入存儲器,就能夠轉換為24位標準BMP格式了。

這樣我們假設在位圖數據區有一個像素的數據在文件裏表示為02 F1。這個數據實際上應為F102:

r = (F102 AND F800) >> 8 = F0h = 240

g= (F102 AND 07E0)>> 3 = 20h = 32
  b=(F102 AND 001F) << 3 = 10h =16

至此我們就能夠顯示了。(本文結束)

參考資源:

1. wiki百科 bmp file format

http://en.wikipedia.org/wiki/BMP_file_format

2. gwwgle的專欄 BMP格式具體解釋 http://blog.csdn.net/gwwgle/archive/2009/11/06/4775396.aspx

3. 匿名 BMP格式圖像文件詳析http://www.thethirdmedia.com/pc/200407/20040722117029.shtm

4. Singler的專欄位圖文件(BMP)格式分析以及程序實現http://blog.csdn.net/yyfzy/archive/2006/06/10/785945.aspx


轉自:http://www.cnblogs.com/Matrix_Yao/archive/2009/12/02/1615295.html


FILE HEADER 實例圖解14 bytes

typedef struct {
/* type : Magic identifier,一般為BM(0x42,0x4d) */
unsigned short int type;
unsigned int size;/* File size in bytes,所有的檔案大小 */
unsigned short int reserved1, reserved2; /* 保留位 */
unsigned int offset;/* Offset to image data, bytes */
} FILEHEADER;

技術分享

  1. type:2 bytes。一般都是‘B‘ (0x42)、‘M‘ (0x4D)
  2. size:4 bytes,記錄該BMP檔的大小。0x436 = 1078 bytes
  3. reserved1:保留位,2 bytes
  4. reserved2:保留位,2 bytes
  5. offset:4 bytes。0x36 = 54 bytes

INFO HEADER 實例圖解40 bytes

typedef struct {
unsigned int size;/* Info Header size in bytes */
int width,height;/* Width and height of image */
unsigned short int planes;/* Number of colour planes */
unsigned short int bits; /* Bits per pixel */
unsigned int compression; /* Compression type */
unsigned int imagesize; /* Image size in bytes */
int xresolution,yresolution; /* Pixels per meter */
unsigned int ncolours; /* Number of colours */
unsigned int importantcolours; /* Important colours */
} INFOHEADER;

技術分享

  1. size:4 bytes,0x28 = 40 bytes。表示Info Header的大長度總共 40 bytes
  2. width:4 bytes。0x10 = 16,圖像寬度為16 pixel
  3. height:4 bytes。0x10 = 16,圖像高度為16 pixel
  4. planes:2 bytes,0x01 = 1。位元面數為1
  5. bits:2 bytes,0x20 = 32。每個pixel須要32bits
  6. compression:4 bytes。0代表不壓縮
  7. imagesize:4 bytes。0x400 = 1024 bytes。點陣圖資料大小為1024 bytes
  8. xresolution:4 bytes。水平解析度
  9. yresolution:4 bytes。垂直解析度
  10. ncolours:4 bytes,點陣圖使用的調色板顏色數
  11. importantcolours:4 bytes,重要的顏色數

RAW DATA 實例圖解

剛剛的File Header共14bytes,Info Header為40bytes,「imagesize」 = 1024 bytes,所以「14 + 40 + 1024 = 1078」, 即等於File Header中「size」的大小。

以下我僅僅提取部分的資料。反正所有的檔案,減去Header檔54位元組。剩下的就是點陣圖的資料。

技術分享

在Info Header中的「bits」為32 bits,故四個位元組一組。若24 bits。則三個位元組一組,樣例中的長寬各為16。以「Z」字型來看。一列則為16組,即16 X 4 = 64 bytes。註意的是。圖中是以A、B、C ~ …的讀取順序來講解,但實際上程序所讀取到的通常回是反過來的,即… ~ C、B、A。另外。下圖是以「BGRA」排列。

技術分享


BMP文件格式具體解釋