數字影象處理之點陣圖在計算機中的儲存結構
一張點陣圖包含了許許多多的畫素點,每個畫素點有不同的顏色。由此構成了五彩斑斕的點陣圖影象,
然而正是因為由畫素點這一基本元素構成,所以在放大圖片的時候,人眼便能夠區分一個一個
的畫素點,進而造成點陣圖失真。本文主要介紹點陣圖檔案在計算機記憶體中的儲存形式。
當然這裡還要介紹兩種點陣圖:DDB,DIB
DDB(device dependent bitmap),為裝置相關點陣圖,這種點陣圖與具體的輸出裝置相關。
在這種點陣圖的結構中沒有儲存調色盤資訊。因為在輸出顯示時是呼叫系統的調色盤。這
便是這種點陣圖的侷限性。
DIB(device independent bitmap),為裝置無關點陣圖。這種點陣圖與具體的輸出無關。
其結構中包含四個部分檔案頭,資訊頭,調色盤,資料區域。所以下文均是介紹這種點陣圖
的結構資訊。
BMP檔案由檔案頭,點陣圖資訊頭,顏色資訊和影象資料四部分組成。
這wingdi.h中對點陣圖檔案頭和資訊頭也作了相應的結構體定義。
//對點陣圖檔案頭的定義
typedef struct tagBITMAPFILEHEADER { WORD bfType; //點陣圖檔案的型別, 必須為BM 對應的16進製為0x4D42 DWORD bfSize; //點陣圖檔案的大小,位元組單位 WORD bfReserved1; //點陣圖檔案保留字,必須為0 WORD bfReserved2; //點陣圖檔案保留字,必須為0 DWORD bfOffBits; //為從檔案頭到實際影象資料區域的長度,即前三個結構長度之和。 } BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
檔案頭長度固定為14個位元組,其中WORD佔兩個位元組,DWORD佔四個位元組。
//對點陣圖資訊頭的定義
typedef struct tagBITMAPINFOHEADER{ DWORD biSize; //指定該資訊頭所佔位元組數,固定佔40個位元組 LONG biWidth; //點陣圖的寬度,單位為畫素 LONG biHeight; //點陣圖的高度,單位為畫素 WORD biPlanes; //目標裝置的位面數,必須是1 WORD biBitCount; //每個畫素所佔的位數 DWORD biCompression; //點陣圖的壓縮方式,大多數情況下為0,也可能是BI_RGB DWORD biSizeImage; //點陣圖的大小,位元組單位 LONG biXPelsPerMeter; //水平解析度,水平每米所佔畫素個數 LONG biYPelsPerMeter; //垂直解析度,垂直每米所佔畫素個數 DWORD biClrUsed; //指出該點陣圖中實際使用的色彩數,若為0,則為2^biBitCount DWORD biClrImportant; //點陣圖顯示中比較重要的顏色數,若為0,則所有顏色都是重要的。 } BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;
資訊頭固定長度為40個位元組,其中word佔兩個位元組,Dword和Long各佔四個位元組。
//對顏色表的定義(針對一個畫素而定義)
typedef struct tagRGBQUAD {
BYTE rgbBlue; //該顏色的藍色分量(0-255)
BYTE rgbGreen; //該顏色的綠色分量(0-255)
BYTE rgbRed; //該顏色的紅色分量(0-255)
BYTE rgbReserved; //保留值
} RGBQUAD;
顏色表中RGBQUAD結構資料的個數有biBitCount來確定:
當biBitCount=1,4,8時,分別有2,16,256個表項;
當biBitCount=24時,沒有顏色表項。
點陣圖資訊頭和顏色表組成點陣圖資訊,BITMAPINFO結構定義如下:
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader; // 點陣圖資訊頭
RGBQUAD bmiColors[1]; // 顏色表
} BITMAPINFO;
// 點陣圖資料
點陣圖資料記錄了點陣圖的每一個畫素值,記錄順序是在掃描行內是從左到右,掃描行之間是從下到上。點陣圖的一個畫素值所佔的位元組數:
當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;
下面用hexeditor16位編輯器對一張點陣圖的儲存結構進行說明:
上圖則是對蘋果點陣圖用16位編輯器開啟後的儲存結構
前14個位元組為點陣圖檔案頭:
0-1位元組:42 4D 點陣圖型別BM
2-5位元組:36 A8 05 00 點陣圖檔案大小為實際上應該0x0005A836 總共為370742個位元組
6-7位元組:00 00 保留字 0
8-9位元組:00 00 保留字 0
10-13位元組:36 00 00 00點陣圖檔案頭到資料的偏移,實際上為00 00 00 36,例項偏移為54位元組。
而檔案頭14位元組,資訊頭40位元組一共54位元組。那麼顏色表呢?顏色表為0.是的,顏色表為0
說明該點陣圖使用24位真彩色,而非索引調色盤。故點陣圖資訊結構中不包括調色盤。
第14到53這40個位元組為點陣圖資訊頭:
14-17位元組:28 00 00 00實際上為0x00000028=40標識該資訊頭結構所佔位元組數。
18-21位元組:55 01 00 00實際上為0x00000155=341標識該點陣圖的寬度,單位為畫素
22-25位元組:00 00 01 6A實際上為0x0000016A=362標識該點陣圖的高度,單位為畫素
26-27位元組:01 00實際上為0x0001=1標識目標裝置的位面數,強制為1
28-29位元組:18 00實際上為0x0018=24標識每個畫素所佔的位數。因為每個畫素由RGB三種
顏色分量組成,且每個分量佔一個位元組。而每個畫素佔24.故該圖使用了RGB三種
分量的所有組合,為24色真彩色影象
30-33位元組:00 00 00 00實際上為0,標識點陣圖壓縮型別
34-37位元組:00 A8 05 00實際上為0x0005A800=1448,表示為點陣圖大小,位元組為單位
38-41位元組:C4 0E 00 00實際上為0x00000EC4=3780,表示水平每米所佔的畫素,即水平解析度
42-45位元組:C4 0E 00 00實際上為0x00000EC4=3780,表示垂直每米所佔的畫素,即垂直解析度
46-49位元組:00 00 00 00表示實際使用的顏色數。若為0,則標識為真彩色點陣圖,使用的顏色種類為2^biBitCount
50-53位元組:00 00 00 00表示點陣圖顯示中比較重要的顏色數.若為0,則標識點陣圖中所以的顏色都重要
而點陣圖影象資料的掃描讀取方式則是以從左到右,從下到上的方式進行。而本圖又為24位真彩圖,故每個畫素
佔三個位元組。故每次從最後一行開始從左到右。一次性讀三個位元組代表一個畫素的顏色資料值。
而對應非24為真色圖:
當biBitCount=16時,兩個位元組代表一個畫素點的顏色資料值。此時存在顏色表,顏色表的種類為2^16種。所以在
影象中儲存此調色盤,在顯示點陣圖時呼叫此調色盤的索引值以兩個位元組代表一個畫素點進行顯示。
當biBitCount=8時,一個位元組代表一個畫素點的顏色資料值。此時存在顏色表,顏色表的種類為2^8=256種。所以在
影象中儲存此調色盤,在顯示點陣圖時呼叫此調色盤的索引值以一個位元組代表一個畫素點進行顯示。
當biBitCount=4時,半個位元組代表一個畫素點的顏色資料值。此時存在顏色表,顏色表的種類為2^4=128種。所以在
影象中儲存此調色盤,在顯示點陣圖時呼叫此調色盤的索引值以半個位元組代表一個畫素點進行顯示,即一個位元組表示兩個
畫素點。
當biBitCount=2時,個位元組代表一個畫素點的顏色資料值。此時存在顏色表,顏色表的種類為2^2=4種。所以在
影象中儲存此調色盤,在顯示點陣圖時呼叫此調色盤的索引值以四分之一個位元組代表一個畫素點進行顯示,即一個位元組表示
四分之一個畫素點。
當biBitCount=1時,此時為灰度影象。僅黑白兩種顏色。一個位元組可標識八個畫素點。
所以不能看出顏色深度越神,所儲存的調色盤越大,儲存需要的記憶體空間越大。
至此,本文關於裝置無關點陣圖的結構已經作了詳解的解釋,相信讀者在看完此文後對點陣圖結構有個大致瞭解,
以至於在後續影象處理的應用中有所幫助。
作者水平有限,難免有錯誤或者不清除的地方,希望讀者批評指正大家共同進步。
轉載請註明文章作者:小劉