DIB處理程式庫 就是現(xiàn)在-經(jīng)過我們長時間地學習GDI點陣圖物件,、裝置無關(guān)點陣圖、DIB區(qū)塊和Windows調(diào)色盤管理器之後-我們才做好了開發(fā)一套有助於處理點陣圖的函式的準備,。 前面的PACKEDIB檔案展示了一種可能的方法:記憶體中的packed DIB只用指向它的指標表示,。程式所的有關(guān)DIB的全部資訊都可以從存取表頭資訊結(jié)構(gòu)的函式獲得。然而,,實際上到「get pixel」和「set pixel」常式時,,這種方法就會產(chǎn)生嚴重的執(zhí)行問題。圖像處理任務(wù)當然需要存取點陣圖位元,,並且這些函式也應(yīng)該盡可能地快,。 可能的C++的解決方式中包括建立DIB類別,這時指向packed DIB的指標正好是一個成員變數(shù),。其他成員變數(shù)和成員函式有助於更快地執(zhí)行獲得和設(shè)定DIB中的圖素的常式,。不過,因為我在第一章已經(jīng)指出,,對於本書您只需要瞭解C,,使用C++將是其他書的範圍,。 當然,用C++能做的事情用C也能做,。一個好的例子就是許多Windows函式都使用代號,。除了將代號當作數(shù)值以外,應(yīng)用程式對它還瞭解什麼呢,?程式知道代號引用特殊的函式物件,,還知道函式用於處理現(xiàn)存的物件。顯然,,作業(yè)系統(tǒng)按某種方式用代號來引用物件的內(nèi)部資訊,。代號可以與結(jié)構(gòu)指標一樣簡單。 例如,,假設(shè)有一個函式集,,這些函式都使用一個稱為HDIB的代號。HDIB是什麼呢,?它可能在某個表頭檔案中定義如下: typedef void * HDIB ; 此定義用「不關(guān)您的事」回答了「HDIB是什麼」這個問題,。 然而,實際上HDIB可能是結(jié)構(gòu)指標,,該結(jié)構(gòu)不僅包括指向packed DIB的指標,,還包括其他資訊: typedef struct { BITMAPINFO * pPackedDib ; int cx, cy, cBitsPerPixel, cBytesPerRow ; BYTE * pBits ; { DIBSTRUCTURE, * PDIBSTRUCTURE ; 此結(jié)構(gòu)的其他五個欄位包括從packed DIB中引出的資訊。當然,,結(jié)構(gòu)中這些值允許更快速地存取它們。不同的DIB程式庫函式都可以處理這個結(jié)構(gòu),,而不是pPackedDib指標,。可以按下面的方法來執(zhí)行DibGetPixelPointer函式: BYTE * DibGetPixelPointer (HDIB hdib, int x, int y) { PDIBSTRUCTURE pdib = hdib ; return pdib->pBits + y * pdib->cBytesPerRow + x * pdib->cBitsPerPixel / 8 ; } 當然,,這種方法可能要比PACKEDIB.C中執(zhí)行「get pixel」常式快,。 由於這種方法非常合理,所以我決定放棄packed DIB,,並改用處理DIB區(qū)塊的DIB程式庫,。這實際上使我們對packed DIB的處理有更大的彈性(也就是說,能夠在裝置無關(guān)的方式下操縱DIB圖素位元),,而且在Windows NT下執(zhí)行時將更有效,。 DIBSTRUCT結(jié)構(gòu) DIBHELP.C檔案-如此命名是因為對處理DIB提供幫助-有上千行,並在幾個小部分中顯示,。但是首先讓我們看一下DIBHELP函式所處理的結(jié)構(gòu),,該結(jié)構(gòu)在DIBHELP.C中定義如下: typedef struct { PBYTE * ppRow ; // array of row pointers int iSignature ; // = "Dib " HBITMAP hBitmap ; // handle returned from CreateDIBSection BYTE * pBits ; // pointer to bitmap bits DIBSECTION ds ; // DIBSECTION structure int iRShift[3] ; // right-shift values for color masks int iLShift[3] ; // left-shift values for color masks } DIBSTRUCT, * PDIBSTRUCT ; 現(xiàn)在跳過第一個欄位。它之所以為第一個欄位是因為它使某些巨集更易於使用-在討論完其他欄位以後再來理解第一個欄位就更容易了,。 在DIBHELP.C中,,當DIB建立的函式首先設(shè)定了此結(jié)構(gòu)時,,第二個欄位就設(shè)定為文字字串「Dib」的二進位值。通過一些DIBHELP函式,,第二個欄位將用於結(jié)構(gòu)有效指標的一個標記,。 第三個欄位,即hBitmap,,是從CreateDIBSection函式傳回的點陣圖代號,。您將想起該代號可有多種使用方式,它與我們在 第十四章 遇到的GDI點陣圖物件的代號用法一樣,。不過,,從CreateDIBSection傳回的代號將涉及按裝置無關(guān)格式儲存的點陣圖,該點陣圖格式一直儲存到通過呼叫BitBlt和StretchBlt來將位元圖畫到輸出設(shè)備,。DIBSTRUCT的第四個欄位是指向點陣圖位元的指標,。此值也可由CreateDIBSection函式設(shè)定。您將想起,,作業(yè)系統(tǒng)將控制這個記憶體塊,,但應(yīng)用程式有存取它的許可權(quán)。在刪除點陣圖代號時,,記憶體塊將自動釋放,。 DIBSTRUCT的第五個欄位是DIBSECTION結(jié)構(gòu)。如果您有從CreateDIBSection傳回的點陣圖代號,,那麼您可以將代號傳遞給GetObject函式以獲得有關(guān)DIBSECTION結(jié)構(gòu)中的點陣圖資訊: GetObject (hBitmap, sizeof (DIBSECTION), &ds) ; 作為提示,,DIBSECTION結(jié)構(gòu)在WINGDI.H中定義如下: typedef struct tagDIBSECTION { BITMAP dsBm ; BITMAPINFOHEADER dsBmih ; DWORD dsBitfields[3] ; // Color masks HANDLE dshSection ; DWORD dsOffset ; } DIBSECTION, * PDIBSECTION ; 第一個欄位是BITMAP結(jié)構(gòu),它與CreateBitmapIndirect一起建立點陣圖物件,,與GetObject一起傳回關(guān)於DDB的資訊,。第二個欄位是BITMAPINFOHEADER結(jié)構(gòu)。不管點陣圖資訊結(jié)構(gòu)是否傳遞給CreateDIBSection函式,,DIBSECTION結(jié)構(gòu)總有BITMAPINFOHEADER結(jié)構(gòu)而不是其他結(jié)構(gòu),,例如BITMAPCOREHEADER結(jié)構(gòu)。這意味著在存取此結(jié)構(gòu)時,,DIBHELP.C中的許多函式都不必檢查與OS/2相容的DIB,。 對於16位元和32位元的DIB,如果BITMAPINFOHEADER結(jié)構(gòu)的biCompression欄位是BI_BITFIELDS,,那麼在資訊表頭結(jié)構(gòu)後面通常有三個遮罩值,。這些遮罩值決定如何將16位元和32位圖素值轉(zhuǎn)換成RGB顏色。遮罩儲存在DIBSECTION結(jié)構(gòu)的第三個欄位中,。 DIBSECTION結(jié)構(gòu)的最後兩個欄位指的是DIB區(qū)塊,,此區(qū)塊由檔案映射建立。DIBHELP不使用CreateDIBSection的這個特性,,因此可以忽略這些欄位,。 DIBSTRUCT的最後兩個欄位儲存左右移位值,,這些值用於處理16位元和32位元DIB的顏色遮罩。我們將在 第十五章 討論這些移位值,。 讓我們再回來看一下DIBSTRUCT的第一個欄位,。正如我們所看到的一樣,在開始建立DIB時,,此欄位設(shè)定為指向一個指標陣列的指標,,該陣列中的每個指標都指向DIB中的一行圖素。這些指標允許以更快的方式來獲得DIB圖素位元,,同時也被定義,,以便頂行可以首先引用DIB圖素位元。此陣列的最後一個元素-引用DIB圖像的最底行-通常等於DIBSTRUCT的pBits欄位,。 資訊函式 DIBHELP.C以定義DIBSTRUCT結(jié)構(gòu)開始,,然後提供一個函式集,此函式集允許應(yīng)用程式獲得有關(guān)DIB區(qū)塊的資訊,。程式16-19顯示了DIBHELP.C的第一部分,。 程式16-19 DIBHELP.C檔案的第一部分 DIBHELP.C (第一部分) /*-------------------------------------------------------------------------- DIBHELP.C -- DIB Section Helper Routines (c) Charles Petzold, 1998 ----------------------------------------------------------------------------*/ #include <windows.h> #include "dibhelp.h" #define HDIB_SIGNATURE (* (int *) "Dib ") typedef struct { PBYTE * ppRow ; // must be first field for macros! int iSignature ; HBITMAP hBitmap ; BYTE * pBits ; DIBSECTION ds ; int iRShift[3] ; int iLShift[3] ; } DIBSTRUCT, * PDIBSTRUCT ; /*---------------------------------------------------------------------------- DibIsValid: Returns TRUE if hdib points to a valid DIBSTRUCT -----------------------------------------------------------------------------*/ BOOL DibIsValid (HDIB hdib) { PDIBSTRUCT pdib = hdib ; if (pdib == NULL) return FALSE ; if (IsBadReadPtr (pdib, sizeof (DIBSTRUCT))) return FALSE ; if (pdib->iSignature != HDIB_SIGNATURE) return FALSE ; return TRUE ; } /*---------------------------------------------------------------------------- DibBitmapHandle: Returns the handle to the DIB section bitmap object -----------------------------------------------------------------------------*/ HBITMAP DibBitmapHandle (HDIB hdib) { if (!DibIsValid (hdib)) return NULL ; return ((PDIBSTRUCT) hdib)->hBitmap ; } /*--------------------------------------------------------------------------- DibWidth: Returns the bitmap pixel width -----------------------------------------------------------------------------*/ int DibWidth (HDIB hdib) { if (!DibIsValid (hdib)) return 0 ; return ((PDIBSTRUCT) hdib)->ds.dsBm.bmWidth ; } /*--------------------------------------------------------------------------- DibHeight: Returns the bitmap pixel height ----------------------------------------------------------------------------*/ int DibHeight (HDIB hdib) { if (!DibIsValid (hdib)) return 0 ; return ((PDIBSTRUCT) hdib)->ds.dsBm.bmHeight ; } /*--------------------------------------------------------------------------- DibBitCount: Returns the number of bits per pixel ----------------------------------------------------------------------------*/ int DibBitCount (HDIB hdib) { if (!DibIsValid (hdib)) return 0 ; return ((PDIBSTRUCT) hdib)->ds.dsBm.bmBitsPixel ; } /*---------------------------------------------------------------------------- DibRowLength: Returns the number of bytes per row of pixels -----------------------------------------------------------------------------*/ int DibRowLength (HDIB hdib) { if (!DibIsValid (hdib)) return 0 ; return 4 * ((DibWidth (hdib) * DibBitCount (hdib) + 31) / 32) ; } /*--------------------------------------------------------------------------- DibNumColors: Returns the number of colors in the color table ----------------------------------------------------------------------------*/ int DibNumColors (HDIB hdib) { PDIBSTRUCT pdib = hdib ; if (!DibIsValid (hdib)) return 0 ; if (pdib->ds.dsBmih.biClrUsed != 0) { return pdib->ds.dsBmih.biClrUsed ; } else if (DibBitCount (hdib) <= 8) { return 1 << DibBitCount (hdib) ; } return 0 ; } /*--------------------------------------------------------------------------- DibMask: Returns one of the color masks ---------------------------------------------------------------------------*/ DWORD DibMask (HDIB hdib, int i) { PDIBSTRUCT pdib = hdib ; if (!DibIsValid (hdib) || i < 0 || i > 2) return 0 ; return pdib->ds.dsBitfields[i] ; } /*---------------------------------------------------------------------------- DibRShift: Returns one of the right-shift values -----------------------------------------------------------------------------*/ int DibRShift (HDIB hdib, int i) { PDIBSTRUCT pdib = hdib ; if (!DibIsValid (hdib) || i < 0 || i > 2) return 0 ; return pdib->iRShift[i] ; } /*---------------------------------------------------------------------------- DibLShift: Returns one of the left-shift values ----------------------------------------------------------------------------*/ int DibLShift (HDIB hdib, int i) { PDIBSTRUCT pdib = hdib ; if (!DibIsValid (hdib) || i < 0 || i > 2) return 0 ; return pdib->iLShift[i] ; } /*--------------------------------------------------------------------------- DibCompression: Returns the value of the biCompression field ----------------------------------------------------------------------------*/ int DibCompression (HDIB hdib) { if (!DibIsValid (hdib)) return 0 ; return ((PDIBSTRUCT) hdib)->ds.dsBmih.biCompression ; } /*--------------------------------------------------------------------------- DibIsAddressable: Returns TRUE if the DIB is not compressed ----------------------------------------------------------------------------*/ BOOL DibIsAddressable (HDIB hdib) { int iCompression ; if (!DibIsValid (hdib)) return FALSE ; iCompression = DibCompression (hdib) ; if ( iCompression == BI_RGB || iCompression == BI_BITFIELDS) return TRUE ; return FALSE ; } /*--------------------------------------------------------------------------- These functions return the sizes of various components of the DIB section AS THEY WOULD APPEAR in a packed DIB. These functions aid in converting the DIB section to a packed DIB and in saving DIB files. -----------------------------------------------------------------------------*/ DWORD DibInfoHeaderSize (HDIB hdib) { if (!DibIsValid (hdib)) return 0 ; return ((PDIBSTRUCT) hdib)->ds.dsBmih.biSize ; } DWORD DibMaskSize (HDIB hdib) { PDIBSTRUCT pdib = hdib ; if (!DibIsValid (hdib)) return 0 ; if (pdib->ds.dsBmih.biCompression == BI_BITFIELDS) return 3 * sizeof (DWORD) ; return 0 ; } DWORD DibColorSize (HDIB hdib) { return DibNumColors (hdib) * sizeof (RGBQUAD) ; } DWORD DibInfoSize (HDIB hdib) { return DibInfoHeaderSize(hdib) + DibMaskSize(hdib) + DibColorSize(hdib) ; } DWORD DibBitsSize (HDIB hdib) { PDIBSTRUCT pdib = hdib ; if (!DibIsValid (hdib)) return 0 ; if (pdib->ds.dsBmih.biSizeImage != 0) { return pdib->ds.dsBmih.biSizeImage ; } return DibHeight (hdib) * DibRowLength (hdib) ; } DWORD DibTotalSize (HDIB hdib) { return DibInfoSize (hdib) + DibBitsSize (hdib) ; } /*--------------------------------------------------------------------------- These functions return pointers to the various components of the DIB section. -----------------------------------------------------------------------------*/ BITMAPINFOHEADER * DibInfoHeaderPtr (HDIB hdib) { if (!DibIsValid (hdib)) return NULL ; return & (((PDIBSTRUCT) hdib)->ds.dsBmih) ; } DWORD * DibMaskPtr (HDIB hdib) { PDIBSTRUCT pdib = hdib ; if (!DibIsValid (hdib)) return 0 ; return pdib->ds.dsBitfields ; } void * DibBitsPtr (HDIB hdib) { if (!DibIsValid (hdib)) return NULL ; return ((PDIBSTRUCT) hdib)->pBits ; } /*--------------------------------------------------------------------------- DibSetColor: Obtains entry from the DIB color table -----------------------------------------------------------------------------*/ BOOL DibGetColor (HDIB hdib, int index, RGBQUAD * prgb) { PDIBSTRUCT pdib = hdib ; HDC hdcMem ; int iReturn ; if (!DibIsValid (hdib)) return 0 ; hdcMem = CreateCompatibleDC (NULL) ; SelectObject (hdcMem, pdib->hBitmap) ; iReturn = GetDIBColorTable (hdcMem, index, 1, prgb) ; DeleteDC (hdcMem) ; return iReturn ? TRUE : FALSE ; } /*---------------------------------------------------------------------------- DibGetColor: Sets an entry in the DIB color table ----------------------------------------------------------------------------*/ BOOL DibSetColor (HDIB hdib, int index, RGBQUAD * prgb) { PDIBSTRUCT pdib = hdib ; HDC hdcMem ; int iReturn ; if (!DibIsValid (hdib)) return 0 ; hdcMem = CreateCompatibleDC (NULL) ; SelectObject (hdcMem, pdib->hBitmap) ; iReturn = SetDIBColorTable (hdcMem, index, 1, prgb) ; DeleteDC (hdcMem) ; return iReturn ? TRUE : FALSE ; } DIBHELP.C中的大部分函式是不用解釋的。DibIsValid函式能有助於保護整個系統(tǒng),。在試圖引用DIBSTRUCT中的資訊之前,,其他函式都呼叫DibIsValid。所有這些函式都有(而且通常是只有)HDIB型態(tài)的第一個參數(shù),,( 我們將立即看到)該參數(shù)在DIBHELP.H中定義為空指標,。這些函式可以將此參數(shù)儲存到PDIBSTRUCT,然後再存取結(jié)構(gòu)中的欄位,。 注意傳回BOOL值的DibIsAddressable函式,。DibIsNotCompressed函式也可以呼叫此函式。傳回值表示獨立的DIB圖素能否定址,。 以DibInfoHeaderSize開始的函式集將取得DIB區(qū)塊中不同元件出現(xiàn)在packed DIB中的大小,。與我們所看到的一樣,,這些函式有助於將DIB區(qū)塊轉(zhuǎn)換成packed DIB,,並儲存DIB檔案。這些函式的後面是獲得指向不同DIB元件的指標的函式集,。 儘管DIBHELP.C包括名稱為DibInfoHeaderPtr的函式,,而且該函式將獲得指向BITMAPINFOHEADER結(jié)構(gòu)的指標,但還是沒有函式可以獲得BITMAPINFO結(jié)構(gòu)指標-即接在DIB顏色表後面的資訊結(jié)構(gòu),。這是因為在處理DIB區(qū)塊時,,應(yīng)用程式並不直接存取這種型態(tài)的結(jié)構(gòu)。BITMAPINFOHEADER結(jié)構(gòu)和顏色遮罩都在DIBSECTION結(jié)構(gòu)中有效,,而且從CreateDIBSection函式傳回指向圖素位元的指標,,這時通過呼叫GetDIBColorTable和SetDIBColorTable,,就只能間接存取DIB顏色表。這些功能都封裝到DIBHELP的DibGetColor和DibSetColor函式裡頭了,。 在DIBHELP.C的後面,,檔案DibCopyToInfo配置一個指向BITMAPINFO結(jié)構(gòu)的指標,並填充資訊,,但是那與獲得指向記憶體中現(xiàn)存結(jié)構(gòu)的指標不完全相同,。 |
|
來自: alal51 > 《調(diào)色板》