From 2c2138e9374cbf7b5ee7c0659baf948740dc9d8b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 9 May 2012 14:24:12 +0000 Subject: [PATCH] Fix creation of wxBitmap from wxIcon in wxMSW: premultiply the pixels. wxBitmap in wxMSW is supposed to store its data in alpha-premultiplied format but didn't do it when it was created from an icon (or a cursor), resulting in wrong display of wxIcons with alpha channel when they were used for e.g. menu items. Fix this by ensuring that the data is always premultiplied. This is not the best solution as in some cases (e.g. if this wxBitmap is added to wxImageList later) we could need to undo this premultiplication later which is quite inefficient but at least it's simple and straightforward. Closes #11414. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@71385 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/msw/bitmap.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/msw/bitmap.cpp b/src/msw/bitmap.cpp index 10756fee7c..98c813fd9d 100644 --- a/src/msw/bitmap.cpp +++ b/src/msw/bitmap.cpp @@ -342,8 +342,9 @@ bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon, wxDIB dib(iconInfo.hbmColor); if (dib.IsOk()) { - const unsigned char* pixels = dib.GetData(); - for (int idx = 0; idx < w*h*4; idx+=4) + unsigned char* const pixels = dib.GetData(); + int idx; + for ( idx = 0; idx < w*h*4; idx += 4 ) { if (pixels[idx+3] != 0) { @@ -353,6 +354,25 @@ bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon, break; } } + + if ( refData->m_hasAlpha ) + { + // If we do have alpha, ensure we use premultiplied + // data for our pixels as this is what the bitmaps + // created in other ways do and this is necessary + // for e.g. AlphaBlend() to work with this bitmap. + for ( idx = 0; idx < w*h*4; idx += 4 ) + { + const unsigned char a = pixels[idx+3]; + + pixels[idx] = ((pixels[idx] *a) + 127)/255; + pixels[idx+1] = ((pixels[idx+1]*a) + 127)/255; + pixels[idx+2] = ((pixels[idx+2]*a) + 127)/255; + } + + ::DeleteObject(refData->m_hBitmap); + refData->m_hBitmap = dib.Detach(); + } } } }