圖像處理學習之路 -- 認識BMP


因為公司的主要業務是圖像識別相關的,因此對圖像處理、識別是我學習的重點。雖然寫程序也不少年了,但是對於圖像處理領域,我還是一個新兵。對很多基礎的概念也還是存在盲區,所以想在邊學邊做的過程中,對一些概念的梳理和學習心得進行記錄。

BMP文件格式

BMP(Bitmap-File)圖形文件,又叫位圖文件,是Windows采用的圖形文件格式,在Windows環境下運行的所有圖象處理軟件都支持BMP圖象文件格式。Windows系統內部各圖像繪制操作都是以BMP為基礎的。一個BMP文件由四部分組成:

image

  • 位圖文件頭
  • 位圖信息段
  • 調色板
  • 位圖數據

                 

                一個BMP文件,可以用代碼表示,如下:

                typedef struct tagBITMAP_FILE{

                BITMAPFILEHEADER bitmapheader;
                BITMAPINFOHEADER bitmapinfoheader;
                PALETTEENTRY palette[256];
                UCHAR *buffer; //UCHAR 大小1字節(同BYTE), 在VC6下

                } BITMAP_FILE;

                1、 BMP文件頭:BITMAPFILEHEADER

                typedef struct tagBITMAPFILEHEADER { // bmfh 
                WORD bfType;
                DWORD bfSize;
                WORD bfReserved1;
                WORD bfReserved2;
                DWORD bfOffBits;
                } BITMAPFILEHEADER;

                bfType 說明文件的類型,該值必需是0x4D42,也就是字符'BM',否則表示根本不是BMP
                bfSize 說明該位圖文件的大小,用字節為單位
                bfReserved1 保留,必須設置為0
                bfReserved2 保留,必須設置為0
                bfOffBits 說明從文件頭開始到實際的圖象數據之間的字節的偏移量。這個參數是非常有用的,因為位圖信息頭和調色板的長度會根據不同情況而變化,所以你可以用這個偏移值迅速的從文件中讀取到位數據。

                 

                下面用Notepad++打開一個BMP文件:

                image(測試BMP文件)

                image

                這里:

                bfType:0X040d(BM)

                bfSize:0X0004a436 == 304182字節 == 297K字節,說明這個位圖文件的大小為297K字節,和我看到的符合:

                image

                跳過4字節的保留字節,

                bfOffBits:0X00000036 == 54字節

                 

                2、位圖信息段:BITMAPINFOHEADER

                typedef struct tagBITMAPINFOHEADER{ // bmih 
                DWORD biSize;
                LONG biWidth;
                LONG biHeight;
                WORD biPlanes;
                WORD biBitCount
                DWORD biCompression;
                DWORD biSizeImage;
                LONG biXPelsPerMeter;
                LONG biYPelsPerMeter;
                DWORD biClrUsed;
                DWORD biClrImportant;
                } BITMAPINFOHEADER;

                biSize 說明BITMAPINFOHEADER結構所需要的字節數
                biWidth 說明圖象的寬度,以象素為單位
                biHeight 說明圖象的高度,以象素為單位。注:這個值除了用於描述圖像的高度之外,它還有另一個用處,就是指明該圖像是倒向的位圖,還是正向的位圖。如果該值是一個正數,說明圖像是倒向的,即:數據的第一行其實是圖像的最后一行,如果該值是一個負數,則說明圖像是正向的。大多數的BMP文件都是倒向的位圖,也就是時,高度值是一個正數。
                biPlanes 表示bmp圖片的平面屬,顯然顯示器只有一個平面,所以恆等於1
                biBitCount 說明比特數/象素,其值為1、4、8、16、24、或32。
                biCompression 說明圖象數據壓縮的類型,其中:

                BI_RGB:沒有壓縮

                BI_RLE8:每個象素8比特的RLE壓縮編碼,壓縮格式由2字節組成(重復象素計數和顏色索引);

                BI_RLE4:每個象素4比特的RLE壓縮編碼,壓縮格式由2字節組成

                BI_BITFIELDS:每個象素的比特由指定的掩碼決定。

                BI_JPEG:JPEG格式

                biSizeImage 說明圖象的大小,以字節為單位。當用BI_RGB格式時,可設置為0。
                biXPelsPerMeter 說明水平分辨率,用象素/米表示。
                biYPelsPerMeter 說明垂直分辨率,用象素/米表示。
                biClrUsed 說明位圖實際使用的彩色表中的顏色索引數(設為0的話,則說明使用所有調色板項)。
                biClrImportant 說明對圖象顯示有重要影響的顏色索引的數目,如果是0,表示都重要。

                image

                biSize:位圖信息段結構BITMAPINFOHEADER的字節數 0x00000028 ==40字節

                biWidth:352像素;

                biHeight:288像素;

                和圖片信息相符:

                image

                biPlanes:1

                biBitCount :24位圖

                biCompression:沒有壓縮;

                biSizeImage:0x4a400 == 304128字節 ,當用BI_RGB格式時,可設置為0,為什么這里是304128呢?這里的304128是怎么出來的呢?

                原來biSizeImage = biWidth*biHeight*每個像素的字節數

                那么我們這里應該是:352*288*24/8 = 304128。(我們這里的位數/像素為24,所以每個像素的字節數為3)

                注:這里的biWidth必須是4的倍數,如果不是4的倍數,則需要取4的倍數,比如241,則取244;為什么必須是4的倍數?這里涉及到一個行對齊的問題:

                由於Windows在進行行掃描的時候最小的單位為4個字節,所以當

                圖片寬 X 每個像素的字節數 != 4的整數倍

                時要在每行的后面補上缺少的字節,以0填充

                biXPelsPerMeter:0x00000000

                biYPelsPerMeter:0x00000000

                biClrUsed:0x00000000  使用所有調色板項

                biClrImportant:00000000

                 

                3、調色板

                上面這張BMP圖片是否有調色板呢?答案是否定的。

                因為從bfOffBits = 54字節可以看出,剛好是sizeof(BITMAPFILEHEADER )+sizeof(BITMAPINFOHEADER);

                那么究竟調色板是什么東西?有什么用?為什么我們這種圖片不帶調試板呢?

                我們先來說說三元色RGB概念。

                我們知道,自然界中的所有顏色都可以由紅、綠、藍(R,G,B)組合而成。有的顏色含有紅色成分多一些,如深紅;有的含有紅色成分少一些,如淺紅。針對含有紅色成分的多少,可以分成0到255共256個等級,0級表示不含紅色成分;255級表示含有100%的紅色成分。同樣,綠色和藍色也被分成256級。這種分級概念稱為量化。

                1.1 常見顏色的RGB組合值

                image

                當一幅圖中每個象素賦予不同的RGB值時,能呈現出五彩繽紛的顏色了,這樣就形成了彩色圖。

                讓我們舉例說明什么是調色板?為什么需要調色板?

                        有一個長寬各為200個象素,顏色數為16色的彩色圖,每一個象素都用R、G、B三個分量表示。因為每個分量有256個級別,要用8位(bit),即一個字節(byte)來表示,所以每個象素需要用3個字節。整個圖象要用200×200×3,約120k字節,可不是一個小數目呀!如果我們用下面的方法,就能省的多。

                因為是一個16色圖,也就是說這幅圖中最多只有16種顏色,我們可以用一個表:表中的每一行記錄一種顏色的R、G、B值。這樣當我們表示一個象素的顏色時,只需要指出該顏色是在第幾行,即該顏色在表中的索引值。舉個例子,如果表的第0行為255,0,0(紅色),那么當某個象素為紅色時,只需要標明0即可。

                讓我們再來計算一下:16種狀態可以用4位(bit)表示,所以一個象素要用半個字節。整個圖象要用200×200×0.5,約20k字節,再加上表占用的字節為3×16=48字節.整個占用的字節數約為前面的1/6,省很多吧?

                        這張R、G、B的表,就是我們常說的調色板(Palette),另一種叫法是顏色查找表LUT(Look Up Table),似乎更確切一些。調色板在windows里的結構定義如下:

                typedef struct tagPALETTEENTRY { // pe 
                BYTE peRed;
                BYTE peGreen;
                BYTE peBlue;
                BYTE peFlags;
                } PALETTEENTRY;

                那么為什么我們這張BMP不帶調色板呢?

                       是因為我們這張BMP是24位真彩色的BMP,所謂真彩色圖(true color),就是它的顏色數高達256×256×256種,也就是說包含我們上述提到的R、G、B顏色表示方法中所有的顏色。真彩色圖並不是說一幅圖包含了所有的顏色,而是說它具有顯示所有顏色的能力,即最多可以包含所有的顏色。表示真彩色圖時,每個象素直接用R、G、B三個分量字節表示,而不采用調色板技術。原因很明顯:如果用調色板,表示一個象素也要用24位,這是因為每種顏色的索引要用24位(因為總共有256×256×256種顏色,即調色板有256×256×256行),和直接用R,G,B三個分量表示用的字節數一樣,不但沒有任何便宜,還要加上一個256×256×256×3個字節的大調色板。所以真彩色圖直接用R、G、B三個分量表示,它又叫做24位色圖。

                這么看來BMP文件不能一概而論了,其是否用調色板或者是RGB掩碼,位圖數據中的數據的真正含義直接與biBitCount 有關,不同類型的位圖,其中的設計原理也不同,下面對此作一個對比:

                image

                 

                4、位圖數據

                上面基本把調色板及相關取色策略梳理清楚了,接着回到我們上面的例子。24位BMP圖,每3個字節表示一個像素,3個字節分別表示R、G、B的分量值

                image

                這里每3個字節表示一個像素的顏色,注意:由於位圖信息頭中的圖像高度是正數,所以位圖數據在文件中的排列順序是從左下角到右上角,以行為主序排列的。

                 

                參考了BMP文件格式詳解(BMP file format)的學習思路,對BMP格式進行了梳理和學習。

                參考資源:

                        BMP文件格式詳解(BMP file format)

                        百度BMP格式


                免責聲明!

                本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



                 
                粵ICP備18138465號   © 2018-2025 CODEPRJ.COM