diff --git a/src/msw/graphics.cpp b/src/msw/graphics.cpp index 21e5dc0df6..1d27ae3645 100644 --- a/src/msw/graphics.cpp +++ b/src/msw/graphics.cpp @@ -317,6 +317,7 @@ class WXDLLIMPEXP_CORE wxGDIPlusBitmapData : public wxGraphicsBitmapData public: wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, Bitmap* bitmap ); wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, const wxBitmap &bmp ); + wxGDIPlusBitmapData(wxGraphicsRenderer* renderer, const wxImage& img); ~wxGDIPlusBitmapData (); virtual Bitmap* GetGDIPlusBitmap() { return m_bitmap; } @@ -1294,6 +1295,67 @@ wxGDIPlusBitmapData::wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, } #if wxUSE_IMAGE +wxGDIPlusBitmapData::wxGDIPlusBitmapData(wxGraphicsRenderer* renderer, const wxImage& img) + : wxGraphicsBitmapData(renderer) +{ + m_helper = NULL; + m_bitmap = new Bitmap(img.GetWidth(), img.GetHeight(), img.HasAlpha() || img.HasMask() ? PixelFormat32bppPARGB : PixelFormat32bppRGB); + + UINT w = m_bitmap->GetWidth(); + UINT h = m_bitmap->GetHeight(); + Rect bounds(0, 0, (INT)w, (INT)h); + BitmapData bmpData; + m_bitmap->LockBits(&bounds, ImageLockModeWrite, PixelFormat32bppARGB, &bmpData); + + const unsigned char* imgRGB = img.GetData(); + const unsigned char* imgAlpha = img.GetAlpha(); + BYTE* pPixLine = reinterpret_cast(bmpData.Scan0); + for ( UINT y = 0; y < h; y++ ) + { + BYTE* pPixByte = pPixLine; + for ( UINT x = 0; x < w; x++ ) + { + unsigned char r = *imgRGB++; + unsigned char g = *imgRGB++; + unsigned char b = *imgRGB++; + *pPixByte++ = b; + *pPixByte++ = g; + *pPixByte++ = r; + *pPixByte++ = imgAlpha ? *imgAlpha++ : 255; + } + + pPixLine += bmpData.Stride; + } + + // If there is a mask, set the alpha bytes in the target buffer to + // fully transparent or retain original value + if ( img.HasMask() ) + { + unsigned char mr = img.GetMaskRed(); + unsigned char mg = img.GetMaskGreen(); + unsigned char mb = img.GetMaskBlue(); + imgRGB = img.GetData(); + pPixLine = reinterpret_cast(bmpData.Scan0); + for ( UINT y = 0; y < h; y++ ) + { + BYTE* pPixByte = pPixLine; + for ( UINT x = 0; x < w; x++ ) + { + unsigned char r = *imgRGB++; + unsigned char g = *imgRGB++; + unsigned char b = *imgRGB++; + if ( r == mr && g == mg && b == mb ) + pPixByte[0] = pPixByte[1] = pPixByte[2] = pPixByte[3] = 0; + + pPixByte += 4; + } + + pPixLine += bmpData.Stride; + } + } + + m_bitmap->UnlockBits(&bmpData); +} wxImage wxGDIPlusBitmapData::ConvertToImage() const { @@ -2818,12 +2880,6 @@ wxGraphicsBitmap wxGDIPlusRenderer::CreateBitmapFromImage(const wxImage& image) ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap); if ( image.IsOk() ) { - // Notice that we rely on conversion from wxImage to wxBitmap here but - // we could probably do it more efficiently by converting from wxImage - // to GDI+ Bitmap directly, i.e. copying wxImage pixels to the buffer - // returned by Bitmap::LockBits(). However this would require writing - // code specific for this task while like this we can reuse existing - // code (see also wxGDIPlusBitmapData::ConvertToImage()). wxGraphicsBitmap gb; gb.SetRefData(new wxGDIPlusBitmapData(this, image)); return gb;