Allow creating DIBs storing pixels in non-premultiplied format in wxMSW.
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
This commit is contained in:
		| @@ -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; | ||||
|   | ||||
| @@ -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]; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user