+ // are we going to use DIB?
+ //
+ // NB: DDBs don't support alpha so if we have alpha channel we must use DIB
+ if ( image.HasAlpha() || wxShouldCreateDIB(w, h, depth, hdc) )
+ {
+ // don't delete the DIB section in dib object dtor
+ hbitmap = dib.Detach();
+
+ refData->m_isDIB = true;
+ refData->m_depth = dib.GetDepth();
+ }
+#ifndef ALWAYS_USE_DIB
+ else // we need to convert DIB to DDB
+ {
+ hbitmap = dib.CreateDDB((HDC)hdc);
+
+ refData->m_depth = depth == -1 ? dib.GetDepth() : depth;
+ }
+#endif // !ALWAYS_USE_DIB
+
+ // validate this object
+ SetHBITMAP((WXHBITMAP)hbitmap);
+
+ // finally also set the mask if we have one
+ if ( image.HasMask() )
+ {
+ SetMask(new wxMask(*this, wxColour(image.GetMaskRed(),
+ image.GetMaskGreen(),
+ image.GetMaskBlue())));
+ }
+
+ return true;
+}
+
+wxImage wxBitmap::ConvertToImage() const
+{
+ // convert DDB to DIB
+ wxDIB dib(*this);
+
+ if ( !dib.IsOk() )
+ {
+ return wxNullImage;
+ }
+
+ // and then DIB to our wxImage
+ wxImage image = dib.ConvertToImage();
+ if ( !image.Ok() )
+ {
+ return wxNullImage;
+ }
+
+ // now do the same for the mask, if we have any
+ HBITMAP hbmpMask = GetMask() ? (HBITMAP) GetMask()->GetMaskBitmap() : NULL;
+ if ( hbmpMask )
+ {
+ wxDIB dibMask(hbmpMask);
+ if ( dibMask.IsOk() )
+ {
+ // TODO: use wxRawBitmap to iterate over DIB
+
+ // we hard code the mask colour for now but we could also make an
+ // effort (and waste time) to choose a colour not present in the
+ // image already to avoid having to fudge the pixels below --
+ // whether it's worth to do it is unclear however
+ static const int MASK_RED = 1;
+ static const int MASK_GREEN = 2;
+ static const int MASK_BLUE = 3;
+ static const int MASK_BLUE_REPLACEMENT = 2;
+
+ const int h = dibMask.GetHeight();
+ const int w = dibMask.GetWidth();
+ const int bpp = dibMask.GetDepth();
+ const int maskBytesPerPixel = bpp >> 3;
+ const int maskBytesPerLine = wxDIB::GetLineSize(w, bpp);
+ unsigned char *data = image.GetData();
+
+ // remember that DIBs are stored in bottom to top order
+ unsigned char *
+ maskLineStart = dibMask.GetData() + ((h - 1) * maskBytesPerLine);
+
+ for ( int y = 0; y < h; y++, maskLineStart -= maskBytesPerLine )
+ {
+ // traverse one mask DIB line
+ unsigned char *mask = maskLineStart;
+ for ( int x = 0; x < w; x++, mask += maskBytesPerPixel )
+ {
+ // should this pixel be transparent?
+ if ( *mask )
+ {
+ // no, check that it isn't transparent by accident
+ if ( (data[0] == MASK_RED) &&
+ (data[1] == MASK_GREEN) &&
+ (data[2] == MASK_BLUE) )
+ {
+ // we have to fudge the colour a bit to prevent
+ // this pixel from appearing transparent
+ data[2] = MASK_BLUE_REPLACEMENT;
+ }
+
+ data += 3;
+ }
+ else // yes, transparent pixel
+ {
+ *data++ = MASK_RED;
+ *data++ = MASK_GREEN;
+ *data++ = MASK_BLUE;
+ }
+ }
+ }
+
+ image.SetMaskColour(MASK_RED, MASK_GREEN, MASK_BLUE);
+ }
+ }
+
+ return image;