+ if (!hMaskBitmap)
+ {
+ hasMask = FALSE;
+ }
+ else
+ {
+ hScreenDC = ::GetDC(NULL);
+ hMaskDC = ::CreateCompatibleDC(hScreenDC);
+ ::ReleaseDC(NULL, hScreenDC);
+
+ hOldMaskBitmap = ::SelectObject( hMaskDC, hMaskBitmap);
+ }
+#else
+ hasMask = FALSE;
+#endif
+ }
+
+ int i, j;
+ for (i = 0; i < image.GetWidth(); i++)
+ {
+ for (j = 0; j < image.GetHeight(); j++)
+ {
+ unsigned char red = image.GetRed(i, j);
+ unsigned char green = image.GetGreen(i, j);
+ unsigned char blue = image.GetBlue(i, j);
+
+ ::SetPixel(hMemDC, i, j, PALETTERGB(red, green, blue));
+
+ if (hasMask)
+ {
+ // scan the bitmap for the transparent colour and set the corresponding
+ // pixels in the mask to BLACK and the rest to WHITE
+ if (maskR == red && maskG == green && maskB == blue)
+ ::SetPixel(hMaskDC, i, j, PALETTERGB(0, 0, 0));
+ else
+ ::SetPixel(hMaskDC, i, j, PALETTERGB(255, 255, 255));
+ }
+ }
+ }
+
+ ::SelectObject(hMemDC, hOldBitmap);
+ ::DeleteDC(hMemDC);
+ if (hasMask)
+ {
+ ::SelectObject(hMaskDC, hOldMaskBitmap);
+ ::DeleteDC(hMaskDC);
+
+ ((wxBitmapRefData*)m_refData)->SetMask(hMaskBitmap);
+ }
+
+ SetWidth(image.GetWidth());
+ SetHeight(image.GetHeight());
+ SetDepth(screenDepth);
+ SetHBITMAP( (WXHBITMAP) hBitmap );
+
+#if wxUSE_PALETTE
+ // Copy the palette from the source image
+ SetPalette(image.GetPalette());
+#endif // wxUSE_PALETTE
+
+#if WXWIN_COMPATIBILITY_2
+ // check the wxBitmap object
+ GetBitmapData()->SetOk();
+#endif // WXWIN_COMPATIBILITY_2
+
+ return TRUE;
+
+#else // !__WXMICROWIN__
+ wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") )
+
+ m_refData = new wxBitmapRefData();
+
+#if wxUSE_DIB_FOR_BITMAP
+ int h = image.GetHeight();
+ int w = image.GetWidth();
+ unsigned char *dibBits = (unsigned char*)CreateDIB(w, h, 24);
+ if ( !dibBits )
+ return FALSE;
+
+ // DIBs are stored in bottom to top order so we need to copy bits line by
+ // line and starting from the end
+ const int srcBytesPerLine = w * 3;
+ const int dstBytesPerLine = (srcBytesPerLine + sizeof(DWORD) - 1) /
+ sizeof(DWORD) * sizeof(DWORD);
+ const unsigned char *src = image.GetData() + ((h - 1) * srcBytesPerLine);
+ for ( int i = 0; i < h; i++ )
+ {
+ // copy one DIB line
+ int x = w;
+ const unsigned char *rgbBits = src;
+ while ( x-- )
+ {
+ // also, the order of RGB is inversed for DIBs
+ *dibBits++ = rgbBits[2];
+ *dibBits++ = rgbBits[1];
+ *dibBits++ = rgbBits[0];
+
+ rgbBits += 3;
+ }
+
+ // pass to the next line
+ src -= srcBytesPerLine;
+ dibBits += dstBytesPerLine - srcBytesPerLine;
+ }
+
+ if ( image.HasMask() )
+ {
+ SetMask(new wxMask(*this, wxColour(image.GetMaskRed(),
+ image.GetMaskGreen(),
+ image.GetMaskBlue())));
+ }
+#else // wxUSE_DIB_FOR_BITMAP
+ // sizeLimit is the MS upper limit for the DIB size
+#ifdef WIN32
+ int sizeLimit = 1024*768*3;
+#else
+ int sizeLimit = 0x7fff;
+#endif
+
+ // width and height of the device-dependent bitmap
+ int width = image.GetWidth();
+ int bmpHeight = image.GetHeight();
+
+ // calc the number of bytes per scanline and padding
+ int bytePerLine = width*3;
+ int sizeDWORD = sizeof( DWORD );
+ int lineBoundary = bytePerLine % sizeDWORD;
+ int padding = 0;
+ if( lineBoundary > 0 )
+ {
+ padding = sizeDWORD - lineBoundary;
+ bytePerLine += padding;
+ }
+ // calc the number of DIBs and heights of DIBs
+ int numDIB = 1;
+ int hRemain = 0;
+ int height = sizeLimit/bytePerLine;
+ if( height >= bmpHeight )
+ height = bmpHeight;
+ else
+ {
+ numDIB = bmpHeight / height;
+ hRemain = bmpHeight % height;
+ if( hRemain >0 ) numDIB++;
+ }
+
+ // set bitmap parameters
+ wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") );
+ SetWidth( width );
+ SetHeight( bmpHeight );
+ if (depth == -1) depth = wxDisplayDepth();
+ SetDepth( depth );
+
+#if wxUSE_PALETTE
+ // Copy the palette from the source image
+ SetPalette(image.GetPalette());
+#endif // wxUSE_PALETTE
+
+ // create a DIB header
+ int headersize = sizeof(BITMAPINFOHEADER);
+ BITMAPINFO *lpDIBh = (BITMAPINFO *) malloc( headersize );
+ wxCHECK_MSG( lpDIBh, FALSE, wxT("could not allocate memory for DIB header") );
+ // Fill in the DIB header
+ lpDIBh->bmiHeader.biSize = headersize;
+ lpDIBh->bmiHeader.biWidth = (DWORD)width;
+ lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
+ lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
+ // the general formula for biSizeImage:
+ // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
+ lpDIBh->bmiHeader.biPlanes = 1;
+ lpDIBh->bmiHeader.biBitCount = 24;
+ lpDIBh->bmiHeader.biCompression = BI_RGB;
+ lpDIBh->bmiHeader.biClrUsed = 0;
+ // These seem not really needed for our purpose here.
+ lpDIBh->bmiHeader.biClrImportant = 0;
+ lpDIBh->bmiHeader.biXPelsPerMeter = 0;
+ lpDIBh->bmiHeader.biYPelsPerMeter = 0;
+ // memory for DIB data
+ unsigned char *lpBits;
+ lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
+ if( !lpBits )
+ {
+ wxFAIL_MSG( wxT("could not allocate memory for DIB") );
+ free( lpDIBh );
+ return FALSE;
+ }
+
+ // create and set the device-dependent bitmap
+ HDC hdc = ::GetDC(NULL);
+ HDC memdc = ::CreateCompatibleDC( hdc );
+ HBITMAP hbitmap;
+ hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
+ ::SelectObject( memdc, hbitmap);