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
 | 
					#if wxUSE_IMAGE
 | 
				
			||||||
    // create a DIB from the given image, the DIB will be either 24 or 32 (if
 | 
					    // Possible formats for DIBs created by the functions below.
 | 
				
			||||||
    // the image has alpha channel) bpp
 | 
					    enum PixelFormat
 | 
				
			||||||
    wxDIB(const wxImage& image) { Init(); (void)Create(image); }
 | 
					    {
 | 
				
			||||||
 | 
					        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
 | 
					    // 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
 | 
					    // create wxImage having the same data as this DIB
 | 
				
			||||||
    wxImage ConvertToImage() const;
 | 
					    wxImage ConvertToImage() const;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -658,7 +658,7 @@ wxPalette *wxDIB::CreatePalette() const
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#if wxUSE_IMAGE
 | 
					#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") );
 | 
					    wxCHECK_MSG( image.Ok(), false, wxT("invalid wxImage in wxDIB ctor") );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -683,14 +683,18 @@ bool wxDIB::Create(const wxImage& image)
 | 
				
			|||||||
    unsigned char *dstLineStart = (unsigned char *)m_data;
 | 
					    unsigned char *dstLineStart = (unsigned char *)m_data;
 | 
				
			||||||
    for ( int y = 0; y < h; y++ )
 | 
					    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;
 | 
					        unsigned char *dst = dstLineStart;
 | 
				
			||||||
        if ( alpha )
 | 
					        if ( alpha )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            switch ( pf )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                case PixelFormat_PreMultiplied:
 | 
				
			||||||
 | 
					                    // Pre-multiply pixel values so that the DIB could be used
 | 
				
			||||||
 | 
					                    // with ::AlphaBlend().
 | 
				
			||||||
                    for ( int x = 0; x < w; x++ )
 | 
					                    for ( int x = 0; x < w; x++ )
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                // RGB order is reversed, and we need to premultiply
 | 
					 | 
				
			||||||
                // all channels by alpha value for use with ::AlphaBlend.
 | 
					 | 
				
			||||||
                        const unsigned char a = *alpha++;
 | 
					                        const unsigned char a = *alpha++;
 | 
				
			||||||
                        *dst++ = (unsigned char)((src[2] * a + 127) / 255);
 | 
					                        *dst++ = (unsigned char)((src[2] * a + 127) / 255);
 | 
				
			||||||
                        *dst++ = (unsigned char)((src[1] * a + 127) / 255);
 | 
					                        *dst++ = (unsigned char)((src[1] * a + 127) / 255);
 | 
				
			||||||
@@ -698,12 +702,27 @@ bool wxDIB::Create(const wxImage& image)
 | 
				
			|||||||
                        *dst++ = a;
 | 
					                        *dst++ = a;
 | 
				
			||||||
                        src += 3;
 | 
					                        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
 | 
					        else // no alpha channel
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            for ( int x = 0; x < w; x++ )
 | 
					            for ( int x = 0; x < w; x++ )
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // RGB order is reversed.
 | 
					 | 
				
			||||||
                *dst++ = src[2];
 | 
					                *dst++ = src[2];
 | 
				
			||||||
                *dst++ = src[1];
 | 
					                *dst++ = src[1];
 | 
				
			||||||
                *dst++ = src[0];
 | 
					                *dst++ = src[0];
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user