]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/dib.cpp
use first unused colour for the mask instead of hardcoded #ff00ff (patch 1746895)
[wxWidgets.git] / src / msw / dib.cpp
index a7eebe54f289994fbfbf2ab031ac38b2f2adb2b4..2abcde95b7fddca404af6d7f4ba47abd1968c828 100644 (file)
     #pragma hdrstop
 #endif
 
+#if wxUSE_WXDIB
+
 #ifndef WX_PRECOMP
     #include "wx/string.h"
     #include "wx/log.h"
+    #include "wx/intl.h"
+    #include "wx/bitmap.h"
+    #include "wx/image.h"
 #endif //WX_PRECOMP
 
-#if wxUSE_WXDIB
-
-#include "wx/bitmap.h"
-#include "wx/intl.h"
 #include "wx/file.h"
 
 #include <stdio.h>
     #include <memory.h>
 #endif
 
-#ifdef __GNUWIN32_OLD__
-    #include "wx/msw/gnuwin32/extra.h"
-#endif
-
-#include "wx/image.h"
 #include "wx/msw/dib.h"
 
 #ifdef __WXWINCE__
@@ -69,7 +65,7 @@ static inline WORD GetNumberOfColours(WORD bitsPerPixel)
 {
     // only 1, 4 and 8bpp bitmaps use palettes (well, they could be used with
     // 24bpp ones too but we don't support this as I think it's quite uncommon)
-    return bitsPerPixel <= 8 ? 1 << bitsPerPixel : 0;
+    return (WORD)(bitsPerPixel <= 8 ? 1 << bitsPerPixel : 0);
 }
 
 // wrapper around ::GetObject() for DIB sections
@@ -118,7 +114,7 @@ bool wxDIB::Create(int width, int height, int depth)
     info->bmiHeader.biHeight = height;
 
     info->bmiHeader.biPlanes = 1;
-    info->bmiHeader.biBitCount = depth;
+    info->bmiHeader.biBitCount = (WORD)depth;
     info->bmiHeader.biSizeImage = GetLineSize(width, depth)*height;
 
     m_handle = ::CreateDIBSection
@@ -290,7 +286,7 @@ bool wxDIB::Load(const wxString& filename)
     m_handle = (HBITMAP)::LoadImage
                          (
                             wxGetInstance(),
-                            filename,
+                            filename.fn_str(),
                             IMAGE_BITMAP,
                             0, 0, // don't specify the size
                             LR_CREATEDIBSECTION | LR_LOADFROMFILE
@@ -398,7 +394,31 @@ HBITMAP wxDIB::CreateDDB(HDC hdc) const
         return 0;
     }
 
-    return ConvertToBitmap((BITMAPINFO *)&ds.dsBmih, hdc, ds.dsBm.bmBits);
+    // how many colours are we going to have in the palette?
+    DWORD biClrUsed = ds.dsBmih.biClrUsed;
+    if ( !biClrUsed )
+    {
+        // biClrUsed field might not be set
+        biClrUsed = GetNumberOfColours(ds.dsBmih.biBitCount);
+    }
+
+    if ( !biClrUsed )
+    {
+        return ConvertToBitmap((BITMAPINFO *)&ds.dsBmih, hdc, ds.dsBm.bmBits);
+    }
+    else
+    {
+        // fake a BITMAPINFO w/o bits, just the palette info
+        wxCharBuffer bmi(sizeof(BITMAPINFO) + (biClrUsed - 1)*sizeof(RGBQUAD));
+        BITMAPINFO *pBmi = (BITMAPINFO *)bmi.data();
+        MemoryHDC hDC;
+        // get the colour table
+        SelectInHDC sDC(hDC, m_handle);
+        ::GetDIBColorTable(hDC, 0, biClrUsed, pBmi->bmiColors);
+        memcpy(&pBmi->bmiHeader, &ds.dsBmih, ds.dsBmih.biSize);
+
+        return ConvertToBitmap(pBmi, hdc, ds.dsBm.bmBits);
+    }
 }
 
 /* static */
@@ -546,7 +566,7 @@ HGLOBAL wxDIB::ConvertFromBitmap(HBITMAP hbmp)
         return NULL;
     }
 
