www.pudn.com > 20040006.zip > Dib.cpp
// Dib.cpp : implementation file // #include "stdafx.h" #include "Dib.h" //#include// especially for GlobalAllocPtr #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif IMPLEMENT_SERIAL(CDib, CObject, 0) //////////////////////////////////////////////////////////////////////////// CDib::CDib() { m_dwLength = 0L; m_nBits = 0; m_lpBuf = NULL; m_pPalette = NULL; m_pBitmap = NULL; m_hDib = NULL; } CDib:: CDib(HANDLE hDib, BOOL bDataHandleOnly) { if (hDib==NULL) { m_dwLength = 0L; m_nBits = 0; m_lpBuf = NULL; m_pPalette = NULL; m_pBitmap = NULL; m_hDib = NULL; return; } // Only use Bit-Data Handle if (bDataHandleOnly) { m_pPalette = NULL; m_pBitmap = NULL; m_dwLength = ::GlobalSize(hDib)+sizeof(BITMAPFILEHEADER); if (! AllocMemory()) return; memcpy((LPSTR)m_lpBMI, (LPSTR)::GlobalLock((HGLOBAL)hDib), ::GlobalSize(hDib)); ::GlobalUnlock(hDib); // Fill in file type (first 2 bytes must be "BM" for a bitmap) m_lpBMFH->bfType = 0x4d42; // "BM" // Calculating the size of the DIB is a bit tricky (if we want to // do it right). The easiest way to do this is to call GlobalSize() // on our global handle, but since the size of our global memory may have // been padded a few bytes, we may end up writing out a few too // many bytes to the file (which may cause problems with some apps). // // So, instead let's calculate the size manually (if we can) // // First, find size of header plus size of color table. Since the // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains // the size of the structure, let's use this. DWORD dwDIBSize; dwDIBSize = *(LPDWORD)m_lpBMIH + GetPaletteSize(); // Partial Calculation // Now calculate the size of the image if ((m_lpBMIH->biCompression == BI_RLE8) || (m_lpBMIH->biCompression == BI_RLE4)) { // It's an RLE bitmap, we can't calculate size, so trust the // biSizeImage field dwDIBSize += m_lpBMIH->biSizeImage; } else { DWORD dwBmBitsSize; // Size of Bitmap Bits only // It's not RLE, so size is Width (DWORD aligned) * Height dwBmBitsSize = WIDTHBYTES((m_lpBMIH->biWidth)*((DWORD)m_lpBMIH->biBitCount)) * m_lpBMIH->biHeight; dwDIBSize += dwBmBitsSize; // Now, since we have calculated the correct size, why don't we // fill in the biSizeImage field (this will fix any .BMP files which // have this field incorrect). m_lpBMIH->biSizeImage = dwBmBitsSize; } // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER) m_lpBMFH->bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER); m_lpBMFH->bfReserved1 = 0; m_lpBMFH->bfReserved2 = 0; /* * Now, calculate the offset the actual bitmap bits will be in * the file -- It's the Bitmap file header plus the DIB header, * plus the size of the color table. */ m_lpBMFH->bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + m_lpBMIH->biSize + GetPaletteSize(); //if (IS_WIN30_DIB(m_lpBMIH)) // ASSERT((m_lpBMIH->biBitCount==1)||(m_lpBMIH->biBitCount== 4)|| // (m_lpBMIH->biBitCount==8)||(m_lpBMIH->biBitCount==24)); //else // ASSERT((m_lpBMCH->bcBitCount==1)||(m_lpBMCH->bcBitCount== 4)|| // (m_lpBMCH->bcBitCount==8)||(m_lpBMCH->bcBitCount==24)); m_lpData = (LPSTR)m_lpBMFH + m_lpBMFH->bfOffBits; if (IS_WIN30_DIB(m_lpBMIH)) m_nBits = m_lpBMIH->biBitCount; else m_nBits = m_lpBMCH->bcBitCount; return; } // Use DIB Handle m_hDib = hDib; m_pPalette = NULL; m_pBitmap = NULL; m_dwLength = ::GlobalSize(m_hDib); m_lpBuf = (LPSTR) ::GlobalLock((HGLOBAL) m_hDib); m_lpBMFH = (LPBITMAPFILEHEADER)m_lpBuf; m_lpBMIH = (LPBITMAPINFOHEADER)((LPSTR)m_lpBuf + sizeof(BITMAPFILEHEADER)); m_lpBMI = (LPBITMAPINFO)m_lpBMIH; m_lpBMCH = (LPBITMAPCOREHEADER)m_lpBMIH; m_lpBMC = (LPBITMAPCOREINFO)m_lpBMCH; if (IS_WIN30_DIB(m_lpBMIH)) ASSERT((m_lpBMIH->biBitCount==1)||(m_lpBMIH->biBitCount== 4)|| (m_lpBMIH->biBitCount==8)||(m_lpBMIH->biBitCount==24)); else ASSERT((m_lpBMCH->bcBitCount==1)||(m_lpBMCH->bcBitCount== 4)|| (m_lpBMCH->bcBitCount==8)||(m_lpBMCH->bcBitCount==24)); m_lpData = (LPSTR)m_lpBMFH + m_lpBMFH->bfOffBits; if (IS_WIN30_DIB(m_lpBMIH)) m_nBits = m_lpBMIH->biBitCount; else m_nBits = m_lpBMCH->bcBitCount; } CDib::CDib(CDC* pDC, // Memory DC pointer, which has // selected a DDB bitmap int nBt, // color bits/pixel (default=0, use the value in DDB) BOOL bCompr) // compression? (default = TRUE); { BITMAP bm; int nPaletteSize; m_pPalette = NULL; m_pBitmap = NULL; CBitmap *pEmptyBitmap = new CBitmap; pEmptyBitmap->CreateCompatibleBitmap(pDC,0,0); CBitmap *pBitmap = (CBitmap *)(pDC->SelectObject(pEmptyBitmap)); delete pDC->SelectObject(pBitmap); pBitmap->GetObject(sizeof(bm), &bm); switch (nBt) { case 1 : case 4 : case 8 : case 24: m_nBits = nBt; break; default: m_nBits = bm.bmPlanes * bm.bmBitsPixel; break; } switch (m_nBits) { case 1 : nPaletteSize = 2; break; case 4 : nPaletteSize = 16; break; case 8 : nPaletteSize = 256; break; default: nPaletteSize = 0; break; } DWORD dwBytes = ((DWORD) bm.bmWidth * m_nBits) / 32; if (((DWORD) bm.bmWidth * m_nBits) % 32) dwBytes++; dwBytes *= 4; m_dwLength = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nPaletteSize; if (! AllocMemory()) return; m_lpBMIH->biSize = sizeof(BITMAPINFOHEADER); m_lpBMIH->biWidth = bm.bmWidth; m_lpBMIH->biHeight = bm.bmHeight; m_lpBMIH->biPlanes = 1; m_lpBMIH->biBitCount = m_nBits; if (bCompr && m_nBits==4) m_lpBMIH->biCompression = BI_RLE4; else if (bCompr && m_nBits==8) m_lpBMIH->biCompression = BI_RLE8; else m_lpBMIH->biCompression = BI_RGB; m_lpBMIH->biSizeImage = 0; m_lpBMIH->biXPelsPerMeter = 0; m_lpBMIH->biYPelsPerMeter = 0; m_lpBMIH->biClrUsed = 0; m_lpBMIH->biClrImportant = 0; ::GetDIBits(pDC->GetSafeHdc(), (HBITMAP)pBitmap->GetSafeHandle(), 0, (WORD)bm.bmHeight, NULL, m_lpBMI, DIB_RGB_COLORS); if (m_lpBMIH->biSizeImage == 0) { m_dwLength += dwBytes*bm.bmHeight; m_lpBMIH->biCompression = BI_RGB; TRACE("Can not do compression\n"); } else m_dwLength += m_lpBMIH->biSizeImage; if (! AllocMemory(TRUE)) return; m_lpData = (LPSTR)m_lpBMIH + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nPaletteSize; m_lpBMFH->bfType = 0x4d42; //'BM' m_lpBMFH->bfSize = m_dwLength; m_lpBMFH->bfReserved1 = 0; m_lpBMFH->bfReserved2 = 0; m_lpBMFH->bfOffBits = m_lpData - m_lpBuf; if (! ::GetDIBits(pDC->GetSafeHdc(), (HBITMAP)pBitmap->GetSafeHandle(), 0, (WORD)bm.bmHeight, m_lpData, m_lpBMI, DIB_RGB_COLORS)) m_dwLength = 0L; } CDib::CDib(CDC* pDC, // DC pointer CBitmap* pBitmap, // DDB bitmap int nBt, // color bits/pixel (default=0, use the value in DDB) BOOL bCompr) // compression? (default = TRUE); { BITMAP bm; int nPaletteSize; m_pPalette = NULL; m_pBitmap = NULL; CDC *pMemDC = new CDC; pMemDC->CreateCompatibleDC(pDC); CBitmap* pOldBitmap = (CBitmap *)(pMemDC->SelectObject(pBitmap)); pBitmap->GetObject(sizeof(bm), &bm); switch (nBt) { case 1 : case 4 : case 8 : case 24: m_nBits = nBt; break; default: m_nBits = bm.bmPlanes * bm.bmBitsPixel; break; } switch (m_nBits) { case 1 : nPaletteSize = 2; break; case 4 : nPaletteSize = 16; break; case 8 : nPaletteSize = 256; break; default: nPaletteSize = 0; break; } DWORD dwBytes = ((DWORD) bm.bmWidth * m_nBits) / 32; if (((DWORD) bm.bmWidth * m_nBits) % 32) dwBytes++; dwBytes *= 4; m_dwLength = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nPaletteSize; if (! AllocMemory()) return; m_lpBMIH->biSize = sizeof(BITMAPINFOHEADER); m_lpBMIH->biWidth = bm.bmWidth; m_lpBMIH->biHeight = bm.bmHeight; m_lpBMIH->biPlanes = 1; m_lpBMIH->biBitCount = m_nBits; if (bCompr && m_nBits==4) m_lpBMIH->biCompression = BI_RLE4; else if (bCompr && m_nBits==8) m_lpBMIH->biCompression = BI_RLE8; else m_lpBMIH->biCompression = BI_RGB; m_lpBMIH->biSizeImage = 0; m_lpBMIH->biXPelsPerMeter = 0; m_lpBMIH->biYPelsPerMeter = 0; m_lpBMIH->biClrUsed = 0; m_lpBMIH->biClrImportant = 0; ::GetDIBits(pMemDC->GetSafeHdc(), (HBITMAP)pBitmap->GetSafeHandle(), 0, (WORD)bm.bmHeight, NULL, m_lpBMI, DIB_RGB_COLORS); if (m_lpBMIH->biSizeImage == 0) { m_dwLength += dwBytes*bm.bmHeight; m_lpBMIH->biCompression = BI_RGB; TRACE("Can not do compression\n"); } else m_dwLength += m_lpBMIH->biSizeImage; if (! AllocMemory(TRUE)) return; m_lpData = (LPSTR)m_lpBMIH + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nPaletteSize; m_lpBMFH->bfType = 0x4d42; //'BM' m_lpBMFH->bfSize = m_dwLength; m_lpBMFH->bfReserved1 = 0; m_lpBMFH->bfReserved2 = 0; m_lpBMFH->bfOffBits = m_lpData - m_lpBuf; if (! ::GetDIBits(pMemDC->GetSafeHdc(), (HBITMAP)pBitmap->GetSafeHandle(), 0, (WORD)bm.bmHeight, m_lpData, m_lpBMI, DIB_RGB_COLORS)) m_dwLength = 0L; pMemDC->SelectObject(pOldBitmap); delete pMemDC; } CDib::~CDib() { if (m_hDib!=NULL) { ::GlobalUnlock((HGLOBAL) m_hDib); ::GlobalFree((HGLOBAL) m_hDib); m_lpBuf = NULL; m_hDib = NULL; } if (m_pPalette!=NULL) { delete m_pPalette; m_pPalette = NULL; } if (m_pBitmap!=NULL) { delete m_pBitmap; m_pBitmap = NULL; } } void CDib::Serialize(CArchive& ar) { CObject::Serialize(ar); ar.Flush(); if (ar.IsStoring()) { WriteDib(ar.GetFile()); } else { ReadDib(ar.GetFile()); } } BOOL CDib::LoadDib(UINT uIDS, LPCSTR lpszDibType) { ASSERT(m_dwLength == 0L); LPCSTR lpszDibRes = MAKEINTRESOURCE(uIDS); HINSTANCE hInst = AfxGetInstanceHandle(); HRSRC hRes = ::FindResource(hInst, lpszDibRes, lpszDibType); HGLOBAL hData = ::LoadResource(hInst, hRes); if (hRes != NULL && hData != NULL) { char *lpBuf = (char *)::LockResource(hData); m_dwLength = ((LPBITMAPFILEHEADER)lpBuf)->bfSize; if (! AllocMemory()) return FALSE; for (register DWORD i=0;i bfType != 0x4d42) { CString str = lpszDibRes; str += " : Invalid bitmap file!"; AfxMessageBox(str); return FALSE; } if (IS_WIN30_DIB(m_lpBMIH)) ASSERT((m_lpBMIH->biBitCount==1)||(m_lpBMIH->biBitCount== 4)|| (m_lpBMIH->biBitCount==8)||(m_lpBMIH->biBitCount==24)); else ASSERT((m_lpBMCH->bcBitCount==1)||(m_lpBMCH->bcBitCount== 4)|| (m_lpBMCH->bcBitCount==8)||(m_lpBMCH->bcBitCount==24)); m_lpData = (LPSTR)m_lpBMFH + m_lpBMFH->bfOffBits; m_nBits = m_lpBMIH->biBitCount; return TRUE; } BOOL CDib::LoadDib(LPCSTR lpszDibRes, LPCSTR lpszDibType) { ASSERT(m_dwLength == 0L); HINSTANCE hInst = AfxGetInstanceHandle(); HRSRC hRes = ::FindResource(hInst, lpszDibRes, lpszDibType); HGLOBAL hData = ::LoadResource(hInst, hRes); if (hRes != NULL && hData != NULL) { char *lpBuf = (char *)::LockResource(hData); m_dwLength = ((LPBITMAPFILEHEADER)lpBuf)->bfSize; if (! AllocMemory()) return FALSE; for (register DWORD i=0;i bfType != 0x4d42) { CString str = lpszDibRes; str += " : Invalid bitmap file!"; AfxMessageBox(str); return FALSE; } if (IS_WIN30_DIB(m_lpBMIH)) ASSERT((m_lpBMIH->biBitCount==1)||(m_lpBMIH->biBitCount== 4)|| (m_lpBMIH->biBitCount==8)||(m_lpBMIH->biBitCount==24)); else ASSERT((m_lpBMCH->bcBitCount==1)||(m_lpBMCH->bcBitCount== 4)|| (m_lpBMCH->bcBitCount==8)||(m_lpBMCH->bcBitCount==24)); m_lpData = (LPSTR)m_lpBMFH + m_lpBMFH->bfOffBits; m_nBits = m_lpBMIH->biBitCount; return TRUE; } BOOL CDib::LoadDib(LPCSTR lpszDibFile) { ASSERT(m_dwLength == 0L); TRY { CFile file(lpszDibFile, CFile::modeRead|CFile::shareDenyNone); if (! ReadDib(&file)) { CString str = lpszDibFile; str += " : Read file error!"; AfxMessageBox(str); return FALSE; } } CATCH (CException, e) { CString str = lpszDibFile; str += " : Read file error!"; AfxMessageBox(str); return FALSE; } END_CATCH return TRUE; } BOOL CDib::SaveDib(LPCSTR lpszDibFile) { TRY { CFile file(lpszDibFile, CFile::modeCreate|CFile::modeWrite); if (! WriteDib(&file)) { CString str = lpszDibFile; str += " : Write file error!"; AfxMessageBox(str); return FALSE; } } CATCH (CException, e) { CString str = lpszDibFile; str += " : Write file error!"; AfxMessageBox(str); return FALSE; } END_CATCH return TRUE; } BOOL CDib::ReadDib(CFile *pFile) { ASSERT(m_dwLength == 0L); TRY { m_dwLength = pFile->GetLength(); if (! AllocMemory()) return FALSE; DWORD dwCount = pFile->ReadHuge(m_lpBuf, m_dwLength); if (dwCount != m_dwLength) return FALSE; } CATCH (CException, e) { return FALSE; } END_CATCH if (m_lpBMFH->bfType != 0x4d42) return FALSE; if (IS_WIN30_DIB(m_lpBMIH)) ASSERT((m_lpBMIH->biBitCount==1)||(m_lpBMIH->biBitCount== 4)|| (m_lpBMIH->biBitCount==8)||(m_lpBMIH->biBitCount==24)); else ASSERT((m_lpBMCH->bcBitCount==1)||(m_lpBMCH->bcBitCount== 4)|| (m_lpBMCH->bcBitCount==8)||(m_lpBMCH->bcBitCount==24)); m_lpData = (LPSTR)m_lpBMFH + m_lpBMFH->bfOffBits; m_nBits = m_lpBMIH->biBitCount; return TRUE; } BOOL CDib::WriteDib(CFile *pFile) { TRY { pFile->WriteHuge(m_lpBuf, m_dwLength); } CATCH (CException, e) { return FALSE; } END_CATCH return TRUE; } BOOL CDib::Display(CDC * pDC, CPoint ptDest, DWORD dwRop) { BOOL bSuccess = FALSE; if (m_lpBuf == NULL) return bSuccess; CPalette* pOldPal = pDC->SelectPalette(GetPalette(), TRUE); pDC->RealizePalette(); pDC->SetStretchBltMode(COLORONCOLOR); bSuccess = ::StretchDIBits(pDC->GetSafeHdc(), ptDest.x, ptDest.y, (int)m_lpBMIH->biWidth, (int)m_lpBMIH->biHeight, 0, 0, (int)m_lpBMIH->biWidth, (int)m_lpBMIH->biHeight, m_lpData, m_lpBMI, DIB_RGB_COLORS, dwRop); pDC->SelectPalette(pOldPal, FALSE); //TRUE); return bSuccess; } BOOL CDib::Display(CDC* pDC, CRect rcDest, CRect rcSrc, DWORD dwRop) { BOOL bSuccess = FALSE; if (m_lpBuf == NULL) return bSuccess; CPalette* pOldPal = pDC->SelectPalette(GetPalette(), TRUE); pDC->RealizePalette(); pDC->SetStretchBltMode(COLORONCOLOR); bSuccess = ::StretchDIBits(pDC->GetSafeHdc(), rcDest.left, rcDest.top, rcDest.Width(), rcDest.Height(), rcSrc.left, (int)m_lpBMIH->biHeight-rcSrc.top-rcSrc.Height(), // SrcY --rcSrc.top, rcSrc.Width(), rcSrc.Height(), m_lpData, m_lpBMI, DIB_RGB_COLORS, dwRop); pDC->SelectPalette(pOldPal, FALSE); //TRUE); return bSuccess; } CPalette * CDib::GetPalette() { if (m_pPalette == NULL) MakePalette(); return m_pPalette; } int CDib::GetColorBits() { return m_nBits; } BOOL CDib::IsEmpty() { if (m_dwLength == 0L || m_hDib == NULL) return TRUE; else return FALSE; } DWORD CDib::GetLength() { return m_dwLength; } WORD CDib::GetWidth() { if (IsEmpty()) return 0; if (IS_WIN30_DIB(m_lpBMIH)) return (WORD)(m_lpBMIH->biWidth); else return (WORD)(m_lpBMCH->bcWidth); } WORD CDib::GetHeight() { if (IsEmpty()) return 0; if (IS_WIN30_DIB(m_lpBMIH)) return (WORD)(m_lpBMIH->biHeight); else return (WORD)(m_lpBMCH->bcHeight); } HDIB CDib::GetHandle() { return m_hDib; } HDIB CDib::CopyHandle() { if (IsEmpty()) return NULL; HGLOBAL hCopy = ::GlobalAlloc(GHND, m_dwLength); if (hCopy == NULL) return NULL; void* lpCopy = ::GlobalLock((HGLOBAL) hCopy); memcpy(lpCopy, m_lpBMI, m_dwLength); ::GlobalUnlock(hCopy); return hCopy; } HANDLE CDib::CopyDataHandle() { if (IsEmpty()) return NULL; DWORD dwDataLength = m_dwLength-sizeof(BITMAPFILEHEADER); HGLOBAL hCopy = ::GlobalAlloc(GHND, dwDataLength); if (hCopy == NULL) return NULL; void* lpCopy = ::GlobalLock((HGLOBAL) hCopy); memcpy(lpCopy, m_lpBMI, dwDataLength); ::GlobalUnlock(hCopy); return hCopy; } WORD CDib::GetNumColors() { WORD wBitCount; // DIB bit count /* If this is a Windows-style DIB, the number of colors in the * color table can be less than the number of bits per pixel * allows for (i.e. lpbi->biClrUsed can be set to some value). * If this is the case, return the appropriate value. */ if (IS_WIN30_DIB(m_lpBMIH)) { DWORD dwClrUsed; dwClrUsed = ((LPBITMAPINFOHEADER)m_lpBMIH)->biClrUsed; if (dwClrUsed != 0) return (WORD)dwClrUsed; } /* Calculate the number of colors in the color table based on * the number of bits per pixel for the DIB. */ if (IS_WIN30_DIB(m_lpBMIH)) wBitCount = ((LPBITMAPINFOHEADER)m_lpBMIH)->biBitCount; else wBitCount = ((LPBITMAPCOREHEADER)m_lpBMIH)->bcBitCount; /* return number of colors based on bits per pixel * This function calculates the number of colors in the DIB's color table * by finding the bits per pixel for the DIB (whether Win3.0 or other-style * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256, * if 24, no colors in color table. */ switch (wBitCount) { case 1: return 2; case 4: return 16; case 8: return 256; default: return 0; } } WORD CDib::GetPaletteSize() { // calculate the size required by the palette if (IS_WIN30_DIB (m_lpBMIH)) return (WORD)(GetNumColors() * sizeof(RGBQUAD)); else return (WORD)(GetNumColors() * sizeof(RGBTRIPLE)); } BOOL CDib::AllocMemory(BOOL bRealloc /* default = FALSE */) { if (bRealloc) m_hDib = ::GlobalReAlloc(m_hDib, m_dwLength, GMEM_MOVEABLE | GMEM_ZEROINIT); //m_lpBuf = (char *)GlobalReAllocPtr(m_lpBuf, m_dwLength, GHND); else m_hDib = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, m_dwLength); //m_lpBuf = (char *)GlobalAllocPtr(GHND, m_dwLength); if (m_hDib == NULL) { return FALSE; } m_lpBuf = (LPSTR) ::GlobalLock((HGLOBAL) m_hDib); if (m_lpBuf == NULL) { AfxMessageBox("Allocate DIB memory error!"); m_dwLength = 0L; m_nBits = 0; m_hDib = NULL; return FALSE; } m_lpBMFH = (LPBITMAPFILEHEADER)m_lpBuf; m_lpBMIH = (LPBITMAPINFOHEADER)((LPSTR)m_lpBuf + sizeof(BITMAPFILEHEADER)); m_lpBMI = (LPBITMAPINFO)m_lpBMIH; m_lpBMCH = (LPBITMAPCOREHEADER)m_lpBMIH; m_lpBMC = (LPBITMAPCOREINFO)m_lpBMIH; return TRUE; } BOOL CDib::MakePalette() { LPLOGPALETTE lpPal; // pointer to a logical palette HANDLE hLogPal; // handle to a logical palette HPALETTE hPal = NULL; // handle to a palette WORD wNumColors; // number of colors in color table if (m_pPalette != NULL) return TRUE; if (m_lpBuf == NULL) return FALSE; wNumColors = GetNumColors(); if (wNumColors == 0) return FALSE; hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * wNumColors); if (hLogPal == 0) return FALSE; lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal); /* set version and number of palette entries */ lpPal->palVersion = 0x300; lpPal->palNumEntries = (WORD)wNumColors; /* is this a Win 3.0 DIB? */ BOOL bWinStyleDIB = IS_WIN30_DIB(m_lpBMIH); for (int i=0; i<(int)wNumColors; i++) { if (bWinStyleDIB) { lpPal->palPalEntry[i].peRed = m_lpBMI->bmiColors[i].rgbRed; lpPal->palPalEntry[i].peGreen = m_lpBMI->bmiColors[i].rgbGreen; lpPal->palPalEntry[i].peBlue = m_lpBMI->bmiColors[i].rgbBlue; lpPal->palPalEntry[i].peFlags = 0; } else { lpPal->palPalEntry[i].peRed = m_lpBMC->bmciColors[i].rgbtRed; lpPal->palPalEntry[i].peGreen = m_lpBMC->bmciColors[i].rgbtGreen; lpPal->palPalEntry[i].peBlue = m_lpBMC->bmciColors[i].rgbtBlue; lpPal->palPalEntry[i].peFlags = 0; } } m_pPalette = new CPalette; BOOL bResult = m_pPalette->CreatePalette(lpPal); ::GlobalUnlock((HGLOBAL) hLogPal); ::GlobalFree((HGLOBAL) hLogPal); return bResult; } CBitmap * CDib::MakeBitmap(CDC * pDC) { if (m_pBitmap != NULL) return pDC->SelectObject(m_pBitmap); // return Original-bitmap if (IsEmpty()) return NULL; CPalette *pOldPal = pDC->SelectPalette(GetPalette(), TRUE); pDC->RealizePalette(); int nPlanes = pDC->GetDeviceCaps(PLANES); int nBitsPixel = pDC->GetDeviceCaps(BITSPIXEL); CBitmap* pConfigBitmap = new CBitmap; char bits[100]; if (m_lpBMIH->biBitCount == 1) pConfigBitmap->CreateBitmap(1, 1, 1, 1, bits); else pConfigBitmap->CreateBitmap(1, 1, nPlanes, nBitsPixel, bits); CBitmap* pOriginalBitmap = (CBitmap *)pDC->SelectObject(pConfigBitmap); DWORD dwFore, dwBack; if (GetMonoColors(dwFore, dwBack)) SetMonoColors(0L, 0xFFFFFFL); HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(), m_lpBMIH, CBM_INIT, (CONST BYTE *)(m_lpBuf+m_lpBMFH->bfOffBits), m_lpBMI, DIB_RGB_COLORS); if (hBitmap == NULL) { TRACE("null bitmap!\n"); return NULL; } SetMonoColors(dwFore, dwBack); m_pBitmap = new CBitmap; m_pBitmap->Attach(hBitmap); pDC->SelectObject(m_pBitmap); // delete config-bitmap delete pConfigBitmap; pDC->SelectPalette(pOldPal, FALSE); return pOriginalBitmap; // return original-bitmap } void CDib::SetMonoColors(DWORD dwForegrpund, DWORD dwBackGround) { if (m_nBits != 1) return; unsigned long far* pPalette = (unsigned long far*) ((LPSTR)m_lpBMIH+sizeof(BITMAPINFOHEADER)); *pPalette = dwForegrpund; *(++pPalette) = dwBackGround; return; } BOOL CDib::GetMonoColors(DWORD& dwForegrpund, DWORD& dwBackGround) { if (m_nBits != 1) return FALSE; unsigned long far* pPalette = (unsigned long far*) ((LPSTR)m_lpBMIH+sizeof(BITMAPINFOHEADER)); dwForegrpund = *pPalette; dwBackGround = *(++pPalette); return TRUE; } HANDLE CopyHandle (HANDLE h) { if (h == NULL) return NULL; DWORD dwLen = ::GlobalSize((HGLOBAL) h); HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen); if (hCopy != NULL) { void* lpCopy = ::GlobalLock((HGLOBAL) hCopy); void* lp = ::GlobalLock((HGLOBAL) h); memcpy(lpCopy, lp, dwLen); ::GlobalUnlock(hCopy); ::GlobalUnlock(h); } return hCopy; }