一、BMP圖片的格式分析
1、BMP文件的大致組成
BMP文件的數(shù)據(jù)由四個部分組成:位圖文件頭部、位圖信息頭部、彩色表和圖像數(shù)據(jù)陣列字節(jié)。其中彩色表不是必須的,比如24位真彩色位圖就沒有彩色表。
(1)位圖文件頭部的組成(前面14個字節(jié))

(2)位圖信息頭部的組成(從14字節(jié)開始,14-53共40個字節(jié))

(3)下面以一個文件的分解為例,加深對各個分量的理解。
第一個文件為 160x128,24位真彩色,用Ultraedit獲得其頭部如下:

分析的信息填入上面表格的第三欄和第四欄。
對于BMP最重要的幾個信息如上表用紅色標注出來的。
文件頭14個字節(jié),主要是“BM”標注,文件大小等于61994個字節(jié),最重要的是指出了圖像數(shù)據(jù)的偏移等于54字節(jié)。
信息頭最主要的信息時位圖像素寬度等于160字節(jié),位圖像素高度等于128字節(jié),每個像素占據(jù)24位(也就是3個字節(jié))。圖像數(shù)據(jù)總共占用的字節(jié)數(shù)等于= 160 x 128 x 3 = 61440字節(jié),再加上頭部54字節(jié),就是整個BMP圖片文件的大小 61494個字節(jié)。
(4)單色BMP格式
黑白圖,每個像素只占一位,而顏色表總共有兩項,占8個字節(jié)。故圖像數(shù)據(jù)區(qū)的開始是 0x36 + 8 = 0x3E字節(jié)。
顏色表總是從0x36=54字節(jié)開始。
00000000代表黑色,00FFFFFF代表白色。比如F0這樣一個字節(jié),實際表示八個像素,前面四個胃白色,后面四個像素為黑色。
(5)16色BMP格式
16個顏色,每個像素占據(jù)4位,顏色表總共16項,占據(jù)64個字節(jié),故數(shù)據(jù)區(qū)是從 0x36 + 0x40 = 0x76字節(jié)開始。
(6)256色BMP格式
256個顏色,每個顏色占據(jù)8位,顏色表總共256項,占據(jù) 256 x 4 = 1024字節(jié)。故圖像數(shù)據(jù)區(qū)開始是 第0x36 + 0x400 = 0x436字節(jié)。
(7)BMP圖片的重要特征
數(shù)據(jù)區(qū)里的數(shù)據(jù)是線性的,行主序,依次是 點一的B值,點一的G值,點一的R值,點二的B值,點二的G值,點二的R值,等等,需要注意的是,Windows中普遍采用了行倒向掃描的約定,即,BMP文件中原點在左下角,圖像矩陣數(shù)組第一行實際是圖片的最后一行。
還有一點也需要注意:Windows要求每一行的數(shù)據(jù)的長度必須是4Bytes的整數(shù)倍,如果不是,要以值為0的字節(jié)補充,如果讀取的時候不處理,會得到一個傾斜的圖像。如一個
2、讀取BMP文件的思路
(1)圖像信息結(jié)構(gòu)體
建立一個BMPInfo結(jié)構(gòu)體,主要包括 圖像數(shù)據(jù)區(qū)偏移DataOff、彩色表偏移ColorOff、像素寬度PixWidth、像素高度PixHeight、每像素位數(shù)BitPerPix、是否壓縮Compressed、圖像每行字節(jié)數(shù)BytePerRow=每像素位數(shù) * 寬度/8,補滿為4的整數(shù)倍。(主要是由于每一行的數(shù)據(jù)的長度必須是4Bytes的整數(shù)倍,可能出現(xiàn)0填充情況)。
(2)如何讀取指定行、指定列的像素
U32 GetPixel (&BMPINFO, Row,Col)
首先要定位行(相對高度而言)首的偏移,相對于數(shù)據(jù)區(qū)的偏移計算公式是(Height – Row )* BytePerRow,再計算列數(shù)相對于行首的偏移=Col * 每像素位數(shù) / 8。故總的數(shù)據(jù)偏移 = 數(shù)據(jù)區(qū)偏移 + 行首的相對偏移 + 列偏移。
將文件指針定位到文件的偏移處,如果是24真彩色位圖,則讀取3個字節(jié),轉(zhuǎn)換為32位格式;如果是256色圖,則還要讀取彩色表:文件偏移 = 彩色表偏移 + 顏色索引x 4,再讀取四個字節(jié)返回32位數(shù)據(jù)。
(3)從文件讀取的RGB數(shù)據(jù),要轉(zhuǎn)換為LCD支持的格式,比如我這上面的液晶支持16位(5:6:5)格式,這樣就必須經(jīng)過轉(zhuǎn)換,當然也可以讓液晶底層操作函數(shù)接收32位顏色格式,再作內(nèi)部的轉(zhuǎn)換。
(4)如何確定液晶從哪一行開始顯示,哪一列開始?顯示多少行,顯示多少列?
比如我的液晶為 160x128 最多顯示128行。如果圖片的高度大于128行,液晶顯示是從127行開始。如果圖像小于128行,比如120行,則就從119行開始顯示。
如果液晶列數(shù)小于位圖寬度,則顯示寬度=液晶列數(shù)160。如果液晶列數(shù)大于位圖寬度,則顯示列數(shù)=位圖寬度,截止列為=位圖寬度 – 1。
同時,以后可能還要支持圖片的上下、左右移動,主要是調(diào)整 液晶顯示行列與位圖行列的關(guān)系。
比如按下向右鍵,要求每次移動16個像素,什么意思呢,實際上相當于移動液晶窗口,原來左邊對應位圖第0列,現(xiàn)在對應第16列。那么向下按鍵,液晶窗口向下移動,本來第一行顯示為圖第一行,現(xiàn)在則顯示位圖的第16行。如下圖所示。




