]> git.saurik.com Git - wxWidgets.git/commitdiff
Fix creation of wxBitmap from wxIcon in wxMSW: premultiply the pixels.
authorVadim Zeitlin <vadim@wxwidgets.org>
Wed, 9 May 2012 14:24:12 +0000 (14:24 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Wed, 9 May 2012 14:24:12 +0000 (14:24 +0000)
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

index 10756fee7ca3cbb1e2bd3bb850efac72e281a58e..98c813fd9d6a25a3344c4df9c32a6f626f9def3f 100644 (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();
+                        }
                     }
                 }
             }