BMP檔案結構

magic_yang5發表於2013-12-20

BMP檔案結構

BMP檔案由4部分組成:點陣圖檔案頭(bitmap-file header)

  1. 點陣圖資訊頭(bitmap-information header)

  2. 顏色表(color table)

  3. 顏色點陣資料(bits data)

24位真彩色點陣圖沒有顏色表,所以只有1、2、4這三部分。

用UltraEdit開啟MyBmp.bmp,可以看到這個檔案的全部資料如下圖所示:

點陣圖檔案頭

其結構定義如下:

typedef struct tagBITMAPFILEHEADER{

 WORDbfType; // 點陣圖檔案的型別,必須為BM
DWORD bfSize; // 點陣圖檔案的大小,以位元組為單位
WORDbfReserved1; // 點陣圖檔案保留字,必須為0
WORDbfReserved2; // 點陣圖檔案保留字,必須為0
DWORD bfOffBits; // 點陣圖資料的起始位置,以相對於點陣圖
// 檔案頭的偏移量表示,以位元組為單位
} BITMAPFILEHEADER;

 

點陣圖檔案頭分4部分,共14位元組:

名稱 佔用空間 內容 實際資料
bfType 2位元組 標識,就是“BM”二字 BM
bfSize 4位元組 整個BMP檔案的大小 0x50(80)
bfReserved1/2 4位元組 保留字,沒用 0
bfOffBits 4位元組 偏移數,即 點陣圖檔案頭+點陣圖資訊頭+調色盤 的大小 0x36(54)

 

注意,Windows的資料是倒著唸的,這是PC電腦的特色。如果一段資料為50 1A 25 3C,倒著念就是3C 25 1A 50,即0x3C251A50。因此,如果bfSize的資料為50 00 00 00,實際上就成了0x00000050,也就是0x50。

點陣圖資訊頭

BMP點陣圖資訊頭資料用於說明點陣圖的尺寸等資訊。


typedef struct tagBITMAPINFOHEADER{
DWORD biSize; // 本結構所佔用位元組數
LONGbiWidth; // 點陣圖的寬度,以畫素為單位
LONGbiHeight; // 點陣圖的高度,以畫素為單位
WORD biPlanes; // 目標裝置的級別,必須為1
WORD biBitCount// 每個畫素所需的位數,必須是1(雙色),
// 4(16色),8(256色)或24(真彩色)之一
DWORD biCompression; // 點陣圖壓縮型別,必須是 0(不壓縮),
// 1(BI_RLE8壓縮型別)或2(BI_RLE4壓縮型別)之一
DWORD biSizeImage; // 點陣圖的大小,以位元組為單位
LONGbiXPelsPerMeter; // 點陣圖水平解析度,每米畫素數
LONGbiYPelsPerMeter; // 點陣圖垂直解析度,每米畫素數
DWORD biClrUsed;// 點陣圖實際使用的顏色表中的顏色數
DWORD biClrImportant;// 點陣圖顯示過程中重要的顏色數
} BITMAPINFOHEADER;

 

點陣圖資訊頭共40位元組:

名稱 佔用空間 內容 實際資料
biSize 4位元組 點陣圖資訊頭的大小,為40 0x28(40)
biWidth 4位元組 點陣圖的寬度,單位是畫素 2
biHeight 4位元組 點陣圖的高度,單位是畫素 3
biPlanes 2位元組 固定值1 1
biBitCount 2位元組 每個畫素的位數
1-黑白圖,4-16色,8-256色,24-真彩色
0x18(24)
biCompression 4位元組 壓縮方式,BI_RGB(0)為不壓縮 0
biSizeImage 4位元組 點陣圖全部畫素佔用的位元組數,BI_RGB時可設為0 0x1A
biXPelsPerMeter 4位元組 水平解析度(畫素/米) 0xB12(2834)
biYPelsPerMeter 4位元組 垂直解析度(畫素/米) 0xB12(2834)
biClrUsed 4位元組 點陣圖使用的顏色數
如果為0,則顏色數為2的biBitCount次方
0
biClrImportant 4位元組 重要的顏色數,0代表所有顏色都重要 0

 

