X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/bbc1265c400d44962621a6b2c7c36ccff097207c..6aa855b9ec8702b37b1f5389690e0ec1ba4b2f6b:/src/msw/dib.cpp diff --git a/src/msw/dib.cpp b/src/msw/dib.cpp index 9c2ad41950..8722427148 100644 --- a/src/msw/dib.cpp +++ b/src/msw/dib.cpp @@ -46,6 +46,19 @@ #include "wx/image.h" #include "wx/msw/dib.h" +// ---------------------------------------------------------------------------- +// private functions +// ---------------------------------------------------------------------------- + +// calculate the number of palette entries needed for the bitmap with this +// number of bits per pixel +static WORD wxGetNumOfBitmapColors(WORD bitsPerPixel) +{ + // only 1, 4 and 8bpp bitmaps use palettes (well, they could be used with + // 24bpp ones too but we don't support this as I think it's quite uncommon) + return bitsPerPixel <= 8 ? 1 << bitsPerPixel : 0; +} + // ============================================================================ // implementation // ============================================================================ @@ -79,11 +92,8 @@ bool wxDIB::Create(int width, int height, int depth) info->bmiHeader.biPlanes = 1; info->bmiHeader.biBitCount = depth; - info->bmiHeader.biCompression = BI_RGB; info->bmiHeader.biSizeImage = GetLineSize(width, depth)*height; - // No need to report an error here. If it fails, we just won't use a - // file mapping and CreateDIBSection will just allocate memory for us. m_handle = ::CreateDIBSection ( 0, // hdc (unused with DIB_RGB_COLORS) @@ -110,6 +120,30 @@ bool wxDIB::Create(int width, int height, int depth) return true; } +// ---------------------------------------------------------------------------- +// Loading/saving the DIBs +// ---------------------------------------------------------------------------- + +bool wxDIB::Load(const wxString& filename) +{ + m_handle = (HBITMAP)::LoadImage + ( + wxGetInstance(), + filename, + IMAGE_BITMAP, + 0, 0, // don't specify the size + LR_CREATEDIBSECTION | LR_LOADFROMFILE + ); + if ( !m_handle ) + { + wxLogLastError(_T("LoadImage(LR_CREATEDIBSECTION | LR_LOADFROMFILE)")); + + return false; + } + + return true; +} + // ---------------------------------------------------------------------------- // wxDIB accessors // ---------------------------------------------------------------------------- @@ -129,7 +163,6 @@ void wxDIB::DoGetObject() const if ( !::GetObject(m_handle, sizeof(ds), &ds) ) { wxLogLastError(_T("GetObject(hDIB)")); - return; } @@ -142,6 +175,212 @@ void wxDIB::DoGetObject() const } } +// ---------------------------------------------------------------------------- +// DDB <-> DIB conversions +// ---------------------------------------------------------------------------- + +HBITMAP wxDIB::CreateDDB(HDC hdc) const +{ + wxCHECK_MSG( m_handle, 0, _T("wxDIB::CreateDDB(): invalid object") ); + + DIBSECTION ds; + if ( !::GetObject(m_handle, sizeof(ds), &ds) ) + { + wxLogLastError(_T("GetObject(hDIB)")); + + return 0; + } + + return ConvertToBitmap((BITMAPINFO *)&ds.dsBmih, hdc, ds.dsBm.bmBits); +} + +/* static */ +HBITMAP wxDIB::ConvertToBitmap(const BITMAPINFO *pbmi, HDC hdc, void *bits) +{ + wxCHECK_MSG( pbmi, 0, _T("invalid DIB in ConvertToBitmap") ); + + // here we get BITMAPINFO struct followed by the actual bitmap bits and + // BITMAPINFO starts with BITMAPINFOHEADER followed by colour info + const BITMAPINFOHEADER *pbmih = &pbmi->bmiHeader; + + // get the pointer to the start of the real image data if we have a plain + // DIB and not a DIB section (in the latter case the pointer must be passed + // to us by the caller) + if ( !bits ) + { + // we must skip over the colour table to get to the image data + + // biClrUsed has the number of colors but it may be not initialized at + // all + int numColors = pbmih->biClrUsed; + if ( !numColors ) + { + numColors = wxGetNumOfBitmapColors(pbmih->biBitCount); + } + + bits = (char *)pbmih + sizeof(*pbmih) + numColors*sizeof(RGBQUAD); + } + + HBITMAP hbmp = ::CreateDIBitmap + ( + hdc ? hdc // create bitmap compatible + : ScreenHDC(), // with this DC + pbmih, // used to get size &c + CBM_INIT, // initialize bitmap bits too + bits, // ... using this data + pbmi, // this is used for palette only + DIB_RGB_COLORS // direct or indexed palette? + ); + + if ( !hbmp ) + { + wxLogLastError(wxT("CreateDIBitmap")); + } + + return hbmp; +} + +/* static */ +size_t wxDIB::ConvertFromBitmap(BITMAPINFO *pbi, HBITMAP hbmp) +{ + wxASSERT_MSG( hbmp, wxT("invalid bmp can't be converted to DIB") ); + + // prepare all the info we need + BITMAP bm; + if ( !::GetObject(hbmp, sizeof(bm), &bm) ) + { + wxLogLastError(wxT("GetObject(bitmap)")); + + return 0; + } + + // calculate the number of bits per pixel and the number of items in + // bmiColors array (whose meaning depends on the bitmap format) + WORD biBits = bm.bmPlanes * bm.bmBitsPixel; + WORD biColors = wxGetNumOfBitmapColors(biBits); + + // we need a BITMAPINFO anyhow and if we're not given a pointer to it we + // use this one + BITMAPINFO bi2; + + bool wantSizeOnly = pbi == NULL; + if ( wantSizeOnly ) + pbi = &bi2; + + // just for convenience + const int h = bm.bmHeight; + + // init the header + BITMAPINFOHEADER& bi = pbi->bmiHeader; + wxZeroMemory(bi); + bi.biSize = sizeof(BITMAPINFOHEADER); + bi.biWidth = bm.bmWidth; + bi.biHeight = h; + bi.biPlanes = 1; + bi.biBitCount = biBits; + + // memory we need for BITMAPINFO only + DWORD dwLen = bi.biSize + biColors * sizeof(RGBQUAD); + + // first get the image size + ScreenHDC hdc; + if ( !::GetDIBits(hdc, hbmp, 0, h, NULL, pbi, DIB_RGB_COLORS) ) + { + wxLogLastError(wxT("GetDIBits(NULL)")); + + return 0; + } + + if ( !wantSizeOnly ) + { + // and now copy the bits + void *image = (char *)pbi + dwLen; + if ( !::GetDIBits(hdc, hbmp, 0, h, image, pbi, DIB_RGB_COLORS) ) + { + wxLogLastError(wxT("GetDIBits")); + + return 0; + } + } + + // return the total size + return dwLen + bi.biSizeImage; +} + +// ---------------------------------------------------------------------------- +// palette support +// ---------------------------------------------------------------------------- + +#if wxUSE_PALETTE + +wxPalette *wxDIB::CreatePalette() const +{ + wxCHECK_MSG( m_handle, NULL, _T("wxDIB::CreatePalette(): invalid object") ); + + DIBSECTION ds; + if ( !::GetObject(m_handle, sizeof(ds), &ds) ) + { + wxLogLastError(_T("GetObject(hDIB)")); + + return 0; + } + + // how many colours are we going to have in the palette? + DWORD biClrUsed = ds.dsBmih.biClrUsed; + if ( !biClrUsed ) + { + // biClrUsed field might not be set + biClrUsed = 1 << ds.dsBmih.biBitCount; + } + + if ( biClrUsed > 256 ) + { + // only 8bpp bitmaps (and less) have palettes, so we surely don't + // + // NB: another possibility would be to return + // GetStockObject(DEFAULT_PALETTE) or even CreateHalftonePalette()? + return NULL; + } + + // LOGPALETTE struct has only 1 element in palPalEntry array, we're + // going to have biClrUsed of them so add necessary space + LOGPALETTE *pPalette = (LOGPALETTE *) + malloc(sizeof(LOGPALETTE) + (biClrUsed - 1)*sizeof(PALETTEENTRY)); + wxCHECK_MSG( pPalette, NULL, _T("out of memory") ); + + // initialize the palette header + pPalette->palVersion = 0x300; // magic number, not in docs but works + pPalette->palNumEntries = biClrUsed; + + // and the colour table (it starts right after the end of the header) + const RGBQUAD *pRGB = (RGBQUAD *)((char *)&ds.dsBmih + ds.dsBmih.biSize); + for ( DWORD i = 0; i < biClrUsed; i++, pRGB++ ) + { + pPalette->palPalEntry[i].peRed = pRGB->rgbRed; + pPalette->palPalEntry[i].peGreen = pRGB->rgbGreen; + pPalette->palPalEntry[i].peBlue = pRGB->rgbBlue; + pPalette->palPalEntry[i].peFlags = 0; + } + + HPALETTE hPalette = ::CreatePalette(pPalette); + + free(pPalette); + + if ( !hPalette ) + { + wxLogLastError(_T("CreatePalette")); + + return NULL; + } + + wxPalette *palette = new wxPalette; + palette->SetHPALETTE((WXHPALETTE)hPalette); + + return palette; +} + +#endif // wxUSE_PALETTE + // ---------------------------------------------------------------------------- // wxImage support // ---------------------------------------------------------------------------- @@ -267,14 +506,14 @@ static bool wxWriteDIB(LPTSTR szFile, HANDLE hdib) LPBITMAPINFOHEADER lpbi; int fh; OFSTRUCT of; - + if (!hdib) return FALSE; - + fh = OpenFile(wxConvertWX2MB(szFile), &of, OF_CREATE | OF_READWRITE); if (fh == -1) return FALSE; - + lpbi = (LPBITMAPINFOHEADER) GlobalLock(hdib); /* Fill in the fields of the file header */ @@ -284,13 +523,13 @@ static bool wxWriteDIB(LPTSTR szFile, HANDLE hdib) hdr.bfReserved2 = 0; hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + lpbi->biSize + wxPaletteSize(lpbi); - + /* Write the file header */ _lwrite(fh, (LPSTR) &hdr, sizeof(BITMAPFILEHEADER)); - + /* Write the DIB header and the bits */ lwrite(fh, (LPSTR) lpbi, GlobalSize(hdib)); - + GlobalUnlock(hdib); _lclose(fh); return TRUE; @@ -309,10 +548,10 @@ WORD wxPaletteSize(VOID FAR * pv) { LPBITMAPINFOHEADER lpbi; WORD NumColors; - + lpbi = (LPBITMAPINFOHEADER) pv; NumColors = wxDibNumColors(lpbi); - + if (lpbi->biSize == sizeof(BITMAPCOREHEADER)) return (WORD)(NumColors * sizeof(RGBTRIPLE)); else @@ -331,10 +570,10 @@ static WORD wxDibNumColors(VOID FAR *pv) int bits; BITMAPINFOHEADER *lpbi; BITMAPCOREHEADER *lpbc; - + lpbi = ((BITMAPINFOHEADER*) pv); lpbc = ((BITMAPCOREHEADER*) pv); - + /* With the BITMAPINFO format headers, the size of the palette * is in biClrUsed, whereas in the BITMAPCORE - style headers, it * is dependent on the bits per pixel ( = 2 raised to the power of @@ -347,7 +586,7 @@ static WORD wxDibNumColors(VOID FAR *pv) } else bits = lpbc->bcBitCount; - + switch (bits) { case 1: return 2; @@ -424,7 +663,7 @@ static DWORD lwrite(int fh, VOID FAR *pv, DWORD ul) * filled with the appropriate handles. * FALSE - otherwise */ - + bool wxReadDIB(LPTSTR lpFileName, HBITMAP *bitmap, HPALETTE *palette) { int fh; @@ -437,32 +676,32 @@ bool wxReadDIB(LPTSTR lpFileName, HBITMAP *bitmap, HPALETTE *palette) HDC hDC; bool bCoreHead = FALSE; HANDLE hDIB = 0; - + /* Open the file and get a handle to it's BITMAPINFO */ - + fh = OpenFile (wxConvertWX2MB(lpFileName), &of, OF_READ); if (fh == -1) { wxLogError(_("Can't open file '%s'"), lpFileName); return (0); } - + hDIB = GlobalAlloc(GHND, (DWORD)(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD))); if (!hDIB) return(0); - + lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); - + /* read the BITMAPFILEHEADER */ if (sizeof (bf) != _lread (fh, (LPSTR)&bf, sizeof (bf))) goto ErrExit; - + if (bf.bfType != 0x4d42) /* 'BM' */ goto ErrExit; - + if (sizeof(BITMAPCOREHEADER) != _lread (fh, (LPSTR)lpbi, sizeof(BITMAPCOREHEADER))) goto ErrExit; - + if (lpbi->biSize == sizeof(BITMAPCOREHEADER)) { lpbi->biSize = sizeof(BITMAPINFOHEADER); @@ -479,7 +718,7 @@ bool wxReadDIB(LPTSTR lpFileName, HBITMAP *bitmap, HPALETTE *palette) if (sizeof(BITMAPINFOHEADER) != _lread (fh, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER))) goto ErrExit; } - + nNumColors = (WORD)lpbi->biClrUsed; if ( nNumColors == 0 ) { @@ -487,17 +726,17 @@ bool wxReadDIB(LPTSTR lpFileName, HBITMAP *bitmap, HPALETTE *palette) if (lpbi->biBitCount != 24) nNumColors = 1 << lpbi->biBitCount; /* standard size table */ } - + /* fill in some default values if they are zero */ if (lpbi->biClrUsed == 0) lpbi->biClrUsed = nNumColors; - + if (lpbi->biSizeImage == 0) { lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3) * lpbi->biHeight; } - + /* get a proper-sized buffer for header, color table and bits */ GlobalUnlock(hDIB); hDIB = GlobalReAlloc(hDIB, lpbi->biSize + @@ -505,9 +744,9 @@ bool wxReadDIB(LPTSTR lpFileName, HBITMAP *bitmap, HPALETTE *palette) lpbi->biSizeImage, 0); if (!hDIB) /* can't resize buffer for loading */ goto ErrExit2; - + lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); - + /* read the color table */ if (!bCoreHead) _lread(fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD)); @@ -516,9 +755,9 @@ bool wxReadDIB(LPTSTR lpFileName, HBITMAP *bitmap, HPALETTE *palette) signed int i; RGBQUAD FAR *pQuad; RGBTRIPLE FAR *pTriple; - + _lread(fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBTRIPLE)); - + pQuad = (RGBQUAD FAR *)((LPSTR)lpbi + lpbi->biSize); pTriple = (RGBTRIPLE FAR *) pQuad; for (i = nNumColors - 1; i >= 0; i--) @@ -529,19 +768,19 @@ bool wxReadDIB(LPTSTR lpFileName, HBITMAP *bitmap, HPALETTE *palette) pQuad[i].rgbReserved = 0; } } - + /* offset to the bits from start of DIB header */ offBits = (WORD)(lpbi->biSize + nNumColors * sizeof(RGBQUAD)); - + if (bf.bfOffBits != 0L) { _llseek(fh,bf.bfOffBits,SEEK_SET); } - + if (lpbi->biSizeImage == lread(fh, (LPSTR)lpbi + offBits, lpbi->biSizeImage)) { GlobalUnlock(hDIB); - + hDC = GetDC(NULL); if (!wxMakeBitmapAndPalette(hDC, hDIB, palette, bitmap)) @@ -563,7 +802,7 @@ ErrExit: ErrExit2: GlobalFree(hDIB); } - + _lclose(fh); return(result); } @@ -579,7 +818,7 @@ ErrExit2: * FALSE --> unable to create objects. both pointer are * not valid */ - + static bool wxMakeBitmapAndPalette(HDC hDC, HANDLE hDIB, HPALETTE * phPal, HBITMAP * phBitmap) { @@ -588,24 +827,24 @@ static bool wxMakeBitmapAndPalette(HDC hDC, HANDLE hDIB, HBITMAP hBitmap; HPALETTE hPalette, hOldPal; LPSTR lpBits; - + lpInfo = (LPBITMAPINFOHEADER) GlobalLock(hDIB); - + hPalette = wxMakeDIBPalette(lpInfo); if ( hPalette ) { // Need to realize palette for converting DIB to bitmap. hOldPal = SelectPalette(hDC, hPalette, TRUE); RealizePalette(hDC); - + lpBits = (LPSTR)lpInfo + (WORD)lpInfo->biSize + (WORD)lpInfo->biClrUsed * sizeof(RGBQUAD); hBitmap = CreateDIBitmap(hDC, lpInfo, CBM_INIT, lpBits, (LPBITMAPINFO)lpInfo, DIB_RGB_COLORS); - + SelectPalette(hDC, hOldPal, TRUE); RealizePalette(hDC); - + if (!hBitmap) DeleteObject(hPalette); else @@ -615,9 +854,9 @@ static bool wxMakeBitmapAndPalette(HDC hDC, HANDLE hDIB, result = TRUE; } } - + GlobalUnlock (hDIB); // glt - + return(result); } @@ -628,14 +867,14 @@ static bool wxMakeBitmapAndPalette(HDC hDC, HANDLE hDIB, * RETURNS : non-zero - handle of a corresponding palette * zero - unable to create palette */ - + HPALETTE wxMakeDIBPalette(LPBITMAPINFOHEADER lpInfo) { LPLOGPALETTE npPal; RGBQUAD far *lpRGB; HPALETTE hLogPal; WORD i; - + /* since biClrUsed field was filled during the loading of the DIB, * we know it contains the number of colors in the color table. */ @@ -645,13 +884,13 @@ HPALETTE wxMakeDIBPalette(LPBITMAPINFOHEADER lpInfo) (WORD)lpInfo->biClrUsed * sizeof(PALETTEENTRY)); if (!npPal) return NULL; - + npPal->palVersion = 0x300; npPal->palNumEntries = (WORD)lpInfo->biClrUsed; - + /* get pointer to the color table */ lpRGB = (RGBQUAD FAR *)((LPSTR)lpInfo + lpInfo->biSize); - + /* copy colors from the color table to the LogPalette structure */ for (i = 0; (DWORD)i < lpInfo->biClrUsed; i++, lpRGB++) { @@ -660,13 +899,13 @@ HPALETTE wxMakeDIBPalette(LPBITMAPINFOHEADER lpInfo) npPal->palPalEntry[i].peBlue = lpRGB->rgbBlue; npPal->palPalEntry[i].peFlags = 0; } - + hLogPal = CreatePalette((LPLOGPALETTE)npPal); free(npPal); - + return(hLogPal); } - + /* 24-bit DIB with no color table. Return default palette. Another * option would be to create a 256 color "rainbow" palette to provide * some good color choices. @@ -675,64 +914,6 @@ HPALETTE wxMakeDIBPalette(LPBITMAPINFOHEADER lpInfo) return((HPALETTE) GetStockObject(DEFAULT_PALETTE)); } -bool wxLoadIntoBitmap(wxChar *filename, wxBitmap *bitmap, wxPalette **pal) -{ - HBITMAP hBitmap = NULL; - HPALETTE hPalette = NULL; - - bool success = (wxReadDIB(filename, &hBitmap, &hPalette) != 0); - - if (!success) - { - if (hPalette) - DeleteObject(hPalette); - return FALSE; - } - - if (hPalette) - { -#if wxUSE_PALETTE - if (pal) - { - *pal = new wxPalette; - (*pal)->SetHPALETTE((WXHPALETTE) hPalette); - } - else -#endif // wxUSE_PALETTE - DeleteObject(hPalette); - } - else if (pal) - *pal = NULL; - - if (hBitmap) - { - BITMAP bm; - GetObject(hBitmap, sizeof(bm), (LPSTR)&bm); - - bitmap->SetHBITMAP((WXHBITMAP) hBitmap); - bitmap->SetWidth(bm.bmWidth); - bitmap->SetHeight(bm.bmHeight); - bitmap->SetDepth(bm.bmPlanes * bm.bmBitsPixel); -#if WXWIN_COMPATIBILITY_2 - bitmap->SetOk(TRUE); -#endif // WXWIN_COMPATIBILITY_2 - return TRUE; - } - else return FALSE; -} - -wxBitmap *wxLoadBitmap(wxChar *filename, wxPalette **pal) -{ - wxBitmap *bitmap = new wxBitmap; - if (wxLoadIntoBitmap(filename, bitmap, pal)) - return bitmap; - else - { - delete bitmap; - return NULL; - } -} - /* * * Function: InitBitmapInfoHeader @@ -768,12 +949,12 @@ static void InitBitmapInfoHeader (LPBITMAPINFOHEADER lpBmInfoHdr, { // _fmemset (lpBmInfoHdr, 0, sizeof (BITMAPINFOHEADER)); memset (lpBmInfoHdr, 0, sizeof (BITMAPINFOHEADER)); - + lpBmInfoHdr->biSize = sizeof (BITMAPINFOHEADER); lpBmInfoHdr->biWidth = dwWidth; lpBmInfoHdr->biHeight = dwHeight; lpBmInfoHdr->biPlanes = 1; - + if (nBPP <= 1) nBPP = 1; else if (nBPP <= 4) @@ -786,7 +967,7 @@ static void InitBitmapInfoHeader (LPBITMAPINFOHEADER lpBmInfoHdr, */ else nBPP = 24; - + lpBmInfoHdr->biBitCount = nBPP; lpBmInfoHdr->biSizeImage = WIDTHBYTES (dwWidth * nBPP) * dwHeight; } @@ -818,52 +999,52 @@ HANDLE wxBitmapToDIB (HBITMAP hBitmap, HPALETTE hPal) HDC hMemDC; HANDLE hDIB; HPALETTE hOldPal = NULL; - + // Do some setup -- make sure the Bitmap passed in is valid, // get info on the bitmap (like its height, width, etc.), // then setup a BITMAPINFOHEADER. - + if (!hBitmap) return NULL; - + if (!GetObject (hBitmap, sizeof (Bitmap), (LPSTR) &Bitmap)) return NULL; - + InitBitmapInfoHeader (&bmInfoHdr, Bitmap.bmWidth, Bitmap.bmHeight, - Bitmap.bmPlanes * Bitmap.bmBitsPixel); - + Bitmap.bmPlanes * Bitmap.bmBitsPixel); + // Now allocate memory for the DIB. Then, set the BITMAPINFOHEADER // into this memory, and find out where the bitmap bits go. - + hDIB = GlobalAlloc (GHND, sizeof (BITMAPINFOHEADER) + wxPaletteSize ((LPSTR) &bmInfoHdr) + bmInfoHdr.biSizeImage); - + if (!hDIB) return NULL; - + lpbmInfoHdr = (LPBITMAPINFOHEADER) GlobalLock (hDIB); - + *lpbmInfoHdr = bmInfoHdr; lpBits = wxFindDIBBits ((LPSTR) lpbmInfoHdr); - - + + // Now, we need a DC to hold our bitmap. If the app passed us // a palette, it should be selected into the DC. - + hMemDC = GetDC (NULL); - + if (hPal) { hOldPal = SelectPalette (hMemDC, hPal, FALSE); RealizePalette (hMemDC); } - + // We're finally ready to get the DIB. Call the driver and let // it party on our bitmap. It will fill in the color table, // and bitmap bits of our global memory block. - + if (!GetDIBits (hMemDC, hBitmap, 0, Bitmap.bmHeight, lpBits, (LPBITMAPINFO) lpbmInfoHdr, DIB_RGB_COLORS)) { @@ -872,15 +1053,15 @@ HANDLE wxBitmapToDIB (HBITMAP hBitmap, HPALETTE hPal) hDIB = NULL; } else - GlobalUnlock (hDIB); - + GlobalUnlock (hDIB); + // Finally, clean up and return. - + if (hOldPal) SelectPalette (hMemDC, hOldPal, FALSE); - + ReleaseDC (NULL, hMemDC); - + return hDIB; } @@ -891,7 +1072,7 @@ bool wxSaveBitmap(wxChar *filename, wxBitmap *bitmap, wxPalette *palette) if (palette) hPalette = (HPALETTE) palette->GetHPALETTE(); #endif // wxUSE_PALETTE - + HANDLE dibHandle = wxBitmapToDIB((HBITMAP) bitmap->GetHBITMAP(), hPalette); if (dibHandle) {