• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            c++初學者

            專注技術開發

            (轉) bmp圖分析

            說到圖片,位圖(Bitmap)當然是最簡單的,它Windows顯示圖片的基本格式,其文件擴展名為*.BMP。在Windows下,任何各式的圖片文件(包括視頻播放)都要轉化為位圖個時候才能顯示出來,各種格式的圖片文件也都是在位圖格式的基礎上采用不同的壓縮算法生成的(Flash中使用了適量圖,是按相同顏色區域存儲的)。

            一、下面我們來看看位圖文件(*.BMP)的格式。

            位圖文件主要分為如下3個部分:

            塊名稱

            對應Windows結構體定義

            大小(Byte

            文件信息頭

            BITMAPFILEHEADER

            14

            位圖信息頭

            BITMAPINFOHEADER

            40

            RGB顏色陣列

            BYTE*

            由圖像長寬尺寸決定

            1、   文件信息頭BITMAPFILEHEADER

            結構體定義如下:

            typedef struct tagBITMAPFILEHEADER { /* bmfh */

            UINT bfType;
            DWORD bfSize;
            UINT bfReserved1;
            UINT bfReserved2;
            DWORD bfOffBits;

            } BITMAPFILEHEADER;

            其中:

            bfType

            說明文件的類型,該值必需是0x4D42,也就是字符'BM'

            bfSize

            說明該位圖文件的大小,用字節為單位

            bfReserved1

            保留,必須設置為0

            bfReserved2

            保留,必須設置為0

            bfOffBits

            說明從文件頭開始到實際的圖象數據之間的字節的偏移量。這個參數是非常有用的,因為位圖信息頭和調色板的長度會根據不同情況而變化,所以你可以用這個偏移值迅速的從文件中讀取到位數據。


            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

            為目標設備說明位面數,其值將總是被設為1

            biBitCount

            說明比特數/象素,其值為1481624、或32。但是由于我們平時用到的圖像絕大部分是24位和32位的,所以我們討論這兩類圖像。

            biCompression

            說明圖象數據壓縮的類型,同樣我們只討論沒有壓縮的類型:BI_RGB

            biSizeImage

            說明圖象的大小,以字節為單位。當用BI_RGB格式時,可設置為0

            biXPelsPerMeter

            說明水平分辨率,用象素/米表示。

            biYPelsPerMeter

            說明垂直分辨率,用象素/米表示。

            biClrUsed

            說明位圖實際使用的彩色表中的顏色索引數(設為0的話,則說明使用所有調色板項)。

            biClrImportant

            說明對圖象顯示有重要影響的顏色索引的數目,如果是0,表示都重要。

            3、RGB顏色陣列

            有關RGB三色空間我想大家都很熟悉,這里我想說的是在Windows下,RGB顏色陣列存儲的格式其實BGR。也就是說,對于24位的RGB位圖像素數據格式是:

            藍色B

            綠色G

            紅色R

            對于32位的RGB位圖像素數據格式是:

            藍色B

            綠色G

            紅色R

            透明通道A

            透明通道也稱Alpha通道,該值是該像素點的透明屬性,取值在0(全透明)到255(不透明)之間。對于24位的圖像來說,因為沒有Alpha通道,故整個圖像都不透明。

            二、搞清了文件格式,下一步我們要實現加載。

                        加載文件的目的是要得到圖片屬性,以及RGB數據,然后可以將其繪制在DC(GDI),或是生成紋理對象(3D:OpenGL/Direct3D)。這兩種用途在數據處理上有點區別,我們主要按前一種用法講,在和3D有不同的地方,我們再提出來。

            1、加載文件頭

                        //Load the file header

                        BITMAPFILEHEADER header;

                        memset(&header, 0, sizeof(header));

                        inf.read((char*)&header, sizeof(header));

                        if(header.bfType != 0x4D42)

                                    return false;

                        這個很簡單,沒有什么好說的。

                        2、加載位圖信息頭

                        //Load the image information header

                        BITMAPINFOHEADER infoheader;

                        memset(&infoheader, 0, sizeof(infoheader));

                        inf.read((char*)&infoheader, sizeof(infoheader));

                        m_iImageWidth = infoheader.biWidth;

                        m_iImageHeight = infoheader.biHeight;

                        m_iBitsPerPixel = infoheader.biBitCount;

                        這里我們得到了3各重要的圖形屬性:寬,高,以及每個像素顏色所占用的位數。

            3、行對齊

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

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

            時要在每行的后面補上缺少的字節,以0填充(一般來說當圖像寬度為2的冪時不需要對齊)。位圖文件里的數據在寫入的時候已經進行了行對齊,也就是說加載的時候不需要再做行對齊。但是這樣一來圖片數據的長度就不是:寬 X X 每個像素的字節數 了,我們需要通過下面的方法計算正確的數據長度:

            //Calculate the image data size

            int iLineByteCnt = (((m_iImageWidth*m_iBitsPerPixel) + 31) >> 5) << 2;

            m_iImageDataSize = iLineByteCnt * m_iImageHeight;

            4、加載圖片數據

            對于24位和32位的位圖文件,位圖數據的偏移量為sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER),也就是說現在我們可以直接讀取圖像數據了。

                        if(m_pImageData) delete []m_pImageData;

                        m_pImageData = new unsigned char[m_iImageDataSize];

                        inf.read((char*)m_pImageData, m_iImageDataSize);

            如果你足夠細心,就會發現內存m_pImageData里的數據的確是BGR格式,可以用個純藍色或者是純紅色的圖片測試一下。

            5、繪制

            好了,數據和屬性我們都有了,現在就可以拿來隨便用了,就和吃饅頭一樣,愛粘白糖粘白糖,愛粘紅糖粘紅糖。下面是我的GDI繪制代碼,僅作參考。

            void CImage::DrawImage(HDC hdc, int iLeft, int iTop, int iWidth, int iHeight)

            {

                        if(!hdc || m_pImageData == NULL)

                                    return;

                        BITMAPINFO bmi;

                        memset(&bmi, 0, sizeof(bmi));

                        bmi.bmiHeader.biSize = sizeof(BITMAPINFO);

                        bmi.bmiHeader.biWidth = m_iImageWidth;

                        bmi.bmiHeader.biHeight = m_iImageHeight;

                        bmi.bmiHeader.biPlanes = 1;

                        bmi.bmiHeader.biBitCount = m_iBitsPerPixel;

                        bmi.bmiHeader.biCompression = BI_RGB;

                        bmi.bmiHeader.biSizeImage = m_iImageDataSize;

                        StretchDIBits(hdc, iLeft, iTop, iWidth, iHeight,

                                                            0, 0, m_iImageWidth, m_iImageHeight,

                                                            m_pImageData, &bmi, DIB_RGB_COLORS, SRCCOPY);

            }

            6、3D(OpenGL)的不同之處

            如果你是想用剛才我們得到的數據生成紋理對象,那么你還要請出下面的問題。

            首先,用來生成紋理的數據不需要對齊,也就是說不能在每行的后面加上對齊的字節。當然在OpenGL里要求紋理圖片的尺寸為2的冪,所以這個問題實際上不存在;

            其次,我們得到的圖形數據格式是BGR(BGRA),所以在生成紋理的時候,需指定格式為GL_BGR_EXT(GL_BGRA_EXT);否則需要做BGR->RGB(BGRA->RGBA)的轉化

            posted on 2008-09-03 18:24 大海 閱讀(1167) 評論(0)  編輯 收藏 引用 所屬分類: 圖像

            国产精品久久网| 精品国产乱码久久久久软件| 伊人色综合久久天天人手人婷| 超级97碰碰碰碰久久久久最新| 久久久久se色偷偷亚洲精品av| 久久久中文字幕| 精品人妻伦九区久久AAA片69| 综合人妻久久一区二区精品| 久久国产精品国产自线拍免费| 久久天天躁狠狠躁夜夜2020一| 久久久久国产精品熟女影院| 久久亚洲精品成人无码网站| 久久国产精品成人片免费| 久久无码一区二区三区少妇| 国产精品视频久久| 伊人 久久 精品| 日本WV一本一道久久香蕉| 99久久国语露脸精品国产| 久久亚洲精品国产亚洲老地址| 国产高潮国产高潮久久久91| 99精品久久精品一区二区| 亚洲精品国产综合久久一线| 青青草原1769久久免费播放| 色播久久人人爽人人爽人人片AV| 久久国产一区二区| 久久99精品久久久久子伦| 精品乱码久久久久久久| 少妇无套内谢久久久久| 午夜视频久久久久一区 | 午夜肉伦伦影院久久精品免费看国产一区二区三区 | 久久国产视频网| 伊人色综合久久天天| 久久综合久久综合九色| 久久亚洲精品中文字幕| 久久免费精品视频| 久久久久亚洲精品天堂| 色综合久久久久无码专区| 久久久91精品国产一区二区三区| 国产色综合久久无码有码| 久久亚洲熟女cc98cm| 亚洲国产精品久久久天堂|