• <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++ Programmer's Cookbook

            {C++ 基礎(chǔ)} {C++ 高級} {C#界面,C++核心算法} {設(shè)計模式} {C#基礎(chǔ)}

            GDI Bitmaps and Device-Independent Bitmaps 操作

            DIB(Device-Independent Bitmap,設(shè)備無關(guān)位圖)小知識

                        作者:顧勝元 湯澤江 陳載春

             

            位圖簡介

             

            位圖一共有兩種類型,分別為:設(shè)備相關(guān)位圖(DDBDevice-Dependent Bitmap)和設(shè)備無關(guān)位圖(DIBDevice-Independent Bitmap)。GDI bitmap objects (設(shè)備相關(guān)位圖)are represented by the MFC library CBitmap class.

             

            BMP文件是Windows保存圖像的一種通用文件格式,在數(shù)字圖像處理方面占有重要的地位。BMP文件中保存的圖像數(shù)據(jù)就是一種DIB(Device-Independent Bitmap,即設(shè)備無關(guān)位圖)DIB是標(biāo)準(zhǔn)的Windows位圖格式,它自帶顏色信息,因此調(diào)色板管理非常容易。

             

            BMP文件的結(jié)構(gòu)

             

            DIB位圖包含下列的顏色和尺寸信息:

                 原始設(shè)備(即創(chuàng)建圖片的設(shè)備)的顏色格式。

                 原始設(shè)備的分辯率。

                 原始設(shè)備的調(diào)色板(僅用于256色)

                 圖像像素數(shù)據(jù),由紅、綠、藍(RGB)三個值代表一個像素。

                 一個數(shù)組壓縮標(biāo)志,用于表明數(shù)據(jù)的壓縮方案(如果需要的話)。

            以上這些信息保存在BITMAPINFO結(jié)構(gòu)中,該結(jié)構(gòu)由BITMAPINFOHEADER結(jié)構(gòu)和兩個或更多個RGBQUAD結(jié)構(gòu)所組成。BITMAPINFOHEADER結(jié)構(gòu)所包含的成員表明了圖像的尺寸、原始設(shè)備的顏色格式、以及數(shù)據(jù)壓縮方案等信息。RGBQUAD結(jié)構(gòu)標(biāo)識了像素所用到的顏色數(shù)據(jù)。

             

            DIB位圖也有兩種形式,分為:bottom-up DIBtop-down DIBBottom-up DIB的原點(origin)在圖像的左下角,而top-down DIB的原點在圖像的左上角。如果DIB的高度值(由BITMAPINFOHEADER結(jié)構(gòu)中的biHeight成員標(biāo)識)是一個正值,那么就表明這個DIB是一個bottom-up DIB,如果高度值是一個負值,那么它就是一個top-down DIB。注意:top-down DIB位圖是不能被壓縮的。

             

            一般來說,BMP文件均為bottom-up DIB形式,即像素數(shù)據(jù)從下到上,從左到右存儲于文件中。也就是說,從文件中最先讀到的是圖象最下面一行的左邊第一個象素,然后是左邊第二個象素……接下來是倒數(shù)第二行左邊第一個象素,左邊第二個象素……依次類推 ,最后得到的是最上面一行的最右一個象素。

            位圖文件結(jié)構(gòu)概觀分析:

            位圖文件可看成由4個部分組成:位圖文件頭(bitmap-file header)、位圖信息頭(bitmap-information header)、彩色表(color table)和定義位圖的字節(jié)陣列,它具有如下所示的形式。

            位圖文件的組成

            結(jié)構(gòu)名稱

            符號

            位圖文件頭(bitmap-file header)

            BITMAPFILEHEADER

            bmfh

            位圖信息頭(bitmap-information header)

            BITMAPINFOHEADER

            bmih

            彩色表(color table)/調(diào)色板(Palette

            RGBQUAD

            aColors[]

            圖象數(shù)據(jù)陣列

            BYTE

            aBitmapBits[]

             

            struct BITMAPFILEHEADER {

            WORD           bfType;

            DWORD        bfSize;

            WORD           bfReserved1;

            WORD           bfReserved2;

            DWORD        bfOffBits;

            };

             

            struct BITMAPINFOHEADER{

            DWORD        biSize;

            LONG            biWidth;

            LONG            biHeight;

            WORD           biPlanes;

            WORD           biBitCount;

            DWORD        biCompression;

            DWORD        biSizeImage;

            LONG            biXPelsPerMeter;

            LONG            biYPelsPerMeter;

            DWORD        biClrUsed;

            DWORD        biClrImportant;

            };

             

            struct RGBQUAD {

            BYTE             rgbBlue;

            BYTE             rgbGreen;

            BYTE             rgbRed;

            BYTE             rgbReserved;

            };

            位圖文件結(jié)構(gòu)詳細分析:

             

            偏移量

            域的名稱

            大小

            內(nèi)容

             圖象文件頭

            0000h

            bfType = “BM”(0x4D42)

            2 bytes

            兩字節(jié)的內(nèi)容用來識別位圖的類型:

            ‘BM’ Windows 3.1x, 95, NT, …

            ‘BA’ OS/2 Bitmap Array

            ‘CI’ OS/2 Color Icon

            ‘CP’ OS/2 Color Pointer

            ‘IC’ OS/2 Icon

            ‘PT’ OS/2 Pointer

             

            注:因為OS/2系統(tǒng)并沒有被普及開,所以在編程時,你只需判斷第一個標(biāo)識“BM”就行。

             

            0002h

            bfSize

            1 dword

            用字節(jié)表示的整個文件的大小

             

            0006h

            bfReserved1-2

            1 dword

            保留,必須設(shè)置為0

             

            000Ah

            bfOffBits

            1 dword

            從文件開始到位圖數(shù)據(jù)開始之間的數(shù)據(jù)(bitmap data)之間的偏移量,即表前三個部分的長度之和

            位圖信息頭

            000Eh

            biSize

            1 dword

            位圖信息頭(Bitmap Info Header)的長度,用來描述位圖的顏色、壓縮方法等。下面的長度表示:

            28h - Windows 3.1x, 95, NT, …

            0Ch - OS/2 1.x

            F0h - OS/2 2.x

             

            注:在Windows95982000等操作系統(tǒng)中,位圖信息頭的長度并不一定是28h,因為微軟已經(jīng)制定出了新的BMP文件格式,其中的信息頭結(jié)構(gòu)變化比較大,長度加長。所以最好不要直接使用常數(shù)28h,而是應(yīng)該從具體的文件中讀取這個值。這樣才能確保程序的兼容性。

             

            0012h

            biWidth

            1 dword

            位圖的寬度,以象素為單位

             

            0016h

            biHeight

            1 dword

            位圖的高度,以象素為單位

             

            001Ah

            biPlance

            1 word

            位圖的位面數(shù)(注:該值將總是1

             

            001Ch

            biBitCount

            1 word

            每個象素的位數(shù)

            1 - 單色位圖(實際上可有兩種顏色,缺省情況下是黑色和白色。你可以自己定義這兩種顏色)

            4 - 16 色位圖

            8 - 256 色位圖

            16 - 16bit 高彩色位圖

            24 - 24bit 真彩色位圖

            32 - 32bit 增強型真彩色位圖

             

            001Eh

            biCompression

            1 dword

            壓縮說明:

            0 - 不壓縮 (使用BI_RGB表示)

            1 - RLE 8-使用8RLE壓縮方式(BI_RLE8表示)

            2 - RLE 4-使用4RLE壓縮方式(BI_RLE4表示)

            3 - Bitfields-位域存放方式(BI_BITFIELDS表示)

             

            0022h

            biSizeImage

            1 dword

            用字節(jié)數(shù)表示的位圖數(shù)據(jù)的大小。該數(shù)必須是4的倍數(shù)

             

            0026h

            biXPelsPerMeter

            1 dword

            用象素/米表示的水平分辨率

             

            002Ah

            biYPelsPerMeter

            1 dword

            用象素/米表示的垂直分辨率

             

            002Eh

            biClrUsed

            1 dword

            位圖使用的顏色數(shù)。如8-比特/象素表示為100h或者 256.

             

            0032h

            biClrImportant

            1 dword

            指定重要的顏色數(shù)。當(dāng)該域的值等于顏色數(shù)時(或者等于0時),表示所有顏色都一樣重要

            調(diào)色板數(shù)據(jù)

            根據(jù)BMP版本的不同而不同

            Palette真彩色圖是不需要調(diào)色板的,BITMAPINFOHEADER后直接是位圖數(shù)據(jù)

            N * 4 byte

            調(diào)色板實際上是一個數(shù)組,共有biClrUsed個元素(如果該值為零,則有2biBitCount個元素)。數(shù)組中每個元素的類型是一個RGBQUAD結(jié)構(gòu),占4個字節(jié)

            rgbBlue

            1字節(jié)用于藍色分量

            rgbGreen

            1字節(jié)用于綠色分量

            rgbRed

            1字節(jié)用于紅色分量

            rgbReserved

            1字節(jié)用于填充符(0)

            圖象數(shù)據(jù)

            根據(jù)BMP版本及調(diào)色板尺寸的不同而不同

            Bitmap Data:該域的大小取決于壓縮方法及圖像的尺寸和圖像的位深度,它包含所有的位圖數(shù)據(jù)字節(jié),這些數(shù)據(jù)可能是彩色調(diào)色板的索引號,也可能是實際的RGB值(真彩色位圖),這將根據(jù)圖像信息頭中的位深度值來決定。

            xxx bytes

            象素按照行、列的順序排列每一行的字節(jié)數(shù)必須是4的整倍數(shù)。

            比較:

            2色位圖,用1位就可以表示該象素的顏色(一般0表示黑,1表示白),所以一個字節(jié)可以表示8個象素。

            16色位圖,用4位可以表示一個象素的顏色,所以一個字節(jié)可以表示2個象素。256色位圖,一個字節(jié)剛好可以表示1個象素。

            真彩色圖,三個字節(jié)才能表示1個象素

             

             

            顯示位圖的方法有許多,下面示范一種比較簡便的:

            // read bitmap file “a.bmp”

            HBITMAP         hBitmap = (HBITMAP)LoadImage( NULL, "a.bmp", IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE );

            HDC hMemDC  = CreateCompatibleDC( NULL );

            BITMAP   bm;

             

            // get bitmap size

            // bm.bmWidth, bm.bmHeight - size of image

            GetObject( hBitmap, sizeof(bm), &bm );

             

            // select bitmap object

            SelectObject( hMemDC, hBitmap );

             

            // BitBlt the image to screen

            // hdc – screen dc

            BitBlt( hdc, 0, 0, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY );

             

            // release all

            DeleteDC( hMemDC );

            DeleteObject( hBitmap );

             

            位圖讀寫DEMO代碼

             

            bitmap的一般過程:

            1、聲明BITMAPFILEHEADER,并清空該結(jié)構(gòu):

                   BITMAPFILEHEADER bfh

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

            2、初始化該結(jié)構(gòu):

                   bfn.bfType = 'MB';               // Bitmap

                          //說明該文件的大小,cbBuffer為位圖數(shù)據(jù)的大小

                   bfn.bfSize = sizeof(bfn) + cbBuffer + sizeof(BITMAPINFOHEADER);

                   //說明位圖文件數(shù)據(jù)在整個位圖文件中的偏移,即數(shù)據(jù)是從哪兒開始的

                   bfn.bfOffBits = sizeof(BITMAPINFORHEADER) + sizeof(BITMAPFILEHEADER);

             

            如果你的應(yīng)用程序想以位映射的方式保存圖像的話,你可以采用Windows操作系統(tǒng)的位圖格式來保存。步驟是,先初始化BITMAPINFO結(jié)構(gòu)(由BITMAPINFOHEADER結(jié)構(gòu)和RGBQUAD結(jié)構(gòu)數(shù)組組成),然后填寫適當(dāng)?shù)臄?shù)據(jù)用以說明待保存圖像的各種參數(shù)。最后將BITMAPFILEHEADER結(jié)構(gòu)及BITMAPINFO結(jié)構(gòu)和位數(shù)組寫入文件當(dāng)中。

             

            下面的范例代碼演示了怎樣初始化并填寫BITMAPINFOHEADER結(jié)構(gòu)

            PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp) 
            {
                BITMAP bmp; 
                PBITMAPINFO pbmi;
                WORD    cClrBits;  
             
                /* Retrieve the bitmap's color format, width, and height. */  
                if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) 
                    errhandler("GetObject", hwnd);   
             
                /* Convert the color format to a count of bits. */  
                cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
             
                if (cClrBits == 1) 
                    cClrBits = 1;
                else if (cClrBits <= 4)
                    cClrBits = 4; 
                else if (cClrBits <= 8) 
                    cClrBits = 8;
                else if (cClrBits <= 16) 
                    cClrBits = 16;
                else if (cClrBits <= 24) 
                    cClrBits = 24; 
                else 
                    cClrBits = 32;      
             
                /* 
                 * Allocate memory for the BITMAPINFO structure. (This structure 
                 * contains a BITMAPINFOHEADER structure and an array of RGBQUAD data 
                 * structures.)      
                 */      
                if (cClrBits != 24) 
                    pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
                                sizeof(BITMAPINFOHEADER) + 
                                sizeof(RGBQUAD) * (2^cClrBits));      
                /*  There is no RGBQUAD array for the 24-bit-per-pixel format. */  
                else 
                    pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
                                sizeof(BITMAPINFOHEADER));    
             
                /* Initialize the fields in the BITMAPINFO structure. */  
                pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
                pbmi->bmiHeader.biWidth = bmp.bmWidth; 
                pbmi->bmiHeader.biHeight = bmp.bmHeight; 
                pbmi->bmiHeader.biPlanes = bmp.bmPlanes; 
                pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
                if (cClrBits < 24) 
                    pbmi->bmiHeader.biClrUsed = 2^cClrBits;   
             
                /* If the bitmap is not compressed, set the BI_RGB flag. */  
                pbmi->bmiHeader.biCompression = BI_RGB;      
             
                /* 
                 * Compute the number of bytes in the array of color 
                 * indices and store the result in biSizeImage.
                 */  
                pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) /8 
                                              * pbmi->bmiHeader.biHeight 
                                              * cClrBits;      
                /* 
                 * Set biClrImportant to 0, indicating that all of the 
                 * device colors are important.
                 */  
                pbmi->bmiHeader.biClrImportant = 0;
                return pbmi;  
            } 

             

            3、將bfn寫入文件

            4、申明BITMAPINFOHEADER,并清空該結(jié)構(gòu):

                   BITMAPINFOHEADER bih;

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

            5、初始化該結(jié)構(gòu):

                   bih.biSize = sizeof( bih );

                   bih.biWidth = biWidth;                        //位圖的寬度

                   bih.biHeight = biHeight;                //位圖的高度

                   bih.biPlanes = biPlanes;                //位圖的位面數(shù)

                   bih.biBitCount = biBitCount;                //位圖的色深

            6、將bih寫入文件

            7、最后寫入數(shù)據(jù)就行了。

             

            下面的范例將演示怎樣打開一個文件,并拷貝數(shù)組、獲取調(diào)色板索引、初始化保留結(jié)構(gòu)、關(guān)閉文件等操作:

            void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, 
                              HBITMAP hBMP, HDC hDC) 
            {
                HANDLE hf;                  /* file handle */ 
                BITMAPFILEHEADER hdr;       /* bitmap file-header */ 
                PBITMAPINFOHEADER pbih;     /* bitmap info-header */ 
                LPBYTE lpBits;              /* memory pointer */ 
                DWORD dwTotal;              /* total count of bytes */ 
                DWORD cb;                   /* incremental count of bytes */ 
                BYTE *hp;                   /* byte pointer */ 
                DWORD dwTmp; 
             
             
                pbih = (PBITMAPINFOHEADER) pbi; 
                lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);    if (!lpBits) 
                     errhandler("GlobalAlloc", hwnd); 
             
                /* 
                 * Retrieve the color table (RGBQUAD array) and the bits 
                 * (array of palette indices) from the DIB. 
                 */ 
             
                if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, 
                               lpBits, pbi, DIB_RGB_COLORS)) 
                    errhandler("GetDIBits", hwnd); 
             
                /* Create the .BMP file. */ 
             
                hf = CreateFile(pszFile, 
                               GENERIC_READ | GENERIC_WRITE, 
                               (DWORD) 0, 
                               (LPSECURITY_ATTRIBUTES) NULL, 
                               CREATE_ALWAYS, 
                               FILE_ATTRIBUTE_NORMAL, 
                               (HANDLE) NULL); 
             
                if (hf == INVALID_HANDLE_VALUE) 
                    errhandler("CreateFile", hwnd); 
             
                hdr.bfType = 0x4d42;        /* 0x42 = "B" 0x4d = "M" */ 
             
                /* Compute the size of the entire file. */ 
             
                hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + 
                             pbih->biSize + pbih->biClrUsed 
                             * sizeof(RGBQUAD) + pbih->biSizeImage); 
             
                hdr.bfReserved1 = 0; 
                hdr.bfReserved2 = 0; 
             
                /* Compute the offset to the array of color indices. */ 
             
                hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + 
                                pbih->biSize + pbih->biClrUsed 
                                * sizeof (RGBQUAD); 
             
                /* Copy the BITMAPFILEHEADER into the .BMP file. */ 
             
                if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), 
                   (LPDWORD) &dwTmp, (LPOVERLAPPED) NULL)) 
                   errhandler("WriteFile", hwnd); 
             
                /* Copy the BITMAPINFOHEADER and RGBQUAD array into the file. */ 
             
                if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) 
                              + pbih->biClrUsed * sizeof (RGBQUAD), 
                              (LPDWORD) &dwTmp, (LPOVERLAPPED) NULL)) 
                   errhandler("WriteFile", hwnd); 
             
                /* Copy the array of color indices into the .BMP file. */ 
             
                dwTotal = cb = pbih->biSizeImage; 
                hp = lpBits; 
                while (cb > MAXWRITE)  { 
                        if (!WriteFile(hf, (LPSTR) hp, (int) MAXWRITE, 
                                      (LPDWORD) &dwTmp, (LPOVERLAPPED) NULL)) 
                            errhandler("WriteFile", hwnd); 
                        cb-= MAXWRITE; 
                        hp += MAXWRITE; 
                } 
                if (!WriteFile(hf, (LPSTR) hp, (int) cb, 
                     (LPDWORD) &dwTmp, (LPOVERLAPPED) NULL)) 
                       errhandler("WriteFile", hwnd); 
             
                /* Close the .BMP file. */ 
             
                if (!CloseHandle(hf)) 
                       errhandler("CloseHandle", hwnd); 
             
                /* Free memory. */    GlobalFree((HGLOBAL)lpBits);
            } 

             

             

            讀位圖:(偽代碼,未翻譯)

            If open Bitmap file

            Read two bytes (type) and if different than 0x4D42 stop

            Ignore eight bytes

            Read four bytes (start of image data)

            Ignore four bytes

            Read four bytes (width of bitmap)

            Read four bytes (height of bitmap)

            Ignore two bytes

            Read two bytes (bit count of bitmap) and if different than 24 stop

            Read four bytes (compression of bitmap) and if different than BI_RGB stop

            Move to start of image data

            Allocate memory for image data (3(one byte for red, other for

            green other for blue) * ImageWidth * ImageHeight)

            Read (3 * ImageWidth * ImageHeight) bytes from file to buffer

            Swap the red and blue components of buffer

            If ImageHeight is negative

            Flip the buffer lines

            End if

            Close file

             

             

            參考資料:

            posted on 2006-02-20 13:15 夢在天涯 閱讀(1314) 評論(0)  編輯 收藏 引用 所屬分類: MFC/QT

            公告

            EMail:itech001#126.com

            導(dǎo)航

            統(tǒng)計

            • 隨筆 - 461
            • 文章 - 4
            • 評論 - 746
            • 引用 - 0

            常用鏈接

            隨筆分類

            隨筆檔案

            收藏夾

            Blogs

            c#(csharp)

            C++(cpp)

            Enlish

            Forums(bbs)

            My self

            Often go

            Useful Webs

            Xml/Uml/html

            搜索

            •  

            積分與排名

            • 積分 - 1804159
            • 排名 - 5

            最新評論

            閱讀排行榜

            欧美伊人久久大香线蕉综合69| 欧美777精品久久久久网| 麻豆av久久av盛宴av| 欧美伊人久久大香线蕉综合| 漂亮人妻被中出中文字幕久久 | 久久久国产视频| 久久狠狠爱亚洲综合影院 | 国产精品99久久久久久董美香| 久久久黄片| 亚洲级αV无码毛片久久精品 | 国内精品伊人久久久影院| 久久久久人妻精品一区二区三区| 久久中文娱乐网| 一级a性色生活片久久无| 久久精品人人做人人爽97| 久久精品亚洲福利| 蜜臀久久99精品久久久久久小说| 久久国产一片免费观看| 国产人久久人人人人爽| 久久99热这里只频精品6| 久久久久久狠狠丁香| 久久成人国产精品免费软件| 91精品观看91久久久久久| 久久午夜无码鲁丝片秋霞 | 精品国产VA久久久久久久冰 | 精品永久久福利一区二区| 久久九九久精品国产| 国产婷婷成人久久Av免费高清| 亚洲国产成人久久笫一页| 欧美伊香蕉久久综合类网站| 精品久久亚洲中文无码| 久久久久97国产精华液好用吗| 欧洲精品久久久av无码电影| 欧美牲交A欧牲交aⅴ久久| 亚洲欧美国产精品专区久久| 91精品婷婷国产综合久久| 久久久久久国产精品免费无码| 久久乐国产综合亚洲精品| 久久99精品免费一区二区| 国产美女久久精品香蕉69| 性做久久久久久久|