解析.bmp圖片的存放結構

來源:互聯網
上載者:User

以C:/WINDOWS/Blue Lace 16.bmp為例,簡要說明一下bmp圖片的結構。這張圖片是一張典型的4位、16色的bmp圖片,每台電腦上都應該有這張圖片。在說明之前請安裝好UltraEdit軟體以便察看bmp圖片的16進位值。

一個bmp圖片由3大部分組成:BITMAPFILEHEADER結構體,BITMAPINFO結構體,DIB資料區。其中DIB意思就是 Device-Independent Bitmap(裝置無關位元影像)。兩個結構體的定義如下:(注意Integer類型佔2個位元組,Long類型佔4個位元組)
Private Type BITMAPFILEHEADER    // 14 bytes
 bfType As Integer
 bfSize As Long
 bfReserved1 As Integer
 bfReserved2 As Integer
 bfOffBits As Long
End Type
Private Type BITMAPINFO
 bmiHeader As BITMAPINFOHEADER
 bmiColors As RGBQUAD
End Type
其中BITMAPINFO結構體中還有兩個子結構體,分別定義如下:
Private Type BITMAPINFOHEADER '40 bytes
 biSize As Long
 biWidth As Long
 biHeight As Long
 biPlanes As Integer
 biBitCount As Integer
 biCompression As Long
 biSizeImage As Long
 biXPelsPerMeter As Long
 biYPelsPerMeter As Long
 biClrUsed As Long
 biClrImportant As Long
End Type
Private Type RGBQUAD
 rgbBlue As Byte
 rgbGreen As Byte
 rgbRed As Byte
 rgbReserved As Byte
End Type

下面用UltraEdit開啟C:/WINDOWS/Blue Lace 16.bmp察看其16進位資料。
一個bmp檔案以BITMAPFILEHEADER結構體開始,BITMAPFILEHEADER的第1個屬性是bfType(2位元組),這裡恒定等於&H4D42。由於記憶體中的資料排列高位在左,低位在右,所以記憶體中從左往右看就顯示成(42 4D),所以在UltraEdit中頭兩個位元組顯示為(42 4D)就是這樣形成的,以後的資料都是這個特點,不再作重複說明。
BITMAPFILEHEADER的第2個屬性是bfSize(4位元組),表示整個bmp檔案的大小,這裡等於&H000004F8=1272位元組。
BITMAPFILEHEADER的第3個、第4個屬性分別是bfReserved1、bfReserved2(各2位元組),這裡是2個保留屬性,都為0,這裡等於&H0000、&H0000。
BITMAPFILEHEADER的第5個屬性是bfOffBits(4位元組),表示DIB資料區在bmp檔案中的位置位移量,這裡等於&H00000076=118,表示資料區從檔案開始往後數的118位元組開始。
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部分。
BITMAPINFOHEADER的第1個屬性是biSize(4位元組),表示BITMAPINFOHEADER結構體的長度,最常見的長度是40位元組,UltraEdit中可以看到緊接著的4個位元組等於&H00000028=40位元組。
BITMAPINFOHEADER的第2個屬性是biWidth(4位元組),表示bmp圖片的寬度,這裡等於&H00000030=48像素。

BITMAPINFOHEADER的第3個屬性是biHeight(4位元組),表示bmp圖片的高度,這裡等於&H00000030=48像素。
BITMAPINFOHEADER的第4個屬性是biPlanes(2位元組),表示bmp圖片的平面屬,顯然顯示器只有一個平面,所以恒等於1,這裡等於&H0001。
BITMAPINFOHEADER的第5個屬性是biBitCount(2位元組),表示bmp圖片的顏色位元,即24位元影像、32位元影像等等。這裡等於&H0004,表示該圖片為4位元影像。
BITMAPINFOHEADER的第6個屬性是biCompression(4位元組),表示圖片的壓縮屬性,bmp圖片是不壓縮的,等於0,所以這裡為&H00000000。
BITMAPINFOHEADER的第7個屬性是biSizeImage(4位元組),表示bmp圖片資料區的大小,當上一個熟悉biCompression等於0時,這裡的值可以省略不填,所以這裡等於&H00000000。
BITMAPINFOHEADER的第8個屬性是biXPelsPerMeter(4位元組),表示圖片X軸每米多少像素,可省略,這裡等於&H00000EC3=3779像素/米。
BITMAPINFOHEADER的第9個屬性是biYPelsPerMeter(4位元組),表示圖片Y軸每米多少像素,可省略,這裡等於&H00000EC3=3779像素/米。
BITMAPINFOHEADER的第10個屬性是biClrUsed(4位元組),表示使用了多少個色彩索引表,一般biBitCount屬性小於16才會用到,等於0時表示有2^biBitCount個色彩索引表,所以這裡仍等於&H00000000。
BITMAPINFOHEADER的第11個屬性是biClrImportant(4位元組),表示有多少個重要的顏色,等於0時表示所有顏色都很重要,所以這裡等於&H00000000。
至此BITMAPINFOHEADER結構體結束。

