DIB: Fix the BI_BITFIELDS compression mode

Michael Kaufmann hallo at michael-kaufmann.ch
Mon Aug 8 09:27:18 CDT 2005


This fixes a bug introduced in 
http://www.winehq.com/hypermail/wine-cvs/2004/11/0013.html . It's only 
visible in applications that use the new bitmap headers (BITMAPV4HEADER, 
BITMAPV5HEADER) together with the BI_BITFIELDS compression mode.

Ultima Online suffers from this bug. Thanks to Mark Wachtler and Kuba 
Tyszko who have reported and tracked down the bug.

Changelog:
  - DIBs: Fix for BI_BITFIELDS: The color masks are at the same position
    in all the bitmap headers that support this flag.
    (BITMAPINFO: The first color mask is in bmiColors[0], that's
     the same position as bV4RedMask in BITMAPV4HEADER)

-------------- next part --------------
Index: dlls/gdi/dib.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/dib.c,v
retrieving revision 1.12
diff -u -r1.12 dib.c
--- dlls/gdi/dib.c	14 Jul 2005 10:15:42 -0000	1.12
+++ dlls/gdi/dib.c	7 Aug 2005 11:26:08 -0000
@@ -42,6 +42,10 @@
     
     - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
     - BITMAPV5HEADER: Introduced in Windows 98 / 2000
+    
+    If biCompression is BI_BITFIELDS, the color masks are at the same position
+    in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
+    the new headers have structure members for the masks.
 
 
   * You should never access the color table using the bmiColors member,
@@ -1118,7 +1122,6 @@
     LONG width, height;
     WORD planes, bpp;
     DWORD compression, sizeImage;
-    const DWORD *colorPtr;
     void *mapBits = NULL;
 
     if (((bitmap_type = DIB_GetBitmapInfo( &bmi->bmiHeader, &width, &height,
@@ -1167,7 +1170,6 @@
 
 
     /* set dsBitfields values */
-    colorPtr = (const DWORD *)((const char *)bmi + (WORD) bmi->bmiHeader.biSize);
     if (usage == DIB_PAL_COLORS || bpp <= 8)
     {
         dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
@@ -1176,15 +1178,15 @@
     {
     case 15:
     case 16:
-        dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? colorPtr[0] : 0x7c00;
-        dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? colorPtr[1] : 0x03e0;
-        dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? colorPtr[2] : 0x001f;
+        dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors       : 0x7c00;
+        dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x03e0;
+        dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x001f;
         break;
     case 24:
     case 32:
-        dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? colorPtr[0] : 0xff0000;
-        dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? colorPtr[1] : 0x00ff00;
-        dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? colorPtr[2] : 0x0000ff;
+        dib->dsBitfields[0] = (compression == BI_BITFIELDS) ? *(const DWORD *)bmi->bmiColors       : 0xff0000;
+        dib->dsBitfields[1] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 1) : 0x00ff00;
+        dib->dsBitfields[2] = (compression == BI_BITFIELDS) ? *((const DWORD *)bmi->bmiColors + 2) : 0x0000ff;
         break;
     }
 
Index: dlls/x11drv/dib.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/dib.c,v
retrieving revision 1.40
diff -u -r1.40 dib.c
--- dlls/x11drv/dib.c	24 Jul 2005 17:10:38 -0000	1.40
+++ dlls/x11drv/dib.c	7 Aug 2005 11:26:19 -0000
@@ -3761,7 +3761,6 @@
     LONG width, height;
     BOOL top_down;
     POINT pt;
-    const void* colorPtr;
 
     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
 			   &descr.infoBpp, &descr.compression ) == -1)
@@ -3817,8 +3816,6 @@
     XSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[GetROP2(physDev->hdc) - 1]);
     wine_tsx11_unlock();
 
-    colorPtr = (const BYTE*) info + (WORD) info->bmiHeader.biSize;
-
     switch (descr.infoBpp)
     {
        case 1:
@@ -3832,17 +3829,17 @@
                break;
        case 15:
        case 16:
-               descr.rMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr    ) : 0x7c00;
-               descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr + 1) : 0x03e0;
-               descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr + 2) : 0x001f;
+               descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors       : 0x7c00;
+               descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x03e0;
+               descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x001f;
                descr.colorMap = 0;
                break;
 
        case 24:
        case 32:
-               descr.rMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr    ) : 0xff0000;
-               descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr + 1) : 0x00ff00;
-               descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)colorPtr + 2) : 0x0000ff;
+               descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors       : 0xff0000;
+               descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x00ff00;
+               descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x0000ff;
                descr.colorMap = 0;
                break;
     }
@@ -3887,7 +3884,6 @@
   BITMAP bitmap;
   LONG height, tmpheight;
   INT result;
-  const void* colorPtr;
 
   descr.physDev = physDev;
 
@@ -3906,8 +3902,6 @@
 
   if (startscan + lines > height) lines = height - startscan;
 
-  colorPtr = (const BYTE*) info + (WORD) info->bmiHeader.biSize;
-
   switch (descr.infoBpp)
   {
        case 1:
@@ -3922,17 +3916,17 @@
                break;
        case 15:
        case 16:
-               descr.rMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr    ) : 0x7c00;
-               descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr + 1) : 0x03e0;
-               descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr + 2) : 0x001f;
+               descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors       : 0x7c00;
+               descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x03e0;
+               descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x001f;
                descr.colorMap = 0;
                break;
 
        case 24:
        case 32:
-               descr.rMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr    ) : 0xff0000;
-               descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr + 1) : 0x00ff00;
-               descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD*)colorPtr + 2) : 0x0000ff;
+               descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors       : 0xff0000;
+               descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x00ff00;
+               descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x0000ff;
                descr.colorMap = 0;
                break;
 
@@ -4040,15 +4034,15 @@
           break;
       case 15:
       case 16:
-          descr.rMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr    ) : 0x7c00;
-          descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr + 1) : 0x03e0;
-          descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr + 2) : 0x001f;
+          descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors       : 0x7c00;
+          descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x03e0;
+          descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x001f;
           break;
       case 24:
       case 32:
-          descr.rMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr    ) : 0xff0000;
-          descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr + 1) : 0x00ff00;
-          descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)colorPtr + 2) : 0x0000ff;
+          descr.rMask = (descr.compression == BI_BITFIELDS) ? *(const DWORD *)info->bmiColors       : 0xff0000;
+          descr.gMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 1) : 0x00ff00;
+          descr.bMask = (descr.compression == BI_BITFIELDS) ? *((const DWORD *)info->bmiColors + 2) : 0x0000ff;
           break;
   }
 
@@ -4094,9 +4088,9 @@
 
   if (descr.compression == BI_BITFIELDS)
   {
-    *(DWORD *) colorPtr      = descr.rMask;
-    *((DWORD *)colorPtr + 1) = descr.gMask;
-    *((DWORD *)colorPtr + 2) = descr.bMask;
+    *(DWORD *)info->bmiColors       = descr.rMask;
+    *((DWORD *)info->bmiColors + 1) = descr.gMask;
+    *((DWORD *)info->bmiColors + 2) = descr.bMask;
   }
   else if (!core_header)
   {


More information about the wine-patches mailing list