]> git.saurik.com Git - wxWidgets.git/commitdiff
Allow creating DIBs storing pixels in non-premultiplied format in wxMSW.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 30 Oct 2010 23:50:50 +0000 (23:50 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 30 Oct 2010 23:50:50 +0000 (23:50 +0000)
wxDIB assumed that MSW always uses bitmaps in pre-multiplied pixel format but
this turns out to be wrong: some Windows functions such as ImageList_Draw()
or CreateIconIndirect() apply pre-multiplication internally and so must be
given data in non-pre-multiplied format on input.

This commit adds a possibility to create wxDIB in such format but doesn't use
it anywhere yet, this will be done in subsequent commits.

See #9050.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65959 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/msw/dib.h
src/msw/dib.cpp

index c85c9e9d2c77a4c325c7a6739c8eeefb01f31bd2..58061449f1222eae24ecdc92264b415bc52cc095 100644 (file)
@@ -138,12 +138,28 @@ public:
     // ------------------
 
 #if wxUSE_IMAGE
-    // create a DIB from the given image, the DIB will be either 24 or 32 (if
-    // the image has alpha channel) bpp
-    wxDIB(const wxImage& image) { Init(); (void)Create(image); }
+    // Possible formats for DIBs created by the functions below.
+    enum PixelFormat
+    {
+        PixelFormat_PreMultiplied = 0,
+        PixelFormat_NotPreMultiplied = 1
+    };
+
+    // Create a DIB from the given image, the DIB will be either 24 or 32 (if
+    // the image has alpha channel) bpp.
+    //
+    // By default the DIB stores pixel data in pre-multiplied format so that it
+    // can be used with ::AlphaBlend() but it is also possible to disable
+    // pre-multiplication for the DIB to be usable with ImageList_Draw() which
+    // does pre-multiplication internally.
+    wxDIB(const wxImage& image, PixelFormat pf = PixelFormat_PreMultiplied)
+    {
+        Init();
+        (void)Create(image, pf);
+    }
 
     // same as the above ctor but with the return code
-    bool Create(const wxImage& image);
+    bool Create(const wxImage& image, PixelFormat pf = PixelFormat_PreMultiplied);
 
     // create wxImage having the same data as this DIB
     wxImage ConvertToImage() const;
index 45986e70ad141ba5c8714ff594d41077b0015dfd..23ed673d494e341ca42ab250e81932bb06aa6246 100644 (file)
@@ -658,7 +658,7 @@ wxPalette *wxDIB::CreatePalette() const
 
 #if wxUSE_IMAGE
 
-bool wxDIB::Create(const wxImage& image)
+bool wxDIB::Create(const wxImage& image, PixelFormat pf)
 {
     wxCHECK_MSG( image.Ok(), false, wxT("invalid wxImage in wxDIB ctor") );
 
@@ -683,27 +683,46 @@ bool wxDIB::Create(const wxImage& image)
     unsigned char *dstLineStart = (unsigned char *)m_data;
     for ( int y = 0; y < h; y++ )
     {
-        // copy one DIB line
+        // Copy one DIB line. Note that RGB components order is reversed in
+        // Windows bitmaps compared to wxImage and is actually BGR.
         unsigned char *dst = dstLineStart;
         if ( alpha )
         {
-            for ( int x = 0; x < w; x++ )
+            switch ( pf )
             {
-                // RGB order is reversed, and we need to premultiply
-                // all channels by alpha value for use with ::AlphaBlend.
-                const unsigned char a = *alpha++;
-                *dst++ = (unsigned char)((src[2] * a + 127) / 255);
-                *dst++ = (unsigned char)((src[1] * a + 127) / 255);
-                *dst++ = (unsigned char)((src[0] * a + 127) / 255);
-                *dst++ = a;
-                src += 3;
+                case PixelFormat_PreMultiplied:
+                    // Pre-multiply pixel values so that the DIB could be used
+                    // with ::AlphaBlend().
+                    for ( int x = 0; x < w; x++ )
+                    {
+                        const unsigned char a = *alpha++;
+                        *dst++ = (unsigned char)((src[2] * a + 127) / 255);
+                        *dst++ = (unsigned char)((src[1] * a + 127) / 255);
+                        *dst++ = (unsigned char)((src[0] * a + 127) / 255);
+                        *dst++ = a;
+                        src += 3;
+                    }
+                    break;
+
+                case PixelFormat_NotPreMultiplied:
+                    // Just copy pixel data without changing it.
+                    for ( int x = 0; x < w; x++ )
+                    {
+                        *dst++ = src[2];
+                        *dst++ = src[1];
+                        *dst++ = src[0];
+
+                        *dst++ = *alpha++;
+                        src += 3;
+                    }
+                    break;
             }
+
         }
         else // no alpha channel
         {
             for ( int x = 0; x < w; x++ )
             {
-                // RGB order is reversed.
                 *dst++ = src[2];
                 *dst++ = src[1];
                 *dst++ = src[0];