因?yàn)楣镜闹饕獦I(yè)務(wù)是圖像識別相關(guān)的,因此對圖像處理、識別是我學(xué)習(xí)的重點(diǎn)。雖然寫程序也不少年了,但是對于圖像處理領(lǐng)域,我還是一個新兵。對很多基礎(chǔ)的概念也還是存在盲區(qū),所以想在邊學(xué)邊做的過程中,對一些概念的梳理和學(xué)習(xí)心得進(jìn)行記錄。 BMP文件格式 BMP(Bitmap-File)圖形文件,又叫位圖文件,是Windows采用的圖形文件格式,在Windows環(huán)境下運(yùn)行的所有圖象處理軟件都支持BMP圖象文件格式。Windows系統(tǒng)內(nèi)部各圖像繪制操作都是以BMP為基礎(chǔ)的。一個BMP文件由四部分組成:
一個BMP文件,可以用代碼表示,如下: typedef struct tagBITMAP_FILE{ 1、 BMP文件頭:BITMAPFILEHEADER typedef struct tagBITMAPFILEHEADER { // bmfh
下面用Notepad++打開一個BMP文件: 這里: bfType:0X040d(BM) bfSize:0X0004a436 == 304182字節(jié) == 297K字節(jié),說明這個位圖文件的大小為297K字節(jié),和我看到的符合: 跳過4字節(jié)的保留字節(jié), bfOffBits:0X00000036 == 54字節(jié)
2、位圖信息段:BITMAPINFOHEADER typedef struct tagBITMAPINFOHEADER{ // bmih
biSize:位圖信息段結(jié)構(gòu)BITMAPINFOHEADER的字節(jié)數(shù) 0x00000028 ==40字節(jié) biWidth:352像素; biHeight:288像素; 和圖片信息相符: biPlanes:1 biBitCount :24位圖 biCompression:沒有壓縮; biSizeImage:0x4a400 == 304128字節(jié) ,當(dāng)用BI_RGB格式時,可設(shè)置為0,為什么這里是304128呢?這里的304128是怎么出來的呢? 原來biSizeImage = biWidth*biHeight*每個像素的字節(jié)數(shù) 那么我們這里應(yīng)該是:352*288*24/8 = 304128。(我們這里的位數(shù)/像素為24,所以每個像素的字節(jié)數(shù)為3) 注:這里的biWidth必須是4的倍數(shù),如果不是4的倍數(shù),則需要取4的倍數(shù),比如241,則取244;為什么必須是4的倍數(shù)?這里涉及到一個行對齊的問題: 由于Windows在進(jìn)行行掃描的時候最小的單位為4個字節(jié),所以當(dāng) 圖片寬 X 每個像素的字節(jié)數(shù) != 4的整數(shù)倍 時要在每行的后面補(bǔ)上缺少的字節(jié),以0填充 biXPelsPerMeter:0x00000000 biYPelsPerMeter:0x00000000 biClrUsed:0x00000000 使用所有調(diào)色板項(xiàng) biClrImportant:00000000
3、調(diào)色板 上面這張BMP圖片是否有調(diào)色板呢?答案是否定的。 因?yàn)閺腷fOffBits = 54字節(jié)可以看出,剛好是sizeof(BITMAPFILEHEADER )+sizeof(BITMAPINFOHEADER); 那么究竟調(diào)色板是什么東西?有什么用?為什么我們這種圖片不帶調(diào)試板呢? 我們先來說說三元色RGB概念。 我們知道,自然界中的所有顏色都可以由紅、綠、藍(lán)(R,G,B)組合而成。有的顏色含有紅色成分多一些,如深紅;有的含有紅色成分少一些,如淺紅。針對含有紅色成分的多少,可以分成0到255共256個等級,0級表示不含紅色成分;255級表示含有100%的紅色成分。同樣,綠色和藍(lán)色也被分成256級。這種分級概念稱為量化。 表1.1 常見顏色的RGB組合值 當(dāng)一幅圖中每個象素賦予不同的RGB值時,能呈現(xiàn)出五彩繽紛的顏色了,這樣就形成了彩色圖。 讓我們舉例說明什么是調(diào)色板?為什么需要調(diào)色板? 有一個長寬各為200個象素,顏色數(shù)為16色的彩色圖,每一個象素都用R、G、B三個分量表示。因?yàn)槊總€分量有256個級別,要用8位(bit),即一個字節(jié)(byte)來表示,所以每個象素需要用3個字節(jié)。整個圖象要用200×200×3,約120k字節(jié),可不是一個小數(shù)目呀!如果我們用下面的方法,就能省的多。 因?yàn)槭且粋€16色圖,也就是說這幅圖中最多只有16種顏色,我們可以用一個表:表中的每一行記錄一種顏色的R、G、B值。這樣當(dāng)我們表示一個象素的顏色時,只需要指出該顏色是在第幾行,即該顏色在表中的索引值。舉個例子,如果表的第0行為255,0,0(紅色),那么當(dāng)某個象素為紅色時,只需要標(biāo)明0即可。 讓我們再來計算一下:16種狀態(tài)可以用4位(bit)表示,所以一個象素要用半個字節(jié)。整個圖象要用200×200×0.5,約20k字節(jié),再加上表占用的字節(jié)為3×16=48字節(jié).整個占用的字節(jié)數(shù)約為前面的1/6,省很多吧? 這張R、G、B的表,就是我們常說的調(diào)色板(Palette),另一種叫法是顏色查找表LUT(Look Up Table),似乎更確切一些。調(diào)色板在windows里的結(jié)構(gòu)定義如下: typedef struct tagPALETTEENTRY { // pe 那么為什么我們這張BMP不帶調(diào)色板呢? 是因?yàn)槲覀冞@張BMP是24位真彩色的BMP,所謂真彩色圖(true color),就是它的顏色數(shù)高達(dá)256×256×256種,也就是說包含我們上述提到的R、G、B顏色表示方法中所有的顏色。真彩色圖并不是說一幅圖包含了所有的顏色,而是說它具有顯示所有顏色的能力,即最多可以包含所有的顏色。表示真彩色圖時,每個象素直接用R、G、B三個分量字節(jié)表示,而不采用調(diào)色板技術(shù)。原因很明顯:如果用調(diào)色板,表示一個象素也要用24位,這是因?yàn)槊糠N顏色的索引要用24位(因?yàn)榭偣灿?56×256×256種顏色,即調(diào)色板有256×256×256行),和直接用R,G,B三個分量表示用的字節(jié)數(shù)一樣,不但沒有任何便宜,還要加上一個256×256×256×3個字節(jié)的大調(diào)色板。所以真彩色圖直接用R、G、B三個分量表示,它又叫做24位色圖。 這么看來BMP文件不能一概而論了,其是否用調(diào)色板或者是RGB掩碼,位圖數(shù)據(jù)中的數(shù)據(jù)的真正含義直接與biBitCount 有關(guān),不同類型的位圖,其中的設(shè)計原理也不同,下面對此作一個對比:
4、位圖數(shù)據(jù) 上面基本把調(diào)色板及相關(guān)取色策略梳理清楚了,接著回到我們上面的例子。24位BMP圖,每3個字節(jié)表示一個像素,3個字節(jié)分別表示R、G、B的分量值 這里每3個字節(jié)表示一個像素的顏色,注意:由于位圖信息頭中的圖像高度是正數(shù),所以位圖數(shù)據(jù)在文件中的排列順序是從左下角到右上角,以行為主序排列的。 |
|