Microsoft Windows
3.0中的畫筆(Paintbrush)工具軟體為使用者提供了強有力的圖形繪製和編輯功能,例形的旋轉、縮放、拼接等[1].利用這些功能可以非常方便地產生所需要的各種複雜的彩色畫面.產生的畫面以位元影像檔案的格式儲存在磁碟上.以此檔案為資源,在Mircosoft
Windows 3.0的支援下,可以在任何需要的時候在任何裝置上再現該畫面[2].
在實際工作中經常遇到這樣的問題:在利用畫筆工具軟體產生了所需的畫面之後,能否脫離開Windows的支援,在其它系統中使用這些畫面呢?解決這一問題的關鍵在於瞭解位元影像檔案的記錄格式.只要瞭解位元影像檔案的記錄格式,這一問題是容易解決的.基於這一目的,文本將詳細介紹Mircosoft
Windows 3.0位元影像檔案的記錄格式.
Microsoft Windows 3.0位元影像檔案(以.BMP為副檔名)由以下三個部分組成:
* 位元影像檔案頭(BITMAPFILEHEADER) 資料結構
* 位元影像資訊(BITMAPINFO)資料結構
* 位元影像陣列
一. 位元影像檔案頭的結構
位元影像檔案頭資料結構含有位元影像檔案的類型、大小和列印格式等資訊.在Windows.h中對其進行了定義:
Typedef struct tagBITMAPFILEHEADER
{
WORD bfType; /*位元影像檔案的類型,必須為BM. */
DWORD bfSize; /*位元影像檔案的大小,以位元組為單位. */
WORD bfReserved1; /*位元影像檔案保留字,必須為0. */
WORD bfReserved2; /* 位元影像檔案保留字,必須為0. */
DWORD bfoffbits; /*位元影像陣列的起始位置,以相對於位元影像檔案*/
/*頭的位移量表示,以位元組為單位.*/
}BITMAPFILEHEADER;
二. 位元影像資訊的結構
位元影像資訊資料結構含有位元影像檔案的尺寸和顏色等資訊.在Windows.h中對其進行了定義:
typedef stuc tagBITMAPINFO
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColor[];
}BITMAPINFO;
1.bmiHeader是一個位元影像資訊頭(BIMMAPINFOHEADER)類型的資料結構,用於說明位元影像的尺寸.
BITMAPINFOHEADER的定義:
typedef struct tagBITMAPINFOHEADER
{
DWORD BiSize; /*bmiHeader的長度,以位元組為單位.*/
DWORD biWidth; /*位元影像的寬度,以象素為單位.*/
DWORD biHight; /*位元影像的高度,以象素為單位.*/
WORD biPlanes; /*目標裝置的層級,必須為1.*/
WORD biBitCount; /*每個象素所需的位元,必須是1(單色).*/
/*4(16色),8(256色),或24(2^24色)之一. */
DWORD biCompress; /*位元影像的壓縮類型,必須是0(不壓縮).*/
/*1(BI_RLE8壓縮類型)或2(BI_RLE4壓縮類型)之一.*/
DWORD biSizeImage; /*位元影像的大小,以位元組為單位.*/
DOWRD biXPeIsPerMeter;
/*位元影像的目標裝置水平解析度,以每米象素數為單位.*/
DWORD biYPeIsPerMeter;
/*位元影像的目標裝置水平解析度,以每米象素數為單位.*/
DWORD biCIrUsed;
/*位元影像實際使用的顏色表中的顏色變址數,詳見[3].*/
DWORD biCIrImprotant;
/*位元影像顯示過程中被認為重要顏色的變址數,詳見[3]*/
}BITMAPINFOHEADER;
2.
bimColor[]是一個顏色表,用於說明位元影像中的顏色.它有若干個表項,每一表項是一個RGBQUAD類型的結構,定義了一種顏色.RGBQUAD的定義:
Typedef tagRGBQUAD
{
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
}RGBQUAD;
在RGBQUAD定義的顏色中,藍色的亮度由rgbBlue來定,綠色的亮度由rgbGreen來定,紅色的亮度由rgbred來定,rgbRserved必須為0.
例如: 若某表項為00,00,FF,00, 那麼它定義的顏色為純紅色.
bimColor[]表項的個數由bmBitCount來定:
當bmBitCount=1,4,8時,
bimColor[]分別有2,16,256個項.若某點的象素值為n,則該象素的顏色為bimColor[]所定義的顏色.
當bmBitCount=24時,
bimColor[]的表項為空白.位元影像陣列的每3個位元組代表一個像素,這3個位元組直接定義了象素顏色中藍、綠、紅的相對亮度,因此省去了bimColor[]顏色表.
三. 位元影像陣列的結構
位元影像陣列記錄了位元影像的每一個象素值.在產生位元影像檔案時,Windows從位元影像的左下角開始(即從左至右從上到下)漸進式掃描位元影像,將位元影像的象素值一一記錄下來.這些記錄象素值的位元組組成了位元影像陣列.
位元影像陣列有壓縮和非壓縮兩種儲存格式.
1.非壓縮格式
在非壓縮格式中,位元影像的每一點的象素值值一對應於位元影像陣列的若干位(bit),位元影像陣列的大小由位元影像的寬度,高度及位元影像的顏色數(bitBITCount)決定.
(1) 位元影像掃描行與位元影像陣列的關係
設記錄一個掃描行的象素值需n個位元組,則:
位元影像陣列的0~n-1個位元組記錄了位元影像的第一個掃描行的象素值;位元影像陣列的n~2n-1個位元組記錄了位元影像的第二個掃描行的象素值;依些類推,位元影像陣列的(m-1)*n~m*n-1個位元組記錄了位元影像的第m個掃描行的象素值.位元影像陣列的大小為n*biHight.
當(biWith*bitBITCount)mod32=0時:
n=(biWith*biBITCount)/8
當(biWith*bitBITCount)mod32!=0時:
n=(biWith*biBITCount)/8+4
上式中的+4而不+1的原因是為了使一個掃描行的象素值佔用位元影像陣列的位元組數為4的倍數(Windows規定其必須在long邊界結束),不足的位用0填充.
(2)位元影像象素值與位元影像陣列的關係(以第m掃描行為例)
設記錄第m個掃描行的象素值的n個位元組分別為:a0,a1,a2,...,則:
當bitBITCount=1時:a0的D7位記錄了位元影像的第m個掃描行的第1個象素值,D6位記錄了位元影像的第m個掃描行的第1個象素值,...,
D0位記錄了位元影像的第m個掃描行的第8個象素值,
a1的D7位記錄了位元影像的第m個掃描行的第9個象素值,D6位記錄了位元影像的第m個掃描行的第10個象素值,...
當bitBITCount=4時:a0的D7-D4位記錄了位元影像的第m個掃描行的第1個象素值,D3-D0位記錄了位元影像的第m個掃描行的第2個象素值,
a1的D7-D4位記錄了位元影像的第m個掃描行的第3個象素值,...
當bitBITCount=8時:a0的D7-D4位記錄了位元影像的第m個掃描行的第1個象素值,a1記錄了位元影像的第m個掃描行的第2個象素值,...
當bitBITCount=24時:a0,a1,a2位記錄了位元影像的第m個掃描行的第1個象素值,a3,a4,a5記錄了位元影像的第m個掃描行的第2個象素值,...
位元影像其它掃描行的象素值與位元影像陣列的對應關係與此類似.
2. 壓縮格式
Windows支援BI_RLE8及BI_RLE4壓縮位元影像儲存格式,減少了位元影像陣列所佔用的磁碟空間.
(1)BI_RLE8壓縮格式
當bicompression=1時,位元影像檔案採用此壓縮編碼格式.壓縮編碼以兩個位元組為基本單位.其中第一個位元組規定了用兩個位元組指定的顏色重複畫出的連續象素的數目.
例如,壓縮編碼05
04表示從當前位置開始連續顯示5個象素,這5個象素的象素值均為04.
在第一位元組為零時,第二位元組有特殊的含義:
0: 行末
1: 圖末
2:
轉義後面的兩個位元組,用這倆個位元組分別表示下一個象素從當前位置開始的水平位移和垂直位移.
n(0x03<n<xff):轉義後面的n個位元組,其後的n象素分別用這n個位元組所指定的顏色畫出.注意:實際編碼時必須保證後面的位元組數是4的倍數.不足的位用0補齊.
例如,壓縮編碼00 00表示開始新的掃描行,壓縮編碼00
01表示壓縮位元影像陣列結束,壓縮編碼00 02 05
01表示從當前位置開始向右移5個象素,向下移1行後再畫下一個象素,壓縮編碼00 03
05 06 07
00表示從當前位置開始連續畫3個象素,3個象素的顏色分別為05,06,07,最後面的00是為了保證被轉義的位元組數是4的倍數.
(2)BI_RLE4壓縮格式
當bicompression=4時,位元影像檔案採用此後壓縮編碼格式.BI_RLE4的壓縮編碼格式與BI_RLE8的編碼方式類似,維一的不同是:BI_RLE4的一個位元組包含了兩個象素的顏色.
當連續顯示時,第一個象素按位元組高四位規定的顏色畫出,第二個象素按位元組低似位規定的顏色畫出,第三個象素按位元組高四位規定的顏色畫出,...,直到所有象素都畫出為止.
例如:壓縮編碼06
67表示從當前位置開始連續畫5個象素,5個象素的顏色分別為6,7,6,7,6.
壓縮編碼00 04 45 67 00表示從當前位置開始連續畫4個象素,
4個象素的顏色分別為4,5,6,7.最後面的00是為了保證被轉義的位元組數是4的倍數.
四. 執行個體分析
為了更清楚地說明位元影像檔案的格式,下面對儲存一個簡單劃面(如附圖所示)的位元影像檔案進行具體分析.畫面的底色是藍色,上面的直線的顏色是黃色,下面的直線的顏色是紅色.位元影像以16色位映象方式儲存[1],檔案名稱為DEMO.BMP.用debug分析位元影像檔案的內容如下:
186C:0100 42 4D 3E 01 00 00 00 00-00 00 76 00 00 00 28 00
186C:0110 00 00 26 00 00 00 0A 00-00 00 01 00 04 00 00 00
186C:0120 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
186C:0130 00 00 00 00 00 00 00 00-00 00 00 00 80 00 00 80
186C:0140 00 00 00 80 80 00 80 00-00 00 80 00 80 00 80 80
186C:0150 00 00 80 80 80 00 40 40-40 00 00 00 FF 00 00 FF
186C:0160 00 00 00 FF FF 00 FF 00-00 00 FF 00 FF 00 FF
FF
186C:0170 00 00 FF FF FF 00 CC CC-CC CC CC CC CC CC CC CC
186C:0180 CC CC CC CC CC CC CC CC-CC 00 CC CC CC CC CC CC
186C:0190 CC CC CC CC CC CC CC CC-CC CC CC CC CC CC CC 99
186C:01A0 99 99 99 99 99 99 99 99-99 99 99 99 99 99 99 CC
186C:01B0 CC 00 CC CC CC CC CC CC-CC CC CC CC CC CC CC CC
186C:01C0 CC CC CC CC CC 00 CC CC-CC CC CC CC CC CC CC CC
186C:01D0 CC CC CC CC CC CC CC CC-CC 00 CC CB BB BB BB BB
186C:01E0 BB BB BB BB BB BB BB BB-BB BB BB BC CC 00 CC CC
186C:01F0 CC CC CC CC CC CC CC CC-CC CC CC CC CC CC CC CC
186C:0200 CC 00 CC CC CC CC CC CC-CC CC CC CC CC CC CC CC
186C:0210 CC CC CC CC CC 00 CC CC-CC CC CC CC CC CC CC CC
186C:0220 CC CC CC CC CC CC CC CC-CC 00 CC CC CC CC CC CC
186C:0230 CC CC CC CC CC CC CC CC-CC 00 CC CC CC 00 00 00
(0,0)
┌───────────┐
│(3,4) (黃色) (35,4)│
│_____________________ │
│ │
│ │
│(2,7) (紅色) (34,7)│
│_____________________ │
└───────────┘
(38,10)
附圖 執行個體畫面
其中:
0100-010D是BITMAPFILEHEADER資料結構,它說明了如下的資訊:位元影像檔案共318B
(bfSize=0x013E),位元影像陣列從0176處開始(bfoffBits=0x76).
010E-0135是BITMAPFILEHEADER資料結構,它說明了如下的資訊:BITMAPFILEHEADER共28B(biSize=0x28),位元影像的大小為38X10(biWith00x26,
biHight=0x0A,以象素為單位)
位元影像陣列的每四位表示一個象素,位元影像有16種顏色,
bmiColor[]有16個表項(bitBITCount=4),位元影像採用非壓縮儲存方式(bitCompression=0);
0136-0175是bmiColor[]顏色表,每四個位元組定義一種顏色,共64B,定義了16種顏色.其中第九個表項(015A-015D)定義了紅色,第11表項(0162-0165)定義了黃色,第12個表項(0166-0169)定義了藍色.
0176-023D是位元影像陣列,位元影像每個掃描行有38個象素,對應位元影像陣列中的20個位元組,其中第20個位元組被填0,以保證位元組數是4的倍數.黃線在位元影像的第6掃描行,此行對應位元影像陣列的01DA-01ED位元組,紅線在位元影像的第3行掃描,此行對應位元影像陣列的0192-01B1位元組,位元影像共有10個掃描行.