建立和轉(zhuǎn)換 程式16-21所示的DIBHELP第三部分和最後部分展示了如何建立DIB區(qū)塊,,以及如何將DIB區(qū)塊與packed DIB相互轉(zhuǎn)換,。 程式16-21 DIBHELP.C檔案的第三部分和最後部分 DIBHELP.C (第三部分) /*-------------------------------------------------------------------------- Calculating shift values from color masks is required by the DibCreateFromInfo function. ----------------------------------------------------------------------------*/ static int MaskToRShift (DWORD dwMask) { int iShift ; if (dwMask == 0) return 0 ; for (iShift = 0 ; !(dwMask & 1) ; iShift++) dwMask >>= 1 ; return iShift ; } static int MaskToLShift (DWORD dwMask) { int iShift ; if (dwMask == 0) return 0 ; while (!(dwMask & 1)) dwMask >>= 1 ; for (iShift = 0 ; dwMask & 1 ; iShift++) dwMask >>= 1 ; return 8 - iShift ; } /*---------------------------------------------------------------------------- DibCreateFromInfo: All DIB creation functions ultimately call this one. This function is responsible for calling CreateDIBSection, allocating memory for DIBSTRUCT, and setting up the row pointer. -----------------------------------------------------------------------------*/ HDIB DibCreateFromInfo (BITMAPINFO * pbmi) { BYTE * pBits ; DIBSTRUCT * pdib ; HBITMAP hBitmap ; int i, iRowLength, cy, y ; hBitmap = CreateDIBSection (NULL, pbmi, DIB_RGB_COLORS, &pBits, NULL, 0) ; if (hBitmap == NULL) return NULL ; if (NULL == (pdib = malloc (sizeof (DIBSTRUCT)))) { DeleteObject (hBitmap) ; return NULL ; } pdib->iSignature = HDIB_SIGNATURE ; pdib->hBitmap = hBitmap ; pdib->pBits = pBits ; GetObject (hBitmap, sizeof (DIBSECTION), &pdib->ds) ; // Notice that we can now use the DIB information functions // defined above. // If the compression is BI_BITFIELDS, calculate shifts from masks if (DibCompression (pdib) == BI_BITFIELDS) { for (i = 0 ; i < 3 ; i++) { pdib->iLShift[i] = MaskToLShift (pdib->ds.dsBitfields[i]) ; pdib->iRShift[i] = MaskToRShift (pdib->ds.dsBitfields[i]) ; } } // If the compression is BI_RGB, but bit-count is 16 or 32, // set the bitfields and the masks else if (DibCompression (pdib) == BI_RGB) { if (DibBitCount (pdib) == 16) { pdib->ds.dsBitfields[0] = 0x00007C00 ; pdib->ds.dsBitfields[1] = 0x000003E0 ; pdib->ds.dsBitfields[2] = 0x0000001F ; pdib->iRShift [0] = 10 ; pdib->iRShift [1] = 5 ; pdib->iRShift [2] = 0 ; pdib->iLShift [0] = 3 ; pdib->iLShift [1] = 3 ; pdib->iLShift [2] = 3 ; } else if (DibBitCount (pdib) == 24 || DibBitCount (pdib) == 32) { pdib->ds.dsBitfields[0] = 0x00FF0000 ; pdib->ds.dsBitfields[1] = 0x0000FF00 ; pdib->ds.dsBitfields[2] = 0x000000FF ; pdib->iRShift [0] = 16 ; pdib->iRShift [1] = 8 ; pdib->iRShift [2] = 0 ; pdib->iLShift [0] = 0 ; pdib->iLShift [1] = 0 ; pdib->iLShift [2] = 0 ; } } // Allocate an array of pointers to each row in the DIB cy = DibHeight (pdib) ; if (NULL == (pdib->ppRow = malloc (cy * sizeof (BYTE *)))) { free (pdib) ; DeleteObject (hBitmap) ; return NULL ; } // Initialize them. iRowLength = DibRowLength (pdib) ; if (pbmi->bmiHeader.biHeight > 0) // ie, bottom up { for (y = 0 ; y < cy ; y++) pdib->ppRow[y] = pBits + (cy - y - 1) * iRowLength ; } else // top down { for (y = 0 ; y < cy ; y++) pdib->ppRow[y] = pBits + y * iRowLength ; } return pdib ; } /*-------------------------------------------------------------------------- DibDelete: Frees all memory for the DIB section ----------------------------------------------------------------------------*/ BOOL DibDelete (HDIB hdib) { DIBSTRUCT * pdib = hdib ; if (!DibIsValid (hdib)) return FALSE ; free (pdib->ppRow) ; DeleteObject (pdib->hBitmap) ; free (pdib) ; return TRUE ; } /*---------------------------------------------------------------------------- DibCreate: Creates an HDIB from explicit arguments -----------------------------------------------------------------------------*/ HDIB DibCreate (int cx, int cy, int cBits, int cColors) { BITMAPINFO * pbmi ; DWORD dwInfoSize ; HDIB hDib ; int cEntries ; if (cx <= 0 || cy <= 0 || ((cBits != 1) && (cBits != 4) && (cBits != 8) && (cBits != 16) && (cBits != 24) && (cBits != 32))) { return NULL ; } if ( cColors != 0) cEntries = cColors ; else if (cBits <= 8) cEntries = 1 << cBits ; dwInfoSize = sizeof (BITMAPINFOHEADER) + (cEntries - 1) * sizeof (RGBQUAD); if (NULL == (pbmi = malloc (dwInfoSize))) { return NULL ; } ZeroMemory (pbmi, dwInfoSize) ; pbmi->bmiHeader.biSize = sizeof (BITMAPINFOHEADER) ; pbmi->bmiHeader.biWidth = cx ; pbmi->bmiHeader.biHeight = cy ; pbmi->bmiHeader.biPlanes = 1 ; pbmi->bmiHeader.biBitCount = cBits ; pbmi->bmiHeader.biCompression = BI_RGB ; pbmi->bmiHeader.biSizeImage = 0 ; pbmi->bmiHeader.biXPelsPerMeter = 0 ; pbmi->bmiHeader.biYPelsPerMeter = 0 ; pbmi->bmiHeader.biClrUsed = cColors ; pbmi->bmiHeader.biClrImportant = 0 ; hDib = DibCreateFromInfo (pbmi) ; free (pbmi) ; return hDib ; } /*---------------------------------------------------------------------------- DibCopyToInfo: Builds BITMAPINFO structure. Used by DibCopy and DibCopyToDdb -----------------------------------------------------------------------------*/ static BITMAPINFO * DibCopyToInfo (HDIB hdib) { BITMAPINFO * pbmi ; int i, iNumColors ; RGBQUAD * prgb ; if (!DibIsValid (hdib)) return NULL ; // Allocate the memory if (NULL == (pbmi = malloc (DibInfoSize (hdib)))) return NULL ; // Copy the information header CopyMemory (pbmi, DibInfoHeaderPtr (hdib), sizeof (BITMAPINFOHEADER)); // Copy the possible color masks prgb = (RGBQUAD *) ((BYTE *) pbmi + sizeof (BITMAPINFOHEADER)) ; if (DibMaskSize (hdib)) { CopyMemory (prgb, DibMaskPtr (hdib), 3 * sizeof (DWORD)) ; prgb = (RGBQUAD *) ((BYTE *) prgb + 3 * sizeof (DWORD)) ; } // Copy the color table iNumColors = DibNumColors (hdib) ; for (i = 0 ; i < iNumColors ; i++) DibGetColor (hdib, i, prgb + i) ; return pbmi ; } /*-------------------------------------------------------------------------- DibCopy: Creates a new DIB section from an existing DIB section, possibly swapping the DIB width and height. ---------------------------------------------------------------------------*/ HDIB DibCopy (HDIB hdibSrc, BOOL fRotate) { BITMAPINFO * pbmi ; BYTE * pBitsSrc, * pBitsDst ; HDIB hdibDst ; if (!DibIsValid (hdibSrc)) return NULL ; if (NULL == (pbmi = DibCopyToInfo (hdibSrc))) return NULL ; if (fRotate) { pbmi->bmiHeader.biWidth = DibHeight (hdibSrc) ; pbmi->bmiHeader.biHeight = DibWidth (hdibSrc) ; } hdibDst = DibCreateFromInfo (pbmi) ; free (pbmi) ; if ( hdibDst == NULL) return NULL ; // Copy the bits if (!fRotate) { pBitsSrc = DibBitsPtr (hdibSrc) ; pBitsDst = DibBitsPtr (hdibDst) ; CopyMemory (pBitsDst, pBitsSrc, DibBitsSize (hdibSrc)) ; } return hdibDst ; } /*---------------------------------------------------------------------------- DibCopyToPackedDib is generally used for saving DIBs and for transferring DIBs to the clipboard. In the second case, the second argument should be set to TRUE so that the memory is allocated with the GMEM_SHARE flag. -----------------------------------------------------------------------------*/ BITMAPINFO * DibCopyToPackedDib (HDIB hdib, BOOL fUseGlobal) { BITMAPINFO * pPackedDib ; BYTE * pBits ; DWORD dwDibSize ; HDC hdcMem ; HGLOBAL hGlobal ; int iNumColors ; PDIBSTRUCT pdib = hdib ; RGBQUAD * prgb ; if (!DibIsValid (hdib)) return NULL ; // Allocate memory for packed DIB dwDibSize = DibTotalSize (hdib) ; if (fUseGlobal) { hGlobal = GlobalAlloc (GHND | GMEM_SHARE, dwDibSize) ; pPackedDib = GlobalLock (hGlobal) ; } else { pPackedDib = malloc (dwDibSize) ; } if (pPackedDib == NULL) return NULL ; // Copy the information header CopyMemory (pPackedDib, &pdib->ds.dsBmih, sizeof (BITMAPINFOHEADER)) ; prgb = (RGBQUAD *) ((BYTE *) pPackedDib + sizeof (BITMAPINFOHEADER)) ; // Copy the possible color masks if (pdib->ds.dsBmih.biCompression == BI_BITFIELDS) { CopyMemory (prgb, pdib->ds.dsBitfields, 3 * sizeof (DWORD)) ; prgb = (RGBQUAD *) ((BYTE *) prgb + 3 * sizeof (DWORD)) ; } // Copy the color table if (iNumColors = DibNumColors (hdib)) { hdcMem = CreateCompatibleDC (NULL) ; SelectObject (hdcMem, pdib->hBitmap) ; GetDIBColorTable (hdcMem, 0, iNumColors, prgb) ; DeleteDC (hdcMem) ; } pBits = (BYTE *) (prgb + iNumColors) ; // Copy the bits CopyMemory (pBits, pdib->pBits, DibBitsSize (pdib)) ; // If last argument is TRUE, unlock global memory block and // cast it to pointer in preparation for return if (fUseGlobal) { GlobalUnlock (hGlobal) ; pPackedDib = (BITMAPINFO *) hGlobal ; } return pPackedDib ; } /*-------------------------------------------------------------------------- DibCopyFromPackedDib is generally used for pasting DIBs from the clipboard. ------------------------------------------------------------------------*/ HDIB DibCopyFromPackedDib (BITMAPINFO * pPackedDib) { BYTE * pBits ; DWORD dwInfoSize, dwMaskSize, dwColorSize ; int iBitCount ; PDIBSTRUCT pdib ; // Get the size of the information header and do validity check dwInfoSize = pPackedDib->bmiHeader.biSize ; if ( dwInfoSize != sizeof (BITMAPCOREHEADER) && dwInfoSize != sizeof (BITMAPINFOHEADER) && dwInfoSize != sizeof (BITMAPV4HEADER) && dwInfoSize != sizeof (BITMAPV5HEADER)) { return NULL ; } // Get the possible size of the color masks if (dwInfoSize == sizeof (BITMAPINFOHEADER) && pPackedDib->bmiHeader.biCompression == BI_BITFIELDS) { dwMaskSize = 3 * sizeof (DWORD) ; } else { dwMaskSize = 0 ; } // Get the size of the color table if (dwInfoSize == sizeof (BITMAPCOREHEADER)) { iBitCount = ((BITMAPCOREHEADER *) pPackedDib)->bcBitCount ; if (iBitCount <= 8) { dwColorSize = (1 << iBitCount) * sizeof (RGBTRIPLE) ; } else dwColorSize = 0 ; } else // all non-OS/2 compatible DIBs { if (pPackedDib->bmiHeader.biClrUsed > 0) { dwColorSize = pPackedDib->bmiHeader.biClrUsed * sizeof (RGBQUAD); } else if (pPackedDib->bmiHeader.biBitCount <= 8) { dwColorSize = (1 << pPackedDib->bmiHeader.biBitCount) * sizeof (RGBQUAD) ; } else { dwColorSize = 0 ; } } // Finally, get the pointer to the bits in the packed DIB pBits = (BYTE *) pPackedDib + dwInfoSize + dwMaskSize + dwColorSize ; // Create the HDIB from the packed-DIB pointer pdib = DibCreateFromInfo (pPackedDib) ; // Copy the pixel bits CopyMemory (pdib->pBits, pBits, DibBitsSize (pdib)) ; return pdib ; } /*---------------------------------------------------------------------------- DibFileLoad: Creates a DIB section from a DIB file -----------------------------------------------------------------------------*/ HDIB DibFileLoad (const TCHAR * szFileName) { BITMAPFILEHEADER bmfh ; BITMAPINFO * pbmi ; BOOL bSuccess ; DWORD dwInfoSize, dwBitsSize, dwBytesRead ; HANDLE hFile ; HDIB hDib ; // Open the file: read access, prohibit write access hFile = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL) ; if (hFile == INVALID_HANDLE_VALUE) return NULL ; // Read in the BITMAPFILEHEADER bSuccess = ReadFile ( hFile, &bmfh, sizeof (BITMAPFILEHEADER), &dwBytesRead, NULL) ; if (!bSuccess || (dwBytesRead != sizeof (BITMAPFILEHEADER)) || (bmfh.bfType != * (WORD *) "BM")) { CloseHandle (hFile) ; return NULL ; } // Allocate memory for the information structure & read it in dwInfoSize = bmfh.bfOffBits - sizeof (BITMAPFILEHEADER) ; if (NULL == (pbmi = malloc (dwInfoSize))) { CloseHandle (hFile) ; return NULL ; } bSuccess = ReadFile (hFile, pbmi, dwInfoSize, &dwBytesRead, NULL) ; if (!bSuccess || (dwBytesRead != dwInfoSize)) { CloseHandle (hFile) ; free (pbmi) ; return NULL ; } // Create the DIB hDib = DibCreateFromInfo (pbmi) ; free (pbmi) ; if (hDib == NULL) { CloseHandle (hFile) ; return NULL ; } // Read in the bits dwBitsSize = bmfh.bfSize - bmfh.bfOffBits ; bSuccess = ReadFile ( hFile, ((PDIBSTRUCT) hDib)->pBits, dwBitsSize, &dwBytesRead, NULL) ; CloseHandle (hFile) ; if (!bSuccess || (dwBytesRead != dwBitsSize)) { DibDelete (hDib) ; return NULL ; } return hDib ; } /*-------------------------------------------------------------------------- DibFileSave: Saves a DIB section to a file ----------------------------------------------------------------------------*/ BOOL DibFileSave (HDIB hdib, const TCHAR * szFileName) { BITMAPFILEHEADER bmfh ; BITMAPINFO * pbmi ; BOOL bSuccess ; DWORD dwTotalSize, dwBytesWritten ; HANDLE hFile ; hFile = CreateFile (szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) ; if (hFile == INVALID_HANDLE_VALUE) return FALSE ; dwTotalSize = DibTotalSize (hdib) ; bmfh.bfType = * (WORD *) "BM" ; bmfh.bfSize = sizeof (BITMAPFILEHEADER) + dwTotalSize ; bmfh.bfReserved1 = 0 ; bmfh.bfReserved2 = 0 ; bmfh.bfOffBits = bmfh.bfSize - DibBitsSize (hdib) ; // Write the BITMAPFILEHEADER bSuccess = WriteFile ( hFile, &bmfh, sizeof (BITMAPFILEHEADER), &dwBytesWritten, NULL) ; if (!bSuccess || (dwBytesWritten != sizeof (BITMAPFILEHEADER))) { CloseHandle (hFile) ; DeleteFile (szFileName) ; return FALSE ; } // Get entire DIB in packed-DIB format if (NULL == (pbmi = DibCopyToPackedDib (hdib, FALSE))) { CloseHandle (hFile) ; DeleteFile (szFileName) ; return FALSE ; } // Write out the packed DIB bSuccess = WriteFile (hFile, pbmi, dwTotalSize, &dwBytesWritten, NULL) ; CloseHandle (hFile) ; free (pbmi) ; if (!bSuccess || (dwBytesWritten != dwTotalSize)) { DeleteFile (szFileName) ; return FALSE ; } return TRUE ; } /*--------------------------------------------------------------------------- DibCopyToDdb: For more efficient screen displays ---------------------------------------------------------------------------*/ HBITMAP DibCopyToDdb (HDIB hdib, HWND hwnd, HPALETTE hPalette) { BITMAPINFO * pbmi ; HBITMAP hBitmap ; HDC hdc ; if (!DibIsValid (hdib)) return NULL ; if (NULL == (pbmi = DibCopyToInfo (hdib))) return NULL ; hdc = GetDC (hwnd) ; if (hPalette) { SelectPalette (hdc, hPalette, FALSE) ; RealizePalette (hdc) ; } hBitmap = CreateDIBitmap (hdc, DibInfoHeaderPtr (hdib), CBM_INIT, DibBitsPtr (hdib), pbmi, DIB_RGB_COLORS) ; ReleaseDC (hwnd, hdc) ; free (pbmi) ; return hBitmap ; } 這部分的DIBHELP.C檔案從兩個小函式開始,,這兩個函式根據(jù)16位元和32位元DIB的顏色遮罩得到左、右移位值,。這些函式在 第十五章「顏色遮罩」 一節(jié)說明,。 DibCreateFromInfo函式是DIBHELP中唯一呼叫CreateDIBSection並為DIBSTRUCT結(jié)構(gòu)配置記憶體的函式。其他所有建立和複製函式都重複此函式,。DibCreateFromInfo唯一的參數(shù)是指向BITMAPINFO結(jié)構(gòu)的指標,。此結(jié)構(gòu)的顏色表必須存在,但是它不必用有效的值填充,。呼叫CreateDIBSection之後,,該函式將初始化DIBSTRUCT結(jié)構(gòu)的所有欄位。注意,,在設(shè)定DIBSTRUCT結(jié)構(gòu)的ppRow欄位的值時(指向DIB行位址的指標),,DIB有由下而上和由上而下的不同儲存方式。ppRow開頭的元素就是DIB的頂行,。 DibDelete刪除DibCreateFromInfo中建立的點陣圖,,同時釋放在該函式中配置的記憶體。 DibCreate可能比DibCreateFromInfo更像一個從應用程式呼叫的函式,。前三個參數(shù)提供圖素的寬度,、高度和每圖素的位數(shù)。最後一個參數(shù)可以設(shè)定為0(用於顏色表的內(nèi)定尺寸),,或者設(shè)定為非0(表示比每圖素位元數(shù)所需要的顏色表更小的顏色表),。 DibCopy函式根據(jù)現(xiàn)存的DIB區(qū)塊建立新的DIB區(qū)塊,並用DibCreateInfo函式為BITMAPINFO結(jié)構(gòu)配置了記憶體,,還填了所有的資料,。DibCopy函式的一個BOOL參數(shù)指出是否在建立新的DIB時交換了DIB的寬度和高度。我們將在後面看到此函式的用法,。 DibCopyToPackedDib和DibCopyFromPackedDib函式的使用通常與透過剪貼簿傳遞DIB相關(guān),。DibFileLoad函式從DIB檔案建立DIB區(qū)塊;DibFileSave函式將資料儲存到DIB檔案,。 最後,,DibCopyToDdb函式根據(jù)DIB建立GDI點陣圖物件。注意,該函式需要目前調(diào)色盤的代號和程式視窗的代號,。程式視窗代號用於獲得選進並顯現(xiàn)調(diào)色盤的裝置內(nèi)容,。只有這樣,函式才可以呼叫CreateDIBitmap,。這曾在本章前面的SHOWDIB7中展示,。 DIBHELP表頭檔案和巨集 DIBHELP.H表頭檔案如程式16-22所示。 程式16-22 DIBHELP.H檔案 DIBHELP.H /*-------------------------------------------------------------------------- DIBHELP.H header file for DIBHELP.C ----------------------------------------------------------------------------*/ typedef void * HDIB ; // Functions in DIBHELP.C BOOL DibIsValid (HDIB hdib) ; HBITMAP DibBitmapHandle (HDIB hdib) ; int DibWidth (HDIB hdib) ; int DibHeight (HDIB hdib) ; int DibBitCount (HDIB hdib) ; int DibRowLength (HDIB hdib) ; int DibNumColors (HDIB hdib) ; DWORD DibMask (HDIB hdib, int i) ; int DibRShift (HDIB hdib, int i) ; int DibLShift (HDIB hdib, int i) ; int DibCompression (HDIB hdib) ; BOOL DibIsAddressable (HDIB hdib) ; DWORD DibInfoHeaderSize (HDIB hdib) ; DWORD DibMaskSize (HDIB hdib) ; DWORD DibColorSize (HDIB hdib) ; DWORD DibInfoSize (HDIB hdib) ; DWORD DibBitsSize (HDIB hdib) ; DWORD DibTotalSize (HDIB hdib) ; BITMAPINFOHEADER * DibInfoHeaderPtr (HDIB hdib) ; DWORD * DibMaskPtr (HDIB hdib) ; void * DibBitsPtr (HDIB hdib) ; BOOL DibGetColor (HDIB hdib, int index, RGBQUAD * prgb) ; BOOL DibSetColor (HDIB hdib, int index, RGBQUAD * prgb) ; BYTE * DibPixelPtr (HDIB hdib, int x, int y) ; DWORD DibGetPixel (HDIB hdib, int x, int y) ; BOOL DibSetPixel (HDIB hdib, int x, int y, DWORD dwPixel) ; BOOL DibGetPixelColor (HDIB hdib, int x, int y, RGBQUAD * prgb) ; BOOL DibSetPixelColor (HDIB hdib, int x, int y, RGBQUAD * prgb) ; HDIB DibCreateFromInfo (BITMAPINFO * pbmi) ; BOOL DibDelete (HDIB hdib) ; HDIB DibCreate (int cx, int cy, int cBits, int cColors) ; HDIB DibCopy (HDIB hdibSrc, BOOL fRotate) ; BITMAPINFO * DibCopyToPackedDib (HDIB hdib, BOOL fUseGlobal) ; HDIB DibCopyFromPackedDib (BITMAPINFO * pPackedDib) ; HDIB DibFileLoad (const TCHAR * szFileName) ; BOOL DibFileSave (HDIB hdib, const TCHAR * szFileName) ; HBITMAP DibCopyToDdb (HDIB hdib, HWND hwnd, HPALETTE hPalette) ; HDIB DibCreateFromDdb (HBITMAP hBitmap) ; /*--------------------------------------------------------------------------- Quickie no-bounds-checked pixel gets and sets -----------------------------------------------------------------------------*/ #define DibPixelPtr1(hdib, x, y) (((* (PBYTE **) hdib) [y]) + ((x) >> 3)) #define DibPixelPtr4(hdib, x, y) (((* (PBYTE **) hdib) [y]) + ((x) >> 1)) #define DibPixelPtr8(hdib, x, y) (((* (PBYTE **) hdib) [y]) + (x) ) #define DibPixelPtr16(hdib, x, y) ((WORD *) (((* (PBYTE **) hdib) [y]) + (x) * 2)) #define DibPixelPtr24(hdib, x, y) ((RGBTRIPLE *) (((* (PBYTE **) hdib) [y]) + (x) * 3)) #define DibPixelPtr32(hdib, x, y) ((DWORD *) (((* (PBYTE **) hdib) [y]) + (x) * 4)) #define DibGetPixel1(hdib, x, y) (0x01 & (* DibPixelPtr1 (hdib, x, y) >> (7 - ((x) & 7)))) #define DibGetPixel4(hdib, x, y) (0x0F & (* DibPixelPtr4 (hdib, x, y) >> ((x) & 1 ? 0 : 4))) #define DibGetPixel8(hdib, x, y) (* DibPixelPtr8 (hdib, x, y)) #define DibGetPixel16(hdib, x, y) (* DibPixelPtr16 (hdib, x, y)) #define DibGetPixel24(hdib, x, y) (* DibPixelPtr24 (hdib, x, y)) #define DibGetPixel32(hdib, x, y) (* DibPixelPtr32 (hdib, x, y)) #define DibSetPixel1(hdib, x, y, p) ((* DibPixelPtr1 (hdib, x, y) &= ~( 1 << (7 - ((x) & 7)))), (* DibPixelPtr1 (hdib, x, y) |= ((p) << (7 - ((x) & 7))))) #define DibSetPixel4(hdib, x, y, p) ((* DibPixelPtr4 (hdib, x, y) &= (0x0F << ((x) & 1 ? 4 : 0))), (* DibPixelPtr4 (hdib, x, y) |= ((p) << ((x) & 1 ? 0 : 4)))) #define DibSetPixel8(hdib, x, y, p) (* DibPixelPtr8 (hdib, x, y) = p) #define DibSetPixel16(hdib, x, y, p) (* DibPixelPtr16 (hdib, x, y) = p) #define DibSetPixel24(hdib, x, y, p) (* DibPixelPtr24 (hdib, x, y) = p) #define DibSetPixel32(hdib, x, y, p) (* DibPixelPtr32 (hdib, x, y) = p) 這個表頭檔案將HDIB定義為空指標(void* ),。應用程式的確不需要瞭解HDIB所指結(jié)構(gòu)的內(nèi)部結(jié)構(gòu),。此表頭檔案還包括DIBHELP.C中所有函式的說明,還有一些巨集-非常特殊的巨集,。 如果再看一看DIBHELP.C中的DibPixelPtr,、DibGetPixel和DibSetPixel函式,並試圖提高它們的執(zhí)行速度表現(xiàn),,那麼您將看到兩種可能的解決方法,。第一種,可以刪除所有的檢查保護,,並相信應用程式不會使用無效參數(shù)呼叫函式,。還可以刪除一些函式呼叫,例如DibBitCount,,並使用指向DIBSTRUCT結(jié)構(gòu)內(nèi)部的指標來直接獲得資訊,。 提高執(zhí)行速度表現(xiàn)另一項較不明顯的方法是刪除所有對每圖素位元數(shù)的處理方式,同時分離出處理不同DIB函式-例如DibGetPixel1,、DibGetPixel4、DibGetPixel8等等,。下一個最佳化步驟是刪除整個函式呼叫,,將其處理動作透過inline function或巨集中進行合併。 DIBHELP.H採用巨集的方法,。它依據(jù)DibPixelPtr,、DibGetPixel和DibSetPixel函式提出了三套巨集。這些巨集都明確對應於特殊的圖素位元數(shù),。 DIBBLE程式 DIBBLE程式,,如程式16-23所示,使用DIBHELP函式和巨集工作,。儘管DIBBLE是本書中最長的程式,,它確實只是一些作業(yè)的粗略範例,這些作業(yè)可以在簡單的數(shù)位影像處理程式中找到,。對DIBBLE的明顯改進是轉(zhuǎn)換成了多重文件介面(MDI:multiple document interface),,我們將在 第十九章 學習有關(guān)多重文件介面的知識。 程式16-23 DIBBLE DIBBLE.C /*--------------------------------------------------------------------------- DIBBLE.C -- Bitmap and Palette Program (c) Charles Petzold, 1998 -----------------------------------------------------------------------------*/ #include <windows.h> #include "dibhelp.h" #include "dibpal.h" #include "dibconv.h" #include "resource.h" #define WM_USER_SETSCROLLS (WM_USER + 1) #define WM_USER_DELETEDIB (WM_USER + 2) #define WM_USER_DELETEPAL (WM_USER + 3) #define WM_USER_CREATEPAL (WM_USER + 4) LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; TCHAR szAppName[] = TEXT ("Dibble") ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HACCEL hAccel ; HWND hwnd ; MSG msg ; WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = szAppName ; wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass)) { MessageBox ( NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ; return 0 ; } hwnd = CreateWindow ( szAppName, szAppName, WS_OVERLAPPEDWINDOW | WM_VSCROLL | WM_HSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ; ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; hAccel = LoadAccelerators (hInstance, szAppName) ; while (GetMessage (&msg, NULL, 0, 0)) { if (!TranslateAccelerator (hwnd, hAccel, &msg)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } } return msg.wParam ; } /*---------------------------------------------------------------------------- DisplayDib: Displays or prints DIB actual size or stretched depending on menu selection -----------------------------------------------------------------------------*/ int DisplayDib ( HDC hdc, HBITMAP hBitmap, int x, int y, int cxClient, int cyClient, WORD wShow, BOOL fHalftonePalette) { BITMAP bitmap ; HDC hdcMem ; int cxBitmap, cyBitmap, iReturn ; GetObject (hBitmap, sizeof (BITMAP), &bitmap) ; cxBitmap = bitmap.bmWidth ; cyBitmap = bitmap.bmHeight ; SaveDC (hdc) ; if (fHalftonePalette) SetStretchBltMode (hdc, HALFTONE) ; else SetStretchBltMode (hdc, COLORONCOLOR) ; hdcMem = CreateCompatibleDC (hdc) ; SelectObject (hdcMem, hBitmap) ; switch (wShow) { case IDM_SHOW_NORMAL: if (fHalftonePalette) iReturn = StretchBlt (hdc, 0, 0, min (cxClient, cxBitmap - x), min (cyClient, cyBitmap - y), hdcMem, x, y, min (cxClient, cxBitmap - x), min (cyClient, cyBitmap - y), SRCCOPY); else iReturn = BitBlt (hdc,0, 0, min (cxClient, cxBitmap - x), min (cyClient, cyBitmap - y), hdcMem, x, y, SRCCOPY) ; break ; case IDM_SHOW_CENTER: if (fHalftonePalette) iReturn = StretchBlt ( hdc, (cxClient - cxBitmap) / 2, (cyClient - cyBitmap) / 2, cxBitmap, cyBitmap, hdcMem, 0, 0, cxBitmap, cyBitmap, SRCCOPY); else iReturn = BitBlt (hdc, (cxClient - cxBitmap) / 2, cyClient - cyBitmap) / 2, cxBitmap, cyBitmap, hdcMem, 0, 0, SRCCOPY) ; break ; case IDM_SHOW_STRETCH: iReturn = StretchBlt (hdc, 0, 0, cxClient, cyClient, hdcMem, 0, 0, cxBitmap, cyBitmap, SRCCOPY) ; break ; case IDM_SHOW_ISOSTRETCH: SetMapMode (hdc, MM_ISOTROPIC) ; SetWindowExtEx (hdc, cxBitmap, cyBitmap, NULL) ; SetViewportExtEx (hdc, cxClient, cyClient, NULL) ; SetWindowOrgEx (hdc, cxBitmap / 2, cyBitmap / 2, NULL) ; SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ; iReturn = StretchBlt (hdc, 0, 0, cxBitmap, cyBitmap, hdcMem, 0, 0, cxBitmap, cyBitmap, SRCCOPY) ; break ; } DeleteDC (hdcMem) ; RestoreDC (hdc, -1) ; return iReturn ; } /*--------------------------------------------------------------------------- DibFlipHorizontal: Calls non-optimized DibSetPixel and DibGetPixel ----------------------------------------------------------------------------*/ HDIB DibFlipHorizontal (HDIB hdibSrc) { HDIB hdibDst ; int cx, cy, x, y ; if (!DibIsAddressable (hdibSrc)) return NULL ; if (NULL == (hdibDst = DibCopy (hdibSrc, FALSE))) return NULL ; cx = DibWidth (hdibSrc) ; cy = DibHeight (hdibSrc) ; for (x = 0 ; x < cx ; x++) for (y = 0 ; y < cy ; y++) { DibSetPixel (hdibDst, x, cy - 1 - y, DibGetPixel (hdibSrc, x, y)) ; } return hdibDst ; } /*--------------------------------------------------------------------------- DibRotateRight: Calls optimized DibSetPixelx and DibGetPixelx -----------------------------------------------------------------------------*/ HDIB DibRotateRight (HDIB hdibSrc) { HDIB hdibDst ; int cx, cy, x, y ; if (!DibIsAddressable (hdibSrc)) return NULL ; if (NULL == (hdibDst = DibCopy (hdibSrc, TRUE))) return NULL ; cx = DibWidth (hdibSrc) ; cy = DibHeight (hdibSrc) ; switch (DibBitCount (hdibSrc)) { case 1: for ( x = 0 ; x < cx ; x++) for ( y = 0 ; y < cy ; y++) DibSetPixel1 (hdibDst, cy - y - 1, x, DibGetPixel1 (hdibSrc, x, y)) ; break ; case 4: for ( x = 0 ; x < cx ; x++) for ( y = 0 ; y < cy ; y++) DibSetPixel4 (hdibDst, cy - y - 1, x, DibGetPixel4 (hdibSrc, x, y)) ; break ; case 8: for ( x = 0 ; x < cx ; x++) for ( y = 0 ; y < cy ; y++) DibSetPixel8 (hdibDst, cy - y - 1, x, DibGetPixel8 (hdibSrc, x, y)) ; break ; case 16: for (x = 0 ; x < cx ; x++) for (y = 0 ; y < cy ; y++) DibSetPixel16 (hdibDst, cy - y - 1, x, DibGetPixel16 (hdibSrc, x, y)) ; break ; case 24: for (x = 0 ; x < cx ; x++) for (y = 0 ; y < cy ; y++) DibSetPixel24 (hdibDst, cy - y - 1, x, DibGetPixel24 (hdibSrc, x, y)) ; break ; case 32: for (x = 0 ; x < cx ; x++) for (y = 0 ; y < cy ; y++) DibSetPixel32 (hdibDst, cy - y - 1, x, DibGetPixel32 (hdibSrc, x, y)) ; break ; } return hdibDst ; } /*------------------------------------------------------------------------ PaletteMenu: Uncheck and check menu item on palette menu --------------------------------------------------------------------------*/ void PaletteMenu (HMENU hMenu, WORD wItemNew) { static WORD wItem = IDM_PAL_NONE ; CheckMenuItem (hMenu, wItem, MF_UNCHECKED) ; wItem = wItemNew ; CheckMenuItem (hMenu, wItem, MF_CHECKED) ; } LRESULT CALLBACK WndProc ( HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam) { static BOOL fHalftonePalette ; static DOCINFO di = {sizeof(DOCINFO),TEXT("Dibble:Printing")} ; static HBITMAP hBitmap ; static HDIB hdib ; static HMENU hMenu ; static HPALETTE hPalette ; static int cxClient, cyClient, iVscroll, iHscroll ; static OPENFILENAME ofn ; static PRINTDLG printdlg = { sizeof (PRINTDLG) } ; static TCHAR szFileName [MAX_PATH], szTitleName [MAX_PATH] ; static TCHAR szFilter[]= TEXT ("Bitmap Files (*.BMP)\0*.bmp\0") TEXT ("All Files (*.*)\0*.*\0\0") ; static TCHAR * szCompression[] = { TEXT("BI_RGB"),TEXT("BI_RLE8"),TEXT("BI_RLE4"), TEXT("BI_BITFIELDS"),TEXT("Unknown")} ; static WORD wShow = IDM_SHOW_NORMAL ; BOOL fSuccess ; BYTE * pGlobal ; HDC hdc, hdcPrn ; HGLOBAL hGlobal ; HDIB hdibNew ; int iEnable, cxPage, cyPage, iConvert ; PAINTSTRUCT ps ; SCROLLINFO si ; TCHAR szBuffer [256] ; switch (message) { case WM_CREATE: // Save the menu handle in a static variable hMenu = GetMenu (hwnd) ; // Initialize the OPENFILENAME structure for the File Open // and File Save dialog boxes. ofn.lStructSize = sizeof (OPENFILENAME) ; ofn.hwndOwner = hwnd ; ofn.hInstance = NULL ; ofn.lpstrFilter = szFilter ; ofn.lpstrCustomFilter = NULL ; ofn.nMaxCustFilter = 0 ; ofn.nFilterIndex = 0 ; ofn.lpstrFile = szFileName ; ofn.nMaxFile = MAX_PATH ; ofn.lpstrFileTitle = szTitleName ; ofn.nMaxFileTitle = MAX_PATH ; ofn.lpstrInitialDir = NULL ; ofn.lpstrTitle = NULL ; ofn.Flags = OFN_OVERWRITEPROMPT ; ofn.nFileOffset = 0 ; ofn.nFileExtension = 0 ; ofn.lpstrDefExt = TEXT ("bmp") ; ofn.lCustData = 0 ; ofn.lpfnHook = NULL ; ofn.lpTemplateName = NULL ; return 0 ; case WM_DISPLAYCHANGE: SendMessage (hwnd, WM_USER_DELETEPAL, 0, 0) ; SendMessage (hwnd, WM_USER_CREATEPAL, TRUE, 0) ; return 0 ; case WM_SIZE: // Save the client area width and height in static variables. cxClient = LOWORD (lParam) ; cyClient = HIWORD (lParam) ; wParam = FALSE ; // fall through // WM_USER_SETSCROLLS: Programmer-defined Message! // Set the scroll bars. If the display mode is not normal, // make them invisible. If wParam is TRUE, reset the // scroll bar position. case WM_USER_SETSCROLLS: if (hdib == NULL || wShow != IDM_SHOW_NORMAL) { si.cbSize = sizeof (SCROLLINFO) ; si.fMask = SIF_RANGE ; si.nMin = 0 ; si.nMax = 0 ; SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ; SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ; } else { // First the vertical scroll si.cbSize = sizeof (SCROLLINFO) ; si.fMask = SIF_ALL ; GetScrollInfo (hwnd, SB_VERT, &si) ; si.nMin = 0 ; si.nMax = DibHeight (hdib) ; si.nPage = cyClient ; if ((BOOL) wParam) si.nPos = 0 ; SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ; GetScrollInfo (hwnd, SB_VERT, &si) ; iVscroll = si.nPos ; // Then the horizontal scroll GetScrollInfo (hwnd, SB_HORZ, &si) ; si.nMin = 0 ; si.nMax = DibWidth (hdib) ; si.nPage = cxClient ; if ((BOOL) wParam) si.nPos = 0 ; SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ; GetScrollInfo (hwnd, SB_HORZ, &si) ; iHscroll = si.nPos ; } return 0 ; // WM_VSCROLL: Vertically scroll the DIB case WM_VSCROLL: si.cbSize = sizeof (SCROLLINFO) ; si.fMask = SIF_ALL ; GetScrollInfo (hwnd, SB_VERT, &si) ; iVscroll = si.nPos ; switch (LOWORD (wParam)) { case SB_LINEUP: si.nPos - = 1 ; break ; case SB_LINEDOWN: si.nPos + = 1 ; break ; case SB_PAGEUP: si.nPos - = si.nPage ;break ; case SB_PAGEDOWN: si.nPos + = si.nPage ;break ; case SB_THUMBTRACK:si.nPos = si.nTrackPos ;break ; default: break ; } si.fMask = SIF_POS ; SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ; GetScrollInfo (hwnd, SB_VERT, &si) ; if (si.nPos != iVscroll) { ScrollWindow (hwnd, 0, iVscroll - si.nPos, NULL, NULL) ; iVscroll = si.nPos ; UpdateWindow (hwnd) ; } return 0 ; // WM_HSCROLL: Horizontally scroll the DIB case WM_HSCROLL: si.cbSize = sizeof (SCROLLINFO) ; si.fMask = SIF_ALL ; GetScrollInfo (hwnd, SB_HORZ, &si) ; iHscroll = si.nPos ; switch (LOWORD (wParam)) { case SB_LINELEFT: si.nPos -=1 ; break ; case SB_LINERIGHT: si.nPos +=1 ; break ; case SB_PAGELEFT: si.nPos -=si.nPage ;break ; case SB_PAGERIGHT: si.nPos +=si.nPage ;break ; case SB_THUMBTRACK:si.nPos =si.nTrackPos ;break ; default: break ; } si.fMask = SIF_POS ; SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ; GetScrollInfo (hwnd, SB_HORZ, &si) ; if (si.nPos != iHscroll) { ScrollWindow (hwnd, iHscroll - si.nPos, 0, NULL, NULL) ; iHscroll = si.nPos ; UpdateWindow (hwnd) ; } return 0 ; // WM_INITMENUPOPUP: Enable or Gray menu items case WM_INITMENUPOPUP: if (hdib) iEnable = MF_ENABLED ; else iEnable = MF_GRAYED ; EnableMenuItem (hMenu, IDM_FILE_SAVE, iEnable) ; EnableMenuItem (hMenu, IDM_FILE_PRINT, iEnable) ; EnableMenuItem (hMenu, IDM_FILE_PROPERTIES, iEnable) ; EnableMenuItem (hMenu, IDM_EDIT_CUT, iEnable) ; EnableMenuItem (hMenu, IDM_EDIT_COPY, iEnable) ; EnableMenuItem (hMenu, IDM_EDIT_DELETE, iEnable) ; if (DibIsAddressable (hdib)) iEnable = MF_ENABLED ; else iEnable = MF_GRAYED ; EnableMenuItem (hMenu, IDM_EDIT_ROTATE, iEnable) ; EnableMenuItem (hMenu, IDM_EDIT_FLIP, iEnable) ; EnableMenuItem (hMenu, IDM_CONVERT_01, iEnable) ; EnableMenuItem (hMenu, IDM_CONVERT_04, iEnable) ; EnableMenuItem (hMenu, IDM_CONVERT_08, iEnable) ; EnableMenuItem (hMenu, IDM_CONVERT_16, iEnable) ; EnableMenuItem (hMenu, IDM_CONVERT_24, iEnable) ; EnableMenuItem (hMenu, IDM_CONVERT_32, iEnable) ; switch (DibBitCount (hdib)) { case 1: EnableMenuItem (hMenu, IDM_CONVERT_01, MF_GRAYED) ; break ; case 4: EnableMenuItem (hMenu, IDM_CONVERT_04, MF_GRAYED) ; break ; case 8: EnableMenuItem (hMenu, IDM_CONVERT_08, MF_GRAYED) ; break ; case 16: EnableMenuItem (hMenu, IDM_CONVERT_16, MF_GRAYED) ; break ; case 24: EnableMenuItem (hMenu, IDM_CONVERT_24, MF_GRAYED) ; break ; case 32: EnableMenuItem (hMenu, IDM_CONVERT_32, MF_GRAYED) ; break ; } if (hdib && DibColorSize (hdib) > 0) iEnable = MF_ENABLED ; else iEnable = MF_GRAYED ; EnableMenuItem (hMenu, IDM_PAL_DIBTABLE, iEnable) ; if (DibIsAddressable (hdib) && DibBitCount (hdib) > 8) iEnable = MF_ENABLED ; else iEnable = MF_GRAYED ; EnableMenuItem (hMenu, IDM_PAL_OPT_POP4, iEnable) ; EnableMenuItem (hMenu, IDM_PAL_OPT_POP5, iEnable) ; EnableMenuItem (hMenu, IDM_PAL_OPT_POP6, iEnable) ; EnableMenuItem (hMenu, IDM_PAL_OPT_MEDCUT, iEnable) ; EnableMenuItem (hMenu, IDM_EDIT_PASTE, IsClipboardFormatAvailable (CF_DIB) ? MF_ENABLED : MF_GRAYED) ; return 0 ; // WM_COMMAND: Process all menu commands. case WM_COMMAND: iConvert = 0 ; switch (LOWORD (wParam)) { case IDM_FILE_OPEN: // Show the File Open dialog box if (!GetOpenFileName (&ofn)) return 0 ; // If there's an existing DIB and palette, delete them SendMessage (hwnd, WM_USER_DELETEDIB, 0, 0) ; // Load the DIB into memory SetCursor (LoadCursor (NULL, IDC_WAIT)) ; ShowCursor (TRUE) ; hdib = DibFileLoad (szFileName) ; ShowCursor (FALSE) ; SetCursor (LoadCursor (NULL, IDC_ARROW)) ; // Reset the scroll bars SendMessage (hwnd, WM_USER_SETSCROLLS, TRUE, 0) ; // Create the palette and DDB SendMessage (hwnd, WM_USER_CREATEPAL, TRUE, 0) ; if (!hdib) { MessageBox (hwnd, TEXT ("Cannot load DIB file!"), szAppName, MB_OK | MB_ICONEXCLAMATION) ; } InvalidateRect (hwnd, NULL, TRUE) ; return 0 ; case IDM_FILE_SAVE: // Show the File Save dialog box if (! GetSaveFileName (&ofn)) return 0 ; // Save the DIB to memory SetCursor (LoadCursor (NULL, IDC_WAIT)) ; ShowCursor (TRUE) ; fSuccess = DibFileSave (hdib, szFileName) ; ShowCursor (FALSE) ; SetCursor (LoadCursor (NULL, IDC_ARROW)) ; if (!fSuccess) MessageBox ( hwnd, TEXT ("Cannot save DIB file!"), szAppName, MB_OK | MB_ICONEXCLAMATION) ; return 0 ; case IDM_FILE_PRINT: if (!hdib) return 0 ; // Get printer DC printdlg.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION ; if (!PrintDlg (&printdlg)) return 0 ; if (NULL == (hdcPrn = printdlg.hDC)) { MessageBox( hwnd, TEXT ("Cannot obtain Printer DC"), szAppName, MB_ICONEXCLAMATION | MB_OK) ; return 0 ; } // Check if the printer can print bitmaps if (!(RC_BITBLT & GetDeviceCaps (hdcPrn, RASTERCAPS))) { DeleteDC (hdcPrn) ; MessageBox ( hwnd, TEXT ("Printer cannot print bitmaps"), szAppName, MB_ICONEXCLAMATION | MB_OK) ; return 0 ; } // Get size of printable area of page cxPage = GetDeviceCaps (hdcPrn, HORZRES) ; cyPage = GetDeviceCaps (hdcPrn, VERTRES) ; fSuccess = FALSE ; // Send the DIB to the printer SetCursor (LoadCursor (NULL, IDC_WAIT)) ; ShowCursor (TRUE) ; if ((StartDoc (hdcPrn, &di) > 0) && (StartPage (hdcPrn) > 0)) { DisplayDib (hdcPrn, DibBitmapHandle (hdib), 0, 0, cxPage, cyPage, wShow, FALSE) ; if (EndPage (hdcPrn) > 0) { fSuccess = TRUE ; EndDoc (hdcPrn) ; } } ShowCursor (FALSE) ; SetCursor (LoadCursor (NULL, IDC_ARROW)) ; DeleteDC (hdcPrn) ; if ( !fSuccess) MessageBox ( hwnd, TEXT ("Could not print bitmap"), szAppName, MB_ICONEXCLAMATION | MB_OK) ; return 0 ; case IDM_FILE_PROPERTIES: if (!hdib) return 0 ; wsprintf (szBuffer, TEXT ("Pixel width:\t%i\n") TEXT ("Pixel height:\t%i\n") TEXT ("Bits per pixel:\t%i\n") TEXT ("Number of colors:\t%i\n") TEXT ("Compression:\t%s\n"), DibWidth (hdib), DibHeight (hdib), DibBitCount (hdib), DibNumColors (hdib), szCompression [min (3, DibCompression (hdib))]) ; MessageBox ( hwnd, szBuffer, szAppName, MB_ICONEXCLAMATION | MB_OK) ; return 0 ; case IDM_APP_EXIT: SendMessage (hwnd, WM_CLOSE, 0, 0) ; return 0 ; case IDM_EDIT_COPY: case IDM_EDIT_CUT: if (!(hGlobal = DibCopyToPackedDib (hdib, TRUE))) return 0 ; OpenClipboard (hwnd) ; EmptyClipboard () ; SetClipboardData (CF_DIB, hGlobal) ; CloseClipboard () ; if (LOWORD (wParam) == IDM_EDIT_COPY) return 0 ; // fall through for IDM_EDIT_CUT case IDM_EDIT_DELETE: SendMessage (hwnd, WM_USER_DELETEDIB, 0, 0) ; InvalidateRect (hwnd, NULL, TRUE) ; return 0 ; case IDM_EDIT_PASTE: OpenClipboard (hwnd) ; hGlobal = GetClipboardData (CF_DIB) ; pGlobal = GlobalLock (hGlobal) ; // If there's an existing DIB and palette,delete them. // Then convert the packed DIB to an HDIB. if (pGlobal) { SendMessage (hwnd, WM_USER_DELETEDIB, 0, 0) ; hdib = DibCopyFromPackedDib ((BITMAPINFO *) pGlobal) ; SendMessage (hwnd, WM_USER_CREATEPAL, TRUE, 0) ; } GlobalUnlock (hGlobal) ; CloseClipboard () ; // Reset the scroll bars SendMessage (hwnd, WM_USER_SETSCROLLS, TRUE, 0) ; InvalidateRect (hwnd, NULL, TRUE) ; return 0 ; case IDM_EDIT_ROTATE: if (hdibNew = DibRotateRight (hdib)) { DibDelete (hdib) ; DeleteObject (hBitmap) ; hdib = hdibNew ; hBitmap = DibCopyToDdb (hdib, hwnd, hPalette) ; SendMessage (hwnd, WM_USER_SETSCROLLS, TRUE, 0) ; InvalidateRect (hwnd, NULL, TRUE) ; } else { MessageBox ( hwnd, TEXT ("Not enough memory"), szAppName, MB_OK | MB_ICONEXCLAMATION) ; } return 0 ; case IDM_EDIT_FLIP: if (hdibNew = DibFlipHorizontal (hdib)) { DibDelete (hdib) ; DeleteObject (hBitmap) ; hdib = hdibNew ; hBitmap = DibCopyToDdb (hdib, hwnd, hPalette) ; InvalidateRect (hwnd, NULL, TRUE) ; } else { MessageBox ( hwnd, TEXT ("Not enough memory"), szAppName, MB_OK | MB_ICONEXCLAMATION) ; } return 0 ; case IDM_SHOW_NORMAL: case IDM_SHOW_CENTER: case IDM_SHOW_STRETCH: case IDM_SHOW_ISOSTRETCH: CheckMenuItem (hMenu, wShow, MF_UNCHECKED) ; wShow = LOWORD (wParam) ; CheckMenuItem (hMenu, wShow, MF_CHECKED) ; SendMessage (hwnd, WM_USER_SETSCROLLS, FALSE, 0) ; InvalidateRect (hwnd, NULL, TRUE) ; return 0 ; case IDM_CONVERT_32: iConvert += 8 ; case IDM_CONVERT_24: iConvert += 8 ; case IDM_CONVERT_16: iConvert += 8 ; case IDM_CONVERT_08: iConvert += 4 ; case IDM_CONVERT_04: iConvert += 3 ; case IDM_CONVERT_01: iConvert += 1 ; SetCursor (LoadCursor (NULL, IDC_WAIT)) ; ShowCursor (TRUE) ; hdibNew = DibConvert (hdib, iConvert) ; ShowCursor (FALSE) ; SetCursor (LoadCursor (NULL, IDC_ARROW)) ; if (hdibNew) { SendMessage (hwnd, WM_USER_DELETEDIB, 0, 0) ; hdib = hdibNew ; SendMessage (hwnd, WM_USER_CREATEPAL, TRUE, 0) ; InvalidateRect (hwnd, NULL, TRUE) ; } else { MessageBox ( hwnd, TEXT ("Not enough memory"), szAppName, MB_OK | MB_ICONEXCLAMATION) ; } return 0 ; case IDM_APP_ABOUT: MessageBox ( hwnd, TEXT ("Dibble (c) Charles Petzold, 1998"), szAppName, MB_OK | MB_ICONEXCLAMATION) ; return 0 ; } // All the other WM_COMMAND messages are from the palette // items. Any existing palette is deleted, and the cursor // is set to the hourglass. SendMessage (hwnd, WM_USER_DELETEPAL, 0, 0) ; SetCursor (LoadCursor (NULL, IDC_WAIT)) ; ShowCursor (TRUE) ; // Notice that all messages for palette items are ended // with break rather than return. This is to allow // additional processing later on. switch (LOWORD (wParam)) { case IDM_PAL_DIBTABLE: hPalette = DibPalDibTable (hdib) ; break ; case IDM_PAL_HALFTONE: hdc = GetDC (hwnd) ; if (hPalette = CreateHalftonePalette (hdc)) fHalftonePalette = TRUE ; ReleaseDC (hwnd, hdc) ; break ; case IDM_PAL_ALLPURPOSE: hPalette = DibPalAllPurpose () ; break ; case IDM_PAL_GRAY2:hPalette = DibPalUniformGrays (2) ; break; case IDM_PAL_GRAY3:hPalette = DibPalUniformGrays (3) ; break; case IDM_PAL_GRAY4:hPalette = DibPalUniformGrays (4) ; break; case IDM_PAL_GRAY8:hPalette = DibPalUniformGrays (8) ; break; case IDM_PAL_GRAY16:hPalette = DibPalUniformGrays (16) ; break; case IDM_PAL_GRAY32:hPalette = DibPalUniformGrays (32) ; break; case IDM_PAL_GRAY64:hPalette = DibPalUniformGrays (64) ; break; case IDM_PAL_GRAY128:hPalette = DibPalUniformGrays (128) ; break; case IDM_PAL_GRAY256:hPalette = DibPalUniformGrays (256) ; break; case IDM_PAL_RGB222:hPalette = DibPalUniformColors (2,2,2); break; case IDM_PAL_RGB333:hPalette = DibPalUniformColors (3,3,3); break; case IDM_PAL_RGB444:hPalette = DibPalUniformColors (4,4,4); break; case IDM_PAL_RGB555:hPalette = DibPalUniformColors (5,5,5); break; case IDM_PAL_RGB666:hPalette = DibPalUniformColors (6,6,6); break; case IDM_PAL_RGB775:hPalette = DibPalUniformColors (7,7,5); break; case IDM_PAL_RGB757:hPalette = DibPalUniformColors (7,5,7); break; case IDM_PAL_RGB577:hPalette = DibPalUniformColors (5,7,7); break; case IDM_PAL_RGB884:hPalette = DibPalUniformColors (8,8,4); break; case IDM_PAL_RGB848:hPalette = DibPalUniformColors (8,4,8); break; case IDM_PAL_RGB488:hPalette = DibPalUniformColors (4,8,8); break; case IDM_PAL_OPT_POP4:hPalette = DibPalPopularity (hdib, 4) ; break ; case IDM_PAL_OPT_POP5:hPalette = DibPalPopularity (hdib, 5) ; break ; case IDM_PAL_OPT_POP6:hPalette = DibPalPopularity (hdib, 6) ; break ; case IDM_PAL_OPT_MEDCUT:hPalette = DibPalMedianCut (hdib, 6) ; break ; } // After processing Palette items from the menu, the cursor // is restored to an arrow, the menu item is checked, and // the window is invalidated. hBitmap = DibCopyToDdb (hdib, hwnd, hPalette) ; ShowCursor (FALSE) ; SetCursor (LoadCursor (NULL, IDC_ARROW)) ; if (hPalette) PaletteMenu (hMenu, (LOWORD (wParam))) ; InvalidateRect (hwnd, NULL, TRUE) ; return 0 ; // This programmer-defined message deletes an existing DIB // in preparation for getting a new one. Invoked during // File Open command, Edit Paste command, and others. case WM_USER_DELETEDIB: if (hdib) { DibDelete (hdib) ; hdib = NULL ; } SendMessage (hwnd, WM_USER_DELETEPAL, 0, 0) ; return 0 ; // This programmer-defined message deletes an existing palette // in preparation for defining a new one. case WM_USER_DELETEPAL: if (hPalette) { DeleteObject (hPalette) ; hPalette = NULL ; fHalftonePalette = FALSE ; PaletteMenu (hMenu, IDM_PAL_NONE) ; } if (hBitmap) DeleteObject (hBitmap) ; return 0 ; // Programmer-defined message to create a new palette based on // a new DIB. If wParam == TRUE, create a DDB as well. case WM_USER_CREATEPAL: if (hdib) { hdc = GetDC (hwnd) ; if (!(RC_PALETTE & GetDeviceCaps (hdc, RASTERCAPS))) { PaletteMenu (hMenu, IDM_PAL_NONE) ; } else if (hPalette = DibPalDibTable (hdib)) { PaletteMenu (hMenu, IDM_PAL_DIBTABLE) ; } else if (hPalette = CreateHalftonePalette (hdc)) { fHalftonePalette = TRUE ; PaletteMenu (hMenu, IDM_PAL_HALFTONE) ; } ReleaseDC (hwnd, hdc) ; if ((BOOL) wParam) hBitmap = DibCopyToDdb (hdib, hwnd, hPalette) ; } return 0 ; case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; if (hPalette) { SelectPalette (hdc, hPalette, FALSE) ; RealizePalette (hdc) ; } if (hBitmap) { DisplayDib ( hdc, fHalftonePalette ? DibBitmapHandle (hdib) : hBitmap, iHscroll, iVscroll, cxClient, cyClient, wShow, fHalftonePalette) ; } EndPaint (hwnd, &ps) ; return 0 ; case WM_QUERYNEWPALETTE: if (!hPalette) return FALSE ; hdc = GetDC (hwnd) ; SelectPalette (hdc, hPalette, FALSE) ; RealizePalette (hdc) ; InvalidateRect (hwnd, NULL, TRUE) ; ReleaseDC (hwnd, hdc) ; return TRUE ; case WM_PALETTECHANGED: if (!hPalette || (HWND) wParam == hwnd) break ; hdc = GetDC (hwnd) ; SelectPalette (hdc, hPalette, FALSE) ; RealizePalette (hdc) ; UpdateColors (hdc) ; ReleaseDC (hwnd, hdc) ; break ; case WM_DESTROY: if (hdib) DibDelete (hdib) ; if (hBitmap) DeleteObject (hBitmap) ; if (hPalette) DeleteObject (hPalette) ; PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } DIBBLE.RC (摘錄) //Microsoft Developer Studio generated resource script. #include "resource.h" #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// // Menu DIBBLE MENU DISCARDABLE BEGIN POPUP "&File" BEGIN MENUITEM "&Open...\tCtrl+O", IDM_FILE_OPEN MENUITEM "&Save...\tCtrl+S", IDM_FILE_SAVE MENUITEM SEPARATOR MENUITEM "&Print...\tCtrl+P", IDM_FILE_PRINT MENUITEM SEPARATOR MENUITEM "Propert&ies...", IDM_FILE_PROPERTIES MENUITEM SEPARATOR MENUITEM "E&xit", IDM_APP_EXIT END POPUP "&Edit" BEGIN MENUITEM "Cu&t\tCtrl+X", IDM_EDIT_CUT MENUITEM "&Copy\tCtrl+C", IDM_EDIT_COPY MENUITEM "&Paste\tCtrl+V", IDM_EDIT_PASTE MENUITEM "&Delete\tDelete", IDM_EDIT_DELETE MENUITEM SEPARATOR MENUITEM "&Flip", IDM_EDIT_FLIP MENUITEM "&Rotate", IDM_EDIT_ROTATE END POPUP "&Show" BEGIN MENUITEM "&Actual Size", IDM_SHOW_NORMAL, CHECKED MENUITEM "&Center", IDM_SHOW_CENTER MENUITEM "&Stretch to Window", IDM_SHOW_STRETCH MENUITEM "Stretch &Isotropically", IDM_SHOW_ISOSTRETCH END POPUP "&Palette" BEGIN MENUITEM "&None", IDM_PAL_NONE, CHECKED MENUITEM "&Dib ColorTable", IDM_PAL_DIBTABLE MENUITEM "&Halftone", IDM_PAL_HALFTONE MENUITEM "&All-Purpose", IDM_PAL_ALLPURPOSE POPUP "&Gray Shades" BEGIN MENUITEM "&1. 2 Grays", IDM_PAL_GRAY2 MENUITEM "&2. 3 Grays", IDM_PAL_GRAY3 MENUITEM "&3. 4 Grays", IDM_PAL_GRAY4 MENUITEM "&4. 8 Grays", IDM_PAL_GRAY8 MENUITEM "&5. 16 Grays", IDM_PAL_GRAY16 MENUITEM "&6. 32 Grays", IDM_PAL_GRAY32 MENUITEM "&7. 64 Grays", IDM_PAL_GRAY64 MENUITEM "&8. 128 Grays", IDM_PAL_GRAY128 MENUITEM "&9. 256 Grays", IDM_PAL_GRAY256 END POPUP "&Uniform Colors" BEGIN MENUITEM "&1. 2R x 2G x 2B (8)", IDM_PAL_RGB222 MENUITEM "&2. 3R x 3G x 3B (27)", IDM_PAL_RGB333 MENUITEM "&3. 4R x 4G x 4B (64)", IDM_PAL_RGB444 MENUITEM "&4. 5R x 5G x 5B (125)", IDM_PAL_RGB555 MENUITEM "&5. 6R x 6G x 6B (216)", IDM_PAL_RGB666 MENUITEM "&6. 7R x 7G x 5B (245)", IDM_PAL_RGB775 MENUITEM "&7. 7R x 5B x 7B (245)", IDM_PAL_RGB757 MENUITEM "&8. 5R x 7G x 7B (245)", IDM_PAL_RGB577 MENUITEM "&9. 8R x 8G x 4B (256)", IDM_PAL_RGB884 MENUITEM "&A. 8R x 4G x 8B (256)", IDM_PAL_RGB848 MENUITEM "&B. 4R x 8G x 8B (256)", IDM_PAL_RGB488 END POPUP "&Optimized" BEGIN MENUITEM "&1. Popularity Algorithm (4 bits)"IDM_PAL_OPT_POP4 MENUITEM "&2. Popularity Algorithm (5 bits)"IDM_PAL_OPT_POP5 MENUITEM "&3. Popularity Algorithm (6 bits)"IDM_PAL_OPT_POP6 MENUITEM "&4. Median Cut Algorithm ", IDM_PAL_OPT_MEDCUT END END POPUP "Con&vert" BEGIN MENUITEM "&1. to 1 bit per pixel", IDM_CONVERT_01 MENUITEM "&2. to 4 bits per pixel", IDM_CONVERT_04 MENUITEM "&3. to 8 bits per pixel", IDM_CONVERT_08 MENUITEM "&4. to 16 bits per pixel", IDM_CONVERT_16 MENUITEM "&5. to 24 bits per pixel", IDM_CONVERT_24 MENUITEM "&6. to 32 bits per pixel", IDM_CONVERT_32 END POPUP "&Help" BEGIN MENUITEM "&About", IDM_APP_ABOUT END END ///////////////////////////////////////////////////////////////////////////// // Accelerator DIBBLE ACCELERATORS DISCARDABLE BEGIN "C", IDM_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT "O", IDM_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT "P", IDM_FILE_PRINT, VIRTKEY, CONTROL, NOINVERT "S", IDM_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT "V", IDM_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT VK_DELETE, IDM_EDIT_DELETE, VIRTKEY, NOINVERT "X", IDM_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT END RESOURCE.H (摘錄) // Microsoft Developer Studio generated include file. // Used by Dibble.rc #define IDM_FILE_OPEN 40001 #define IDM_FILE_SAVE 40002 #define IDM_FILE_PRINT 40003 #define IDM_FILE_PROPERTIES 40004 #define IDM_APP_EXIT 40005 #define IDM_EDIT_CUT 40006 #define IDM_EDIT_COPY 40007 #define IDM_EDIT_PASTE 40008 #define IDM_EDIT_DELETE 40009 #define IDM_EDIT_FLIP 40010 #define IDM_EDIT_ROTATE 40011 #define IDM_SHOW_NORMAL 40012 #define IDM_SHOW_CENTER 40013 #define IDM_SHOW_STRETCH 40014 #define IDM_SHOW_ISOSTRETCH 40015 #define IDM_PAL_NONE 40016 #define IDM_PAL_DIBTABLE 40017 #define IDM_PAL_HALFTONE 40018 #define IDM_PAL_ALLPURPOSE 40019 #define IDM_PAL_GRAY2 40020 #define IDM_PAL_GRAY3 40021 #define IDM_PAL_GRAY4 40022 #define IDM_PAL_GRAY8 40023 #define IDM_PAL_GRAY16 40024 #define IDM_PAL_GRAY32 40025 #define IDM_PAL_GRAY64 40026 #define IDM_PAL_GRAY128 40027 #define IDM_PAL_GRAY256 40028 #define IDM_PAL_RGB222 40029 #define IDM_PAL_RGB333 40030 #define IDM_PAL_RGB444 40031 #define IDM_PAL_RGB555 40032 #define IDM_PAL_RGB666 40033 #define IDM_PAL_RGB775 40034 #define IDM_PAL_RGB757 40035 #define IDM_PAL_RGB577 40036 #define IDM_PAL_RGB884 40037 #define IDM_PAL_RGB848 40038 #define IDM_PAL_RGB488 40039 #define IDM_PAL_OPT_POP4 40040 #define IDM_PAL_OPT_POP5 40041 #define IDM_PAL_OPT_POP6 40042 #define IDM_PAL_OPT_MEDCUT 40043 #define IDM_CONVERT_01 40044 #define IDM_CONVERT_04 40045 #define IDM_CONVERT_08 40046 #define IDM_CONVERT_16 40047 #define IDM_CONVERT_24 40048 #define IDM_CONVERT_32 40049 #define IDM_APP_ABOUT 40050 DIBBLE使用了兩個其他檔案,我將簡要地說明它們,。DIBCONV檔案(DIBCONV.C和DIBCONV.H)在兩種不同格式之間轉(zhuǎn)換-例如,,從每圖素24位元轉(zhuǎn)換成每圖素8位元。DIBPAL檔案(DIBPAL.C和DIBPAL.H)建立調(diào)色盤,。 DIBBLE維護WndProc中的三個重要的靜態(tài)變數(shù),。這些是呼叫hdib的HDIB代號、呼叫hPalette的HPALETTE代號和呼叫hBitmap的HBITMAP代號,。HDIB來自DIBHELP中的不同函式,;HPALETTE來自DIBPAL中的不同函式或CreateHalftonePalette函式;而HBITMAP代號來自DIBHELP.C中的DibCopyToDdb函式並幫助加速螢幕顯示,,特別是在256色顯示模式下,。不過,無論在程式建立新的「DIB Section」(顯而易見地)或在程式建立不同的調(diào)色盤(不很明顯)時,,這個代號都必須重新建立,。 讓我們從功能上而非循序漸進地來介紹一下DIBBLE。 檔案載入和儲存 DIBBLE可以在回應IDM_FILE_LOAD和IDM_FILE_SAVE的WM_COMMAND訊息處理過程中載入DIB檔案並儲存這些檔案,。在處理這些訊息處理期間,,DIBBLE通過分別呼叫GetOpenFileName和GetSaveFileName來啟動公用檔案對話方塊。 對於「File」,、「Save」功能表命令,,DIBBLE只需要呼叫DibFileSave。對於「File」,、「Open」功能表命令,,DIBBLE必須首先刪除前面的HDIB、調(diào)色盤和點陣圖物件,。它透過發(fā)送一個WM_USER_DELETEDIB訊息來完成這件事,,此訊息通過呼叫DibDelete和DeleteObject來處理。然後DIBBLE呼叫DIBHELP中的DibFileLoad函式,,發(fā)送WM_USER_SETSCROLLS和WM_USER_CREATEPAL訊息來重新設(shè)定捲動列並建立調(diào)色盤,。WM_USER_CREATEPAL訊息也位於程式從DIB區(qū)塊建立的新的DDB位置。 |
|
來自: alal51 > 《調(diào)色板》