From eda112dbfa08d802d29819a720ae40da0fa2223b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 29 Jan 2014 22:24:27 +0000 Subject: [PATCH] Fix display of bitmaps with alpha in wxStaticBitmap under MSW. Avoid double alpha pre-multiplication by converting the bitmap into a non pre-multiplied format before passing it to STM_SETIMAGE. Closes #2395. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_3_0_BRANCH@75727 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + src/msw/statbmp.cpp | 28 +++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/docs/changes.txt b/docs/changes.txt index d7c93adada..cc2dc4aa60 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -615,6 +615,7 @@ wxMSW: - Fix wxSocket::Initialize() after Shutdown() (Laurent Poujoulat). - Fix coordinates of EVT_MOUSEWHEEL in frames with toolbars (LtJax). - Support "show" verb as well as "open" in wxFileType (Eric Jensen). +- Fix display of bitmaps with alpha in wxStaticBitmap (Artur Wieczorek). wxOSX: diff --git a/src/msw/statbmp.cpp b/src/msw/statbmp.cpp index 496df705a8..77e8df1aff 100644 --- a/src/msw/statbmp.cpp +++ b/src/msw/statbmp.cpp @@ -35,6 +35,7 @@ #endif #include "wx/msw/private.h" +#include "wx/msw/dib.h" #include "wx/sysopt.h" @@ -266,6 +267,26 @@ void wxStaticBitmap::SetImageNoCopy( wxGDIImage* image) #ifdef __WIN32__ HANDLE handle = (HANDLE)m_image->GetHandle(); + + AutoHBITMAP hbmpRelease; + if ( !m_isIcon ) + { + // wxBitmap normally stores alpha in pre-multiplied format but + // apparently STM_SETIMAGE message handler does pre-multiplication + // internally so we need to undo the pre-multiplication here for a + // while (this is similar to what we do in ImageList::Add()). + const wxBitmap& bmp = static_cast(*image); + if ( bmp.HasAlpha() ) + { + // For bitmap with alpha channel create temporary DIB with + // not-premultiplied alpha values. + handle = wxDIB(bmp.ConvertToImage(), + wxDIB::PixelFormat_NotPreMultiplied).Detach(); + + // Ensure that this temporary HBITMAP will be destroyed. + hbmpRelease.Init((HBITMAP)handle); + } + } LONG style = ::GetWindowLong( (HWND)GetHWND(), GWL_STYLE ) ; ::SetWindowLong( (HWND)GetHWND(), GWL_STYLE, ( style & ~( SS_BITMAP|SS_ICON ) ) | ( m_isIcon ? SS_ICON : SS_BITMAP ) ); @@ -278,7 +299,12 @@ void wxStaticBitmap::SetImageNoCopy( wxGDIImage* image) // the static control made a copy and we are responsible for deleting it DeleteObject((HGDIOBJ) oldHandle); } - m_currentHandle = (WXHANDLE)handle; + + // Save bitmap handle only if it's not a temporary one, otherwise it's + // going to be destroyed right now anyhow. + if ( !hbmpRelease ) + m_currentHandle = (WXHANDLE)handle; + #endif // Win32 if ( ImageIsOk() )