由於這個圖片到這裡還未到達DIB資料區的位移量,所以接下來的部分是RGBQUAD結構體。RGBQUAD結構體由4個位元組型資料群組成,所以一個RGBQUAD結構體只佔用4位元組空間,從左至右每個位元組依次表示(藍色,綠色,紅色,未使用)。舉例的這個圖片我數了數總共有16個RGBQUAD結構體,由於該圖片是4位元影像,2^4正好等於16,所以它把16種顏色全部都枚舉出來了,這些顏色就是一個色彩索引表。色彩索引表編號從0開始,總共16個顏色,所以編號為0-15。從UltraEdit中可以看到按照順序,這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個像素。
從UltraEdit中可以看到,DIB資料區第一個位元組是&H44,16進位正好是將2進位數每4個一組書寫的,跟4bit圖片正好吻合,所以&H44表示兩個像素,高位的4表示第一個像素,低位的4表示第二個像素。這裡的4不是表示RGB顏色,而是表示色彩索引號為4,由於索引號從0開始編號的,所以4表示索引表中第5個顏色,從附圖中可以看到索引號為4的是藍色。這是第一位元組,表示的是圖片左下角開始2個像素,如果有 PhotoShop開啟這個圖片可以看到,左下角2個像素取出來的顏色RGB值正好等於索引表中第5個顏色的RGB值。後面的DIB資料以此類推。

至此一個bmp圖片就全部解析完了,根據這些資訊就可以完整的繪製一張bmp圖片來。

所以要顯示一個bmp位元影像特別方便,特別是24位、32位元影像片,後面的DIB資料區就是按照(B,G,R)或(B,G,R,A)順序排列的,只要根據 DIB位移量找到DIB資料區,裝入一個buffer中儲存,前面BITMAPINFO結構體也有了,直接用CopyMemory複製過來,然後就可以調用CreateDIBSection函數建立一個hBitMap出來,把這個hBitMap選入DC中,就可以用BitBlt或StretchBlt向目標DC中複製資料,把bmp圖片就在繪圖區顯示出來了。

如果你還不明白,還有:

1. BMP檔案組成
BMP檔案由檔案頭、位元影像資訊頭、顏色資訊和圖形資料四部分組成。
2. BMP檔案頭
BMP檔案頭資料結構含有BMP檔案的類型、檔案大小和位元影像起始位置等資訊。

其結構定義如下:

typedef struct tagBITMAPFILEHEADER
{
WORDbfType; // 位元影像檔案的類型,必須為BM
DWORD bfSize; // 位元影像檔案的大小,以位元組為單位
WORDbfReserved1; // 位元影像檔案保留字,必須為0
WORDbfReserved2; // 位元影像檔案保留字,必須為0
DWORD bfOffBits; // 位元影像資料的起始位置,以相對於位元影像
// 檔案頭的位移量表示,以位元組為單位
} BITMAPFILEHEADER;

3. 位元影像資訊頭

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;

4. 顏色表
顏色表用於說明位元影像中的顏色,它有若干個表項,每一個表項是一個RGBQUAD類型的結構,定義一種顏色。RGBQUAD結構的定義如下:

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;

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

當biBitCount=1時,8個像素佔1個位元組;
當biBitCount=4時,2個像素佔1個位元組;
當biBitCount=8時,1個像素佔1個位元組;
當biBitCount=24時,1個像素佔3個位元組;
Windows規定一個掃描行所佔的位元組數必須是
4的倍數(即以long為單位),不足的以0填充,
一個掃描行所佔的位元組數計算方法:
DataSizePerLine= (biWidth* biBitCount+31)/8;
// 一個掃描行所佔的位元組數
DataSizePerLine= DataSizePerLine/4*4; // 位元組數必須是4的倍數
位元影像資料的大小(不壓縮情況下):
DataSize= DataSizePerLine* biHeight;

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.