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
This commit is contained in:
Vadim Zeitlin 2012-05-09 14:24:12 +00:00
parent 39d169639b
commit 2c2138e937

View File

@ -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();
}
}
}
}