From a25e66d479caabb5c79b19066e52498e185de91d Mon Sep 17 00:00:00 2001 From: Artur Wieczorek Date: Sun, 14 Feb 2021 00:01:53 +0100 Subject: [PATCH] Create native D2D representation of wxGraphicsBitmap directly from wxImage Skip the conversion from wxImage to wxBitmap. --- src/msw/graphicsd2d.cpp | 86 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/src/msw/graphicsd2d.cpp b/src/msw/graphicsd2d.cpp index 6216c739f6..3a4344cd3d 100644 --- a/src/msw/graphicsd2d.cpp +++ b/src/msw/graphicsd2d.cpp @@ -2441,6 +2441,79 @@ public: } #if wxUSE_IMAGE + wxD2DBitmapResourceHolder(const wxImage& img) + { + const int width = img.GetWidth(); + const int height = img.GetHeight(); + // Create a compatible WIC Bitmap + WICPixelFormatGUID fmt = img.HasAlpha() || img.HasMask() ? GUID_WICPixelFormat32bppPBGRA : GUID_WICPixelFormat32bppBGR; + HRESULT hr = wxWICImagingFactory()->CreateBitmap(width, height, fmt, WICBitmapCacheOnLoad, &m_srcBitmap); + wxCHECK_HRESULT_RET(hr); + + // Copy contents of source image to the WIC bitmap. + WICRect rcLock = { 0, 0, width, height }; + wxCOMPtr pLock; + hr = m_srcBitmap->Lock(&rcLock, WICBitmapLockWrite, &pLock); + wxCHECK_HRESULT_RET(hr); + + UINT rowStride = 0; + hr = pLock->GetStride(&rowStride); + wxCHECK_HRESULT_RET(hr); + + UINT bufferSize = 0; + BYTE* pBuffer = NULL; + hr = pLock->GetDataPointer(&bufferSize, &pBuffer); + wxCHECK_HRESULT_RET(hr); + + const unsigned char* imgRGB = img.GetData(); // source RGB buffer + const unsigned char* imgAlpha = img.GetAlpha(); // source alpha buffer + BYTE* pBmpBuffer = pBuffer; + for ( int y = 0; y < height; y++ ) + { + BYTE* pPixByte = pBmpBuffer; + for ( int x = 0; x < width; x++ ) + { + unsigned char r = *imgRGB++; + unsigned char g = *imgRGB++; + unsigned char b = *imgRGB++; + unsigned char a = imgAlpha?*imgAlpha++:255; + // Premultiply RGB values + *pPixByte++ = (b * a + 127) / 255; + *pPixByte++ = (g * a + 127) / 255; + *pPixByte++ = (r * a + 127) / 255; + *pPixByte++ = a; + } + + pBmpBuffer += rowStride; + } + + // 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(); + pBmpBuffer = pBuffer; + for ( int y = 0; y < height; y++ ) + { + BYTE* pPixByte = pBmpBuffer; + for ( int x = 0; x < width; x++ ) + { + if ( imgRGB[0] == mr && imgRGB[1] == mg && imgRGB[2] == mb ) + pPixByte[0] = pPixByte[1] = pPixByte[2] = pPixByte[3] = 0; + + imgRGB += 3; + pPixByte += 4; + } + + pBmpBuffer += rowStride; + } + } + } + wxImage ConvertToImage() const { UINT width, height; @@ -2554,6 +2627,12 @@ public: m_bitmapHolder = new NativeType(bitmap); } + wxD2DBitmapData(wxGraphicsRenderer* renderer, const wxImage& image) : + wxGraphicsBitmapData(renderer) + { + m_bitmapHolder = new NativeType(image); + } + wxD2DBitmapData(wxGraphicsRenderer* renderer, NativeType* pseudoNativeBitmap) : wxGraphicsBitmapData(renderer), m_bitmapHolder(pseudoNativeBitmap) {} @@ -5241,7 +5320,12 @@ wxGraphicsBitmap wxD2DRenderer::CreateBitmapFromNativeBitmap(void* bitmap) #if wxUSE_IMAGE wxGraphicsBitmap wxD2DRenderer::CreateBitmapFromImage(const wxImage& image) { - return CreateBitmap(wxBitmap(image)); + wxD2DBitmapData* bitmapData = new wxD2DBitmapData(this, image); + + wxGraphicsBitmap graphicsBitmap; + graphicsBitmap.SetRefData(bitmapData); + + return graphicsBitmap; } wxImage wxD2DRenderer::CreateImageFromBitmap(const wxGraphicsBitmap& bmp)