Create native GDI+ representation of wxGraphicsBitmap directly from wxImage
Skip the conversion from wxImage to wxBitmap.
This commit is contained in:
@@ -317,6 +317,7 @@ class WXDLLIMPEXP_CORE wxGDIPlusBitmapData : public wxGraphicsBitmapData
|
|||||||
public:
|
public:
|
||||||
wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, Bitmap* bitmap );
|
wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, Bitmap* bitmap );
|
||||||
wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, const wxBitmap &bmp );
|
wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, const wxBitmap &bmp );
|
||||||
|
wxGDIPlusBitmapData(wxGraphicsRenderer* renderer, const wxImage& img);
|
||||||
~wxGDIPlusBitmapData ();
|
~wxGDIPlusBitmapData ();
|
||||||
|
|
||||||
virtual Bitmap* GetGDIPlusBitmap() { return m_bitmap; }
|
virtual Bitmap* GetGDIPlusBitmap() { return m_bitmap; }
|
||||||
@@ -1294,6 +1295,67 @@ wxGDIPlusBitmapData::wxGDIPlusBitmapData( wxGraphicsRenderer* renderer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if wxUSE_IMAGE
|
#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<BYTE*>(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<BYTE*>(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
|
wxImage wxGDIPlusBitmapData::ConvertToImage() const
|
||||||
{
|
{
|
||||||
@@ -2818,12 +2880,6 @@ wxGraphicsBitmap wxGDIPlusRenderer::CreateBitmapFromImage(const wxImage& image)
|
|||||||
ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap);
|
ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap);
|
||||||
if ( image.IsOk() )
|
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;
|
wxGraphicsBitmap gb;
|
||||||
gb.SetRefData(new wxGDIPlusBitmapData(this, image));
|
gb.SetRefData(new wxGDIPlusBitmapData(this, image));
|
||||||
return gb;
|
return gb;
|
||||||
|
Reference in New Issue
Block a user