-    if ( !ConvertFromBitmap((BITMAPINFO *)(void *)GlobalPtr(hDIB), hbmp) )
+    if ( !ConvertFromBitmap((BITMAPINFO *)(void *)GlobalPtrLock(hDIB), hbmp) )
     {
         // this really shouldn't happen... it worked the first time, why not
         // now?
@@ -568,6 +588,10 @@ HGLOBAL wxDIB::ConvertFromBitmap(HBITMAP hbmp)
 
 wxPalette *wxDIB::CreatePalette() const
 {
+    // GetDIBColorTable not available in eVC3
+#if defined(_WIN32_WCE) && _WIN32_WCE < 400
+    return NULL;
+#else
     wxCHECK_MSG( m_handle, NULL, _T("wxDIB::CreatePalette(): invalid object") );
 
     DIBSECTION ds;
@@ -595,6 +619,8 @@ wxPalette *wxDIB::CreatePalette() const
         return NULL;
     }
 
+    MemoryHDC hDC;
+
     // LOGPALETTE struct has only 1 element in palPalEntry array, we're
     // going to have biClrUsed of them so add necessary space
     LOGPALETTE *pPalette = (LOGPALETTE *)
@@ -603,10 +629,13 @@ wxPalette *wxDIB::CreatePalette() const
 
     // initialize the palette header
     pPalette->palVersion = 0x300;  // magic number, not in docs but works
-    pPalette->palNumEntries = biClrUsed;
+    pPalette->palNumEntries = (WORD)biClrUsed;
 
-    // and the colour table (it starts right after the end of the header)
-    const RGBQUAD *pRGB = (RGBQUAD *)((char *)&ds.dsBmih + ds.dsBmih.biSize);
+    // and the colour table
+    wxCharBuffer rgb(sizeof(RGBQUAD) * biClrUsed);
+    RGBQUAD *pRGB = (RGBQUAD*)rgb.data();
+    SelectInHDC selectHandle(hDC, m_handle);
+    ::GetDIBColorTable(hDC, 0, biClrUsed, pRGB);
     for ( DWORD i = 0; i < biClrUsed; i++, pRGB++ )
     {
         pPalette->palPalEntry[i].peRed = pRGB->rgbRed;
@@ -630,6 +659,7 @@ wxPalette *wxDIB::CreatePalette() const
     palette->SetHPALETTE((WXHPALETTE)hPalette);
 
     return palette;
+#endif
 }
 
 #endif // wxUSE_PALETTE
@@ -667,17 +697,30 @@ bool wxDIB::Create(const wxImage& image)
     {
         // copy one DIB line
         unsigned char *dst = dstLineStart;
-        for ( int x = 0; x < w; x++ )
+        if ( alpha )
         {
-            // also, the order of RGB is inversed for DIBs
-            *dst++ = src[2];
-            *dst++ = src[1];
-            *dst++ = src[0];
-
-            src += 3;
-
-            if ( alpha )
-                *dst++ = *alpha++;
+            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++;
+                *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;
+            }
+        }
+        else // no alpha channel
+        {
+            for ( int x = 0; x < w; x++ )
+            {
+                // RGB order is reversed.
+                *dst++ = src[2];
+                *dst++ = src[1];
+                *dst++ = src[0];
+                src += 3;
+            }
         }
 
         // pass to the previous line in the image
@@ -732,14 +775,26 @@ wxImage wxDIB::ConvertToImage() const
             dst[1] = *src++;
             dst[0] = *src++;
 
-            dst += 3;
-
             if ( is32bit )
             {
                 if ( alpha )
-                    *alpha++ = *src;
+                {
+                    // wxImage uses non premultiplied alpha so undo
+                    // premultiplication done in Create() above
+                    const unsigned char a = *src;
+                    *alpha++ = a;
+                    if ( a > 0 )
+                    {
+                        dst[0] = (dst[0] * 255 - 127) / a;
+                        dst[1] = (dst[1] * 255 - 127) / a;
+                        dst[2] = (dst[2] * 255 - 127) / a;
+                    }
+                }
+
                 src++;
             }
+
+            dst += 3;
         }
 
         // pass to the previous line in the image
@@ -757,4 +812,3 @@ wxImage wxDIB::ConvertToImage() const
 #endif // wxUSE_IMAGE
 
 #endif // wxUSE_WXDIB
-