作為真彩色點陣圖,我們主要關心的是biWidth和biHeight這兩個數值,兩個數值告訴我們影象的尺寸。biSize,biPlanes,biBitCount這幾個數值是固定的。想偷懶的話,其它的數值可以一律用0來填充。

顏色表

typedef struct tagRGBQUAD {
BYTErgbBlue;// 藍色的亮度(值範圍為0-255)
BYTErgbGreen; // 綠色的亮度(值範圍為0-255)
BYTErgbRed; // 紅色的亮度(值範圍為0-255)
BYTErgbReserved;// 保留,必須為0
} RGBQUAD;
顏色表中RGBQUAD結構資料的個數有biBitCount來確定:
當biBitCount=1,4,8時,分別有2,16,256個表項;
當biBitCount=24時,沒有顏色表項。
點陣圖資訊頭和顏色表組成點陣圖資訊,BITMAPINFO結構定義如下:
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader; // 點陣圖資訊頭
RGBQUAD bmiColors[1]; // 顏色表
} BITMAPINFO;

24位真彩色點陣圖沒有顏色表。要想在Photoshop中建立有顏色表的BMP影象,選擇影象>模式>索引顏色;要想檢視顏色表,選擇影象>模式>顏色表。本文為了簡化,只討論24位真彩色點陣圖。

顏色點陣資料

點陣圖全部的畫素,是按照自下向上,自左向右的順序排列的。

RGB資料也是倒著唸的,原始資料是按B、G、R的順序排列的。

你應該注意到圖中用黑色框起來的00 00了,在每行顏色的末尾新增的兩個0位元組,是為了行補位。為什麼要行補位呢?因為32位的Windows作業系統處理4個位元組(32位)的速度比較快,所以BMP的每一行顏色佔用的位元組數規定為4的整數倍。MyBmp.bmp中一行顏色有兩個畫素,共佔用6位元組,如果要補齊4*2=8位元組,就要再加兩個0位元組。

行補位的公式為:widthBytes = (width*biBitCount+31)/32*4

舉一個例子,對於2色圖,如果圖象寬是31,則每一行需要31位儲存,合3個位元組加7位,因為位元組數必須是4的整倍數,所以應該是4,而此時的Width=31,biBitCount=1,widthbytes=4,和我們設想的一樣。再舉一個256色的例子,如果圖象寬是31,則每一行需要31個位元組儲存,因為位元組數必須是4的整倍數,所以應該是32,而此時的Width=31,biBitCount=8,widthbytes=(31*8+31)/32*4=8(取整)*4=32

對於上圖的例子中,計算得8,故六個位元組後加上兩個位元組。

 

點陣圖資料記錄了點陣圖的每一個畫素值,記錄順序是在掃描行內是從左到右,掃描行之間是從下到上。點陣圖的一個畫素值所佔的位元組數:

當biBitCount=1時,8個畫素佔1個位元組;
當biBitCount=4時,2個畫素佔1個位元組;
當biBitCount=8時,1個畫素佔1個位元組;
當biBitCount=24時,1個畫素佔3個位元組;

 

Phtoshop在檔案的末尾還補充了兩個0位元組,好像是要整體補位。不過我看過的BMP資料中都沒有提到還要整體補位的,其它軟體生成的BMP檔案也沒有整體補位的,這看起來像是Adobe的獨創,不知道目的何在。

Photoshop和Windows的BMP檔案比較

用Photoshop儲存的MyBmp.bmp:

經Windows畫圖轉存過的BMP檔案:

可以看出Windows的BMP檔案最後少了兩個0位元組,沒有整體補位。bfSize(檔案大小),biSizeImage(全部畫素大小)也相應地減去2。

 

原文出自 http://blog.csdn.net/sjzlxd/article/details/3923907,轉到這只是為了方便自己學習。。。

 

相關文章