Resend: Support legacy bitmap structures

Michael Kaufmann hallo at michael-kaufmann.ch
Sun Oct 24 05:59:14 CDT 2004


This patch is against the current CVS version.

Changelog:
  - Extended support for BITMAPCOREINFO / BITMAPCOREHEADER structures
  - Always calculate the location of the color table
  - CreateCompatibleBitmap: Create a DIB section if necessary
  - Added some tests

-------------- next part --------------
Index: dlls/gdi/bitmap.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/bitmap.c,v
retrieving revision 1.2
diff -u -r1.2 bitmap.c
--- dlls/gdi/bitmap.c	13 Aug 2004 19:48:55 -0000	1.2
+++ dlls/gdi/bitmap.c	23 Oct 2004 19:47:44 -0000
@@ -171,32 +171,83 @@
     HBITMAP hbmpRet = 0;
     DC *dc;
 
-    TRACE("(%p,%d,%d) = \n", hdc, width, height );
-    if (!(dc = DC_GetDCPtr( hdc ))) return 0;
-    if ((width >= 0x10000) || (height >= 0x10000)) {
-	FIXME("got bad width %d or height %d, please look for reason\n",
-	      width, height );
+    TRACE("(%p,%d,%d) = \n", hdc, width, height);
+
+    if ((width >= 0x10000) || (height >= 0x10000))
+    {
+        FIXME("got bad width %d or height %d, please look for reason\n",
+              width, height);
     }
     else
     {
-        INT planes, bpp;
+        if (!(dc = DC_GetDCPtr(hdc))) return 0;
 
-        if (GDIMAGIC( dc->header.wMagic ) != MEMORY_DC_MAGIC)
+        if (GDIMAGIC(dc->header.wMagic) != MEMORY_DC_MAGIC)
         {
-            planes = GetDeviceCaps( hdc, PLANES );
-            bpp = GetDeviceCaps( hdc, BITSPIXEL );
+            hbmpRet = CreateBitmap(width, height,
+                                   GetDeviceCaps(hdc, PLANES),
+                                   GetDeviceCaps(hdc, BITSPIXEL),
+                                   NULL);
         }
-        else  /* memory DC, get the depth of the bitmap */
+        else  /* Memory DC */
         {
-            BITMAPOBJ *bmp = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC );
-            planes = bmp->bitmap.bmPlanes;
-            bpp = bmp->bitmap.bmBitsPixel;
-            GDI_ReleaseObj( dc->hBitmap );
-        }
-        hbmpRet = CreateBitmap( width, height, planes, bpp, NULL );
+            BITMAPOBJ *bmp = GDI_GetObjPtr(dc->hBitmap, BITMAP_MAGIC);
+
+            if (!bmp->dib)
+            {
+                /* A device-dependent bitmap is selected in the DC */
+                hbmpRet = CreateBitmap(width, height,
+                                       bmp->bitmap.bmPlanes,
+                                       bmp->bitmap.bmBitsPixel,
+                                       NULL);
+            }
+            else
+            {
+                /* A DIB section is selected in the DC */
+                BITMAPINFO *bi;
+                void *bits;
+
+                /* Allocate memory for a BITMAPINFOHEADER structure and a
+                   color table. The maximum number of colors in a color table
+                   is 256 which corresponds to a bitmap with depth 8.
+                   Bitmaps with higher depths don't have color tables. */
+                bi = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
+
+                if (bi)
+                {
+                    bi->bmiHeader.biSize          = sizeof(bi->bmiHeader);
+                    bi->bmiHeader.biWidth         = width;
+                    bi->bmiHeader.biHeight        = height;
+                    bi->bmiHeader.biPlanes        = bmp->dib->dsBmih.biPlanes;
+                    bi->bmiHeader.biBitCount      = bmp->dib->dsBmih.biBitCount;
+                    bi->bmiHeader.biCompression   = bmp->dib->dsBmih.biCompression;
+                    bi->bmiHeader.biSizeImage     = 0;
+                    bi->bmiHeader.biXPelsPerMeter = bmp->dib->dsBmih.biXPelsPerMeter;
+                    bi->bmiHeader.biYPelsPerMeter = bmp->dib->dsBmih.biYPelsPerMeter;		
+                    bi->bmiHeader.biClrUsed       = bmp->dib->dsBmih.biClrUsed;
+                    bi->bmiHeader.biClrImportant  = bmp->dib->dsBmih.biClrImportant;
+
+                    if (bi->bmiHeader.biCompression == BI_BITFIELDS)
+                    {
+                        /* Copy the color masks */
+                        CopyMemory(bi->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD));
+                    }
+                    else if (bi->bmiHeader.biBitCount <= 8)
+                    {
+                        /* Copy the color table */
+                        GetDIBColorTable(hdc, 0, 256, bi->bmiColors);
+                    }
+
+                    hbmpRet = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, &bits, NULL, 0);
+                    HeapFree(GetProcessHeap(), 0, bi);
+                }
+            }
+            GDI_ReleaseObj(dc->hBitmap);
+        }    
+        GDI_ReleaseObj(hdc);
     }
+
     TRACE("\t\t%p\n", hbmpRet);
-    GDI_ReleaseObj(hdc);
     return hbmpRet;
 }
 
@@ -618,6 +669,8 @@
  * SetBitmapDimensionEx [GDI32.@]
  *
  * Assigns dimensions to a bitmap.
+ * MSDN says that this function will fail if hbitmap is a handle created by
+ * CreateDIBSection, but that's not true on Windows 2000.
  *
  * RETURNS
  *    Success: TRUE
Index: dlls/gdi/dib.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/dib.c,v
retrieving revision 1.6
diff -u -r1.6 dib.c
--- dlls/gdi/dib.c	18 Oct 2004 19:35:50 -0000	1.6
+++ dlls/gdi/dib.c	23 Oct 2004 19:47:44 -0000
@@ -18,6 +18,44 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+/*
+  Important information:
+  
+  * Current Windows versions support two different DIB structures:
+
+    - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
+    - BITMAPINFO / BITMAPINFOHEADER
+  
+    Most Windows API functions taking a BITMAPINFO* / BITMAPINFOHEADER* also
+    accept the old "core" structures, and so must WINE.
+    You can distinguish them by looking at the first member (bcSize/biSize),
+    or use the internal function DIB_GetBitmapInfo.
+
+    
+  * The palettes are stored in different formats:
+
+    - BITMAPCOREINFO: Array of RGBTRIPLE
+    - BITMAPINFO:     Array of RGBQUAD
+
+    
+  * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
+    
+    - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
+    - BITMAPV5HEADER: Introduced in Windows 98 / 2000
+
+
+  * You should never access the color table using the bmiColors member,
+    because the passed structure may have one of the extended headers
+    mentioned above. Use this to calculate the location:
+    
+    BITMAPINFO* info;
+    void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
+
+    
+  * More information:
+    Search for "Bitmap Structures" in MSDN
+*/
+
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
@@ -31,6 +69,12 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
 
+
+/*
+  Some of the following helper functions are duplicated in
+  dlls/x11drv/dib.c
+*/
+
 /***********************************************************************
  *           DIB_GetDIBWidthBytes
  *
@@ -174,12 +218,27 @@
     {
         HBITMAP hBitmap, hOldBitmap;
         HPALETTE hpal = NULL;
-	HDC hdcMem;
+        HDC hdcMem;
+        LONG height;
+        LONG width;
+        WORD bpp;
+        DWORD compr;
+
+        if (DIB_GetBitmapInfo( (BITMAPINFOHEADER*) info, &width, &height, &bpp, &compr ) == -1)
+        {
+            ERR("Invalid bitmap\n");
+            return 0;
+        }
+
+        if (width < 0)
+        {
+            ERR("Bitmap has a negative width\n");
+            return 0;
+        }
 
         GDI_ReleaseObj( hdc );
 	hdcMem = CreateCompatibleDC( hdc );
-        hBitmap = CreateCompatibleBitmap(hdc, info->bmiHeader.biWidth,
-                                         info->bmiHeader.biHeight);
+        hBitmap = CreateCompatibleBitmap(hdc, width, height);
         hOldBitmap = SelectObject( hdcMem, hBitmap );
         if(wUsage == DIB_PAL_COLORS)
         {
@@ -206,18 +265,17 @@
 	    */
 
             /* copy existing bitmap from destination dc */
-            StretchBlt( hdcMem, xSrc, abs(info->bmiHeader.biHeight) - heightSrc - ySrc,
+            StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
                         widthSrc, heightSrc, hdc, xDst, yDst, widthDst, heightDst,
                         dwRop );
         }
 
-        SetDIBits(hdcMem, hBitmap, 0, info->bmiHeader.biHeight, bits,
-		     info, wUsage);
+        SetDIBits(hdcMem, hBitmap, 0, height, bits, info, wUsage);
 
         /* Origin for DIBitmap may be bottom left (positive biHeight) or top
            left (negative biHeight) */
         StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
-		    hdcMem, xSrc, abs(info->bmiHeader.biHeight) - heightSrc - ySrc,
+		    hdcMem, xSrc, abs(height) - heightSrc - ySrc,
 		    widthSrc, heightSrc, dwRop );
         if(hpal)
             SelectPalette(hdcMem, hpal, FALSE);
@@ -346,8 +404,8 @@
    NB. RGBQUAD and PALETTEENTRY have different orderings of red, green
    and blue - sigh */
 
-static RGBQUAD EGAColors[16] = {
-/* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
+static RGBQUAD EGAColorsQuads[16] = {
+/* rgbBlue, rgbGreen, rgbRed, rgbReserved */
     { 0x00, 0x00, 0x00, 0x00 },
     { 0x00, 0x00, 0x80, 0x00 },
     { 0x00, 0x80, 0x00, 0x00 },
@@ -366,9 +424,28 @@
     { 0xff, 0xff, 0xff, 0x00 }
 };
 
+static RGBTRIPLE EGAColorsTriples[16] = {
+/* rgbBlue, rgbGreen, rgbRed */
+    { 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x80 },
+    { 0x00, 0x80, 0x00 },
+    { 0x00, 0x80, 0x80 },
+    { 0x80, 0x00, 0x00 },
+    { 0x80, 0x00, 0x80 },
+    { 0x80, 0x80, 0x00 },
+    { 0x80, 0x80, 0x80 },
+    { 0xc0, 0xc0, 0xc0 },
+    { 0x00, 0x00, 0xff },
+    { 0x00, 0xff, 0x00 },
+    { 0x00, 0xff, 0xff },
+    { 0xff, 0x00, 0x00 } ,
+    { 0xff, 0x00, 0xff },
+    { 0xff, 0xff, 0x00 },
+    { 0xff, 0xff, 0xff }
+};
 
-static RGBQUAD DefLogPalette[20] = { /* Copy of Default Logical Palette */
-/* rgbBlue, rgbGreen, rgbRed, rgbReserverd */
+static RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
+/* rgbBlue, rgbGreen, rgbRed, rgbReserved */
     { 0x00, 0x00, 0x00, 0x00 },
     { 0x00, 0x00, 0x80, 0x00 },
     { 0x00, 0x80, 0x00, 0x00 },
@@ -391,6 +468,30 @@
     { 0xff, 0xff, 0xff, 0x00 }
 };
 
+static RGBTRIPLE DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
+/* rgbBlue, rgbGreen, rgbRed */
+    { 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x80 },
+    { 0x00, 0x80, 0x00 },
+    { 0x00, 0x80, 0x80 },
+    { 0x80, 0x00, 0x00 },
+    { 0x80, 0x00, 0x80 },
+    { 0x80, 0x80, 0x00 },
+    { 0xc0, 0xc0, 0xc0 },
+    { 0xc0, 0xdc, 0xc0 },
+    { 0xf0, 0xca, 0xa6 },
+    { 0xf0, 0xfb, 0xff },
+    { 0xa4, 0xa0, 0xa0 },
+    { 0x80, 0x80, 0x80 },
+    { 0x00, 0x00, 0xf0 },
+    { 0x00, 0xff, 0x00 },
+    { 0x00, 0xff, 0xff },
+    { 0xff, 0x00, 0x00 },
+    { 0xff, 0x00, 0xff },
+    { 0xff, 0xff, 0x00 },
+    { 0xff, 0xff, 0xff}
+};
+
 
 /******************************************************************************
  * GetDIBits [GDI32.@]
@@ -416,8 +517,26 @@
     BITMAPOBJ * bmp;
     int i;
     HDC memdc;
+    int bitmap_type;
+    BOOL core_header;
+    LONG width;
+    LONG height;
+    WORD bpp;
+    DWORD compr;
+    void* colorPtr;
+    RGBTRIPLE* rgbTriples;
+    RGBQUAD* rgbQuads;
 
     if (!info) return 0;
+
+    bitmap_type = DIB_GetBitmapInfo( (BITMAPINFOHEADER*) info, &width, &height, &bpp, &compr);
+    if (bitmap_type == -1)
+    {
+        ERR("Invalid bitmap format\n");
+        return 0;
+    }
+    core_header = (bitmap_type == 0);
+printf("bpp: %d\n", bpp);
     memdc = CreateCompatibleDC(hdc);
     if (!(dc = DC_GetDCUpdate( hdc )))
     {
@@ -431,30 +550,57 @@
 	return 0;
     }
 
-    /* Transfer color info */
+    colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
+    rgbTriples = (RGBTRIPLE *) colorPtr;
+    rgbQuads = (RGBQUAD *) colorPtr;
 
-    if (info->bmiHeader.biBitCount <= 8 && info->bmiHeader.biBitCount > 0 ) {
+    /* Transfer color info */
 
-	info->bmiHeader.biClrUsed = 0;
+    if (bpp <= 8 && bpp > 0)
+    {
+        if (!core_header) info->bmiHeader.biClrUsed = 0;
 
 	/* If the bitmap object already has a dib section at the
 	   same color depth then get the color map from it */
-	if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == info->bmiHeader.biBitCount) {
+	if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
             if(coloruse == DIB_RGB_COLORS) {
-                HBITMAP oldbm;
-                oldbm = SelectObject(memdc, hbitmap);
-                GetDIBColorTable(memdc, 0, 1 << info->bmiHeader.biBitCount, info->bmiColors);
+                HBITMAP oldbm = SelectObject(memdc, hbitmap);
+                unsigned int colors = 1 << bpp;
+
+                if (core_header)
+                {
+                    /* Convert the color table (RGBQUAD to RGBTRIPLE) */		    
+                    RGBQUAD* buffer = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD));
+
+                    if (buffer)
+                    {
+                        RGBTRIPLE* index = rgbTriples;
+                        GetDIBColorTable(memdc, 0, colors, buffer);
+
+                        for (i=0; i < colors; i++, index++)
+                        {
+                            index->rgbtRed   = buffer[i].rgbRed;
+                            index->rgbtGreen = buffer[i].rgbGreen;
+                            index->rgbtBlue  = buffer[i].rgbBlue;
+                        }
+
+                        HeapFree(GetProcessHeap(), 0, buffer);
+                    }
+                }
+                else
+                {
+                    GetDIBColorTable(memdc, 0, colors, colorPtr);
+                }
                 SelectObject(memdc, oldbm);
             }
             else {
-                WORD *index = (WORD*)info->bmiColors;
-                int i;
+                WORD *index = colorPtr;
                 for(i = 0; i < 1 << info->bmiHeader.biBitCount; i++, index++)
                     *index = i;
             }
-	}
+        }
         else {
-            if(info->bmiHeader.biBitCount >= bmp->bitmap.bmBitsPixel) {
+            if(bpp >= bmp->bitmap.bmBitsPixel) {
                 /* Generate the color map from the selected palette */
                 PALETTEENTRY * palEntry;
                 PALETTEOBJ * palette;
@@ -467,48 +613,93 @@
                 palEntry = palette->logpalette.palPalEntry;
                 for (i = 0; i < (1 << bmp->bitmap.bmBitsPixel); i++, palEntry++) {
                     if (coloruse == DIB_RGB_COLORS) {
-                        info->bmiColors[i].rgbRed      = palEntry->peRed;
-                        info->bmiColors[i].rgbGreen    = palEntry->peGreen;
-                        info->bmiColors[i].rgbBlue     = palEntry->peBlue;
-                        info->bmiColors[i].rgbReserved = 0;
+                        if (core_header)
+                        {
+                            rgbTriples[i].rgbtRed   = palEntry->peRed;
+                            rgbTriples[i].rgbtGreen = palEntry->peGreen;
+                            rgbTriples[i].rgbtBlue  = palEntry->peBlue;
+                        }
+                        else
+                        {
+                            rgbQuads[i].rgbRed      = palEntry->peRed;
+                            rgbQuads[i].rgbGreen    = palEntry->peGreen;
+                            rgbQuads[i].rgbBlue     = palEntry->peBlue;
+                            rgbQuads[i].rgbReserved = 0;
+                        }
                     }
-                    else ((WORD *)info->bmiColors)[i] = (WORD)i;
+                    else ((WORD *)colorPtr)[i] = (WORD)i;
                 }
                 GDI_ReleaseObj( dc->hPalette );
-            } else {
-                switch (info->bmiHeader.biBitCount) {
+            } else {printf("else\n");printf("%d\n", bpp);
+                switch (bpp) {
                 case 1:
-                    info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen =
-                        info->bmiColors[0].rgbBlue = 0;
-                    info->bmiColors[0].rgbReserved = 0;
-                    info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen =
-                        info->bmiColors[1].rgbBlue = 0xff;
-                    info->bmiColors[1].rgbReserved = 0;
+                    if (core_header)
+                    {
+                        rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
+                            rgbTriples[0].rgbtBlue = 0;
+                        rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
+                            rgbTriples[1].rgbtBlue = 0xff;
+                    }
+                    else
+                    {    
+                        rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
+                            rgbQuads[0].rgbBlue = 0;
+                        rgbQuads[0].rgbReserved = 0;
+                        rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
+                            rgbQuads[1].rgbBlue = 0xff;
+                        rgbQuads[1].rgbReserved = 0;
+                    }
                     break;
 
                 case 4:
-                    memcpy(info->bmiColors, EGAColors, sizeof(EGAColors));
+                    if (core_header)
+                        memcpy(colorPtr, EGAColorsTriples, sizeof(EGAColorsTriples));
+                    else
+                        memcpy(colorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
+
                     break;
 
                 case 8:
                     {
-                        INT r, g, b;
-                        RGBQUAD *color;
+                        if (core_header)
+                        {
+                            INT r, g, b;
+                            RGBTRIPLE *color;
 
-                        memcpy(info->bmiColors, DefLogPalette,
-                               10 * sizeof(RGBQUAD));
-                        memcpy(info->bmiColors + 246, DefLogPalette + 10,
-                               10 * sizeof(RGBQUAD));
-                        color = info->bmiColors + 10;
-                        for(r = 0; r <= 5; r++) /* FIXME */
-                            for(g = 0; g <= 5; g++)
-                                for(b = 0; b <= 5; b++) {
-                                    color->rgbRed =   (r * 0xff) / 5;
-                                    color->rgbGreen = (g * 0xff) / 5;
-                                    color->rgbBlue =  (b * 0xff) / 5;
-                                    color->rgbReserved = 0;
-                                    color++;
-                                }
+                            memcpy(rgbTriples, DefLogPaletteTriples,
+                                       10 * sizeof(RGBTRIPLE));
+                            memcpy(rgbTriples + 246, DefLogPaletteTriples + 10,
+                                       10 * sizeof(RGBTRIPLE));
+                            color = rgbTriples + 10;
+                            for(r = 0; r <= 5; r++) /* FIXME */
+                                for(g = 0; g <= 5; g++)
+                                    for(b = 0; b <= 5; b++) {
+                                        color->rgbtRed =   (r * 0xff) / 5;
+                                        color->rgbtGreen = (g * 0xff) / 5;
+                                        color->rgbtBlue =  (b * 0xff) / 5;
+                                        color++;
+                                    }
+                        }
+                        else
+                        {
+                            INT r, g, b;
+                            RGBQUAD *color;
+
+                            memcpy(rgbQuads, DefLogPaletteQuads,
+                                       10 * sizeof(RGBQUAD));
+                            memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
+                                   10 * sizeof(RGBQUAD));
+                            color = rgbQuads + 10;
+                            for(r = 0; r <= 5; r++) /* FIXME */
+                                for(g = 0; g <= 5; g++)
+                                    for(b = 0; b <= 5; b++) {
+                                        color->rgbRed =   (r * 0xff) / 5;
+                                        color->rgbGreen = (g * 0xff) / 5;
+                                        color->rgbBlue =  (b * 0xff) / 5;
+                                        color->rgbReserved = 0;
+                                        color++;
+                                    }
+                        }
                     }
                 }
             }
@@ -518,22 +709,22 @@
     if (bits && lines)
     {
         /* If the bitmap object already have a dib section that contains image data, get the bits from it */
-        if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && info->bmiHeader.biBitCount >= 15)
+        if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && bpp >= 15)
         {
             /*FIXME: Only RGB dibs supported for now */
             unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
-            unsigned int dstwidth = info->bmiHeader.biWidth;
-            int dstwidthb = DIB_GetDIBWidthBytes( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
+            unsigned int dstwidth = width;
+            int dstwidthb = DIB_GetDIBWidthBytes( width, bpp );
             LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
             unsigned int x, y, width, widthb;
 
-            if ((info->bmiHeader.biHeight < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
+            if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
             {
                 dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
                 dstwidthb = -dstwidthb;
             }
 
-            switch( info->bmiHeader.biBitCount ) {
+            switch( bpp ) {
 
 	    case 15:
             case 16: /* 16 bpp dstDIB */
@@ -734,35 +925,41 @@
             }
         }
     }
-    else if( info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
+    else
     {
 	/* fill in struct members */
 
-        if( info->bmiHeader.biBitCount == 0)
-	{
-	    info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
-	    info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
-	    info->bmiHeader.biPlanes = 1;
-	    info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
-	    info->bmiHeader.biSizeImage =
-                             DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
-						   bmp->bitmap.bmHeight,
-						   bmp->bitmap.bmBitsPixel );
-	    info->bmiHeader.biCompression = 0;
-	}
-	else
-	{
-	    info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
-					       info->bmiHeader.biWidth,
-					       info->bmiHeader.biHeight,
-					       info->bmiHeader.biBitCount );
-	}
-	lines = info->bmiHeader.biHeight;
-    }
-
-    TRACE("biSizeImage = %ld, biWidth = %ld, biHeight = %ld\n",
-	  info->bmiHeader.biSizeImage, info->bmiHeader.biWidth,
-	  info->bmiHeader.biHeight);
+        if (bpp == 0)
+        {
+            if (core_header)
+            {
+                BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
+                coreheader->bcWidth = bmp->bitmap.bmWidth;
+                coreheader->bcHeight = bmp->bitmap.bmHeight;
+                coreheader->bcPlanes = 1;
+                coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
+            }
+            else
+            {
+                info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
+                info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
+                info->bmiHeader.biPlanes = 1;
+                info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
+                info->bmiHeader.biSizeImage =
+                                 DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
+                                                       bmp->bitmap.bmHeight,
+                                                       bmp->bitmap.bmBitsPixel );
+                info->bmiHeader.biCompression = 0;
+            }
+            lines = abs(bmp->bitmap.bmHeight);
+        }
+    }
+
+    if (core_header)
+    {
+        TRACE("biSizeImage = %ld, ", info->bmiHeader.biSizeImage);
+    }
+    TRACE("biWidth = %ld, biHeight = %ld\n", width, height);
 
     GDI_ReleaseObj( hdc );
     GDI_ReleaseObj( hbitmap );
@@ -841,15 +1038,33 @@
         if (bmp && bmp->dib && bits32)
         {
             const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
-            INT height = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
-            INT width_bytes = DIB_GetDIBWidthBytes(bi->biWidth, bi->biBitCount);
-            INT size  = (bi->biSizeImage && bi->biCompression != BI_RGB) ?
-                         bi->biSizeImage : width_bytes * height;
+            LONG width, height;
+            WORD bpp;
+            DWORD compr;
+            BOOL core_header;
+            INT width_bytes;
+            INT size;
+            WORD count, sel;
+            int i;
+
+            core_header = (DIB_GetBitmapInfo(bi, &width, &height, &bpp, &compr) == 0);
+
+            height = height >= 0 ? height : -height;
+            width_bytes = DIB_GetDIBWidthBytes(width, bpp);
+            
+            if (core_header)
+            {
+                size = width_bytes * height;
+            }
+            else
+            {
+                size = (bi->biSizeImage && compr != BI_RGB) ?
+                        bi->biSizeImage : width_bytes * height;
+            }
 
             /* calculate number of sel's needed for size with 64K steps */
-            WORD count = (size + 0xffff) / 0x10000;
-            WORD sel = AllocSelectorArray16(count);
-            int i;
+            count = (size + 0xffff) / 0x10000;
+            sel = AllocSelectorArray16(count);
 
             for (i = 0; i < count; i++)
             {
Index: dlls/gdi/tests/bitmap.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/tests/bitmap.c,v
retrieving revision 1.4
diff -u -r1.4 bitmap.c
--- dlls/gdi/tests/bitmap.c	11 Oct 2004 19:54:54 -0000	1.4
+++ dlls/gdi/tests/bitmap.c	23 Oct 2004 19:47:45 -0000
@@ -160,7 +160,11 @@
     HDC hdc, hdcmem, hdcmem2;
     HBITMAP hdib, oldbm, hdib2, oldbm2;
     char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
+    char bcibuf[sizeof(BITMAPCOREINFO) + 256 * sizeof(RGBTRIPLE)];
     BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
+    BITMAPCOREINFO *pbci = (BITMAPCOREINFO *)bcibuf;
+    HBITMAP hcoredib;
+    char coreBits[256];
     BYTE *bits;
     RGBQUAD rgb[256];
     int ret;
@@ -187,6 +191,37 @@
 
     hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
     ok(hdib != NULL, "CreateDIBSection failed\n");
+
+    /* Test if the old BITMAPCOREINFO structure is supported */    
+        
+    pbci->bmciHeader.bcSize = sizeof(BITMAPCOREHEADER);
+    pbci->bmciHeader.bcBitCount = 0;
+
+    ret = GetDIBits(hdc, hdib, 0, 16, NULL, (BITMAPINFO*) pbci, DIB_RGB_COLORS);    
+    ok(ret, "GetDIBits doesn't work with a BITMAPCOREHEADER\n");
+    ok((pbci->bmciHeader.bcWidth == 16) && (pbci->bmciHeader.bcHeight == 16)
+        && (pbci->bmciHeader.bcBitCount == 1) && (pbci->bmciHeader.bcPlanes == 1),
+	"GetDIBits did't fill in the BITMAPCOREHEADER structure properly\n");
+
+    ret = GetDIBits(hdc, hdib, 0, 16, &coreBits, (BITMAPINFO*) pbci, DIB_RGB_COLORS);
+    ok(ret, "GetDIBits doesn't work with a BITMAPCOREHEADER\n");
+    ok((pbci->bmciColors[0].rgbtRed == 0xff) && (pbci->bmciColors[0].rgbtGreen == 0) &&
+       (pbci->bmciColors[0].rgbtBlue == 0) && (pbci->bmciColors[1].rgbtRed == 0) &&
+       (pbci->bmciColors[1].rgbtGreen == 0) && (pbci->bmciColors[1].rgbtBlue == 0xff),
+       "The color table has not been translated to the old BITMAPCOREINFO format\n");
+
+    hcoredib = CreateDIBSection(hdc, (BITMAPINFO*) pbci, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
+    ok(hcoredib != NULL, "CreateDIBSection failed with a BITMAPCOREINFO\n");
+
+    ZeroMemory(pbci->bmciColors, 256 * sizeof(RGBTRIPLE));
+    ret = GetDIBits(hdc, hcoredib, 0, 16, &coreBits, (BITMAPINFO*) pbci, DIB_RGB_COLORS);
+    ok(ret, "GetDIBits doesn't work with a BITMAPCOREHEADER\n");
+    ok((pbci->bmciColors[0].rgbtRed == 0xff) && (pbci->bmciColors[0].rgbtGreen == 0) &&
+       (pbci->bmciColors[0].rgbtBlue == 0) && (pbci->bmciColors[1].rgbtRed == 0) &&
+       (pbci->bmciColors[1].rgbtGreen == 0) && (pbci->bmciColors[1].rgbtBlue == 0xff),
+       "The color table has not been translated to the old BITMAPCOREINFO format\n");    
+
+    DeleteObject(hcoredib);
 
     hdcmem = CreateCompatibleDC(hdc);
     oldbm = SelectObject(hdcmem, hdib);
Index: dlls/x11drv/dib.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/dib.c,v
retrieving revision 1.18
diff -u -r1.18 dib.c
--- dlls/x11drv/dib.c	27 Sep 2004 20:33:58 -0000	1.18
+++ dlls/x11drv/dib.c	23 Oct 2004 19:48:09 -0000
@@ -83,6 +83,12 @@
   RLE_DELTA = 2  /* Delta */
 };
 
+
+/* 
+  Some of the following helper functions are duplicated in
+  dlls/gdi/dib.c
+*/
+
 /***********************************************************************
  *           X11DRV_DIB_GetXImageWidthBytes
  *
@@ -140,13 +146,24 @@
 
 
 /***********************************************************************
+ *           X11DRV_DIB_GetDIBImageBytes
+ *
+ * Return the number of bytes used to hold the image in a DIB bitmap.
+ */
+static int X11DRV_DIB_GetDIBImageBytes( int width, int height, int depth )
+{
+    return X11DRV_DIB_GetDIBWidthBytes( width, depth ) * abs( height );
+}
+
+
+/***********************************************************************
  *           X11DRV_DIB_BitmapInfoSize
  *
  * Return the size of the bitmap info structure including color table.
  */
 int X11DRV_DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse )
 {
-    int colors;
+    unsigned int colors;
 
     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
     {
@@ -187,29 +204,34 @@
 
 
 /***********************************************************************
- *           DIB_GetBitmapInfo
+ *           DIB_GetBitmapInfoEx
  *
  * Get the info from a bitmap header.
  * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
  */
-static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
-                              int *height, WORD *bpp, WORD *compr )
+static int DIB_GetBitmapInfoEx( const BITMAPINFOHEADER *header, LONG *width,
+                                LONG *height, WORD *planes, WORD *bpp,
+                                WORD *compr, DWORD *size )
 {
     if (header->biSize == sizeof(BITMAPCOREHEADER))
     {
         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
         *width  = core->bcWidth;
         *height = core->bcHeight;
+        *planes = core->bcPlanes;
         *bpp    = core->bcBitCount;
         *compr  = 0;
+        *size   = 0;
         return 0;
     }
     if (header->biSize >= sizeof(BITMAPINFOHEADER))
     {
         *width  = header->biWidth;
         *height = header->biHeight;
+        *planes = header->biPlanes;
         *bpp    = header->biBitCount;
         *compr  = header->biCompression;
+        *size   = header->biSizeImage;
         return 1;
     }
     ERR("(%ld): unknown/wrong size for header\n", header->biSize );
@@ -218,6 +240,22 @@
 
 
 /***********************************************************************
+ *           DIB_GetBitmapInfo
+ *
+ * Get the info from a bitmap header.
+ * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
+ */
+static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
+                              LONG *height, WORD *bpp, WORD *compr )
+{
+    WORD planes;
+    DWORD size;
+    
+    return DIB_GetBitmapInfoEx( header, width, height, &planes, bpp, compr, &size);    
+}
+
+
+/***********************************************************************
  *           X11DRV_DIB_GenColorMap
  *
  * Fills the color map of a bitmap palette. Should not be called
@@ -285,24 +323,25 @@
 int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
                                const BITMAPINFO *info, int *nColors )
 {
-    int colors;
+    unsigned int colors;
     BOOL isInfo;
     const void *colorPtr;
     int *colorMapping;
 
-    if ((isInfo = (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))))
+    isInfo = info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER);
+
+    if (isInfo)
     {
-        /* assume BITMAPINFOHEADER */
         colors = info->bmiHeader.biClrUsed;
         if (!colors) colors = 1 << info->bmiHeader.biBitCount;
-        colorPtr = info->bmiColors;
     }
-    else  /* BITMAPCOREHEADER */
+    else
     {
         colors = 1 << ((BITMAPCOREHEADER *)info)->bcBitCount;
-        colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
     }
 
+    colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
+
     if (colors > 256)
     {
         ERR("called with >256 colors!\n");
@@ -333,10 +372,19 @@
                                             const BITMAPINFO *info )
 {
     RGBQUAD *colorTable;
-    int colors, i;
+    unsigned int colors;
+    int i;
+    BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
 
-    colors = info->bmiHeader.biClrUsed;
-    if (!colors) colors = 1 << info->bmiHeader.biBitCount;
+    if (core_info)
+    {
+        colors = 1 << ((BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
+    }
+    else
+    {
+        colors = info->bmiHeader.biClrUsed;
+        if (!colors) colors = 1 << info->bmiHeader.biBitCount;
+    }
 
     if (colors > 256) {
         ERR("called with >256 colors!\n");
@@ -347,14 +395,33 @@
 	return NULL;
 
     if(coloruse == DIB_RGB_COLORS)
-        memcpy(colorTable, info->bmiColors, colors * sizeof(RGBQUAD));
-    else {
+    {
+        if (core_info)
+        {
+           /* Convert RGBTRIPLEs to RGBQUADs */
+           for (i=0; i < colors; i++)
+           {
+               colorTable[i].rgbRed   = ((BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
+               colorTable[i].rgbGreen = ((BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
+               colorTable[i].rgbBlue  = ((BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
+               colorTable[i].rgbReserved = 0;
+           }
+        }
+        else
+        {
+            memcpy(colorTable, (LPBYTE) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
+        }
+    }
+    else
+    {
         HPALETTE hpal = GetCurrentObject(physDev->hdc, OBJ_PAL);
         PALETTEENTRY pal_ents[256];
-        WORD *index;
+        WORD *index = (WORD*) ((LPBYTE) info + (WORD) info->bmiHeader.biSize);
 
         GetPaletteEntries(hpal, 0, 256, pal_ents);
-        for(i = 0, index = (WORD*)info->bmiColors; i < colors; i++, index++) {
+
+        for(i = 0; i < colors; i++, index++)
+        {
             colorTable[i].rgbRed = pal_ents[*index].peRed;
             colorTable[i].rgbGreen = pal_ents[*index].peGreen;
             colorTable[i].rgbBlue = pal_ents[*index].peBlue;
@@ -370,7 +437,7 @@
  */
 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
 {
-    int color;
+    unsigned int color;
 
     if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
         return oldcol;
@@ -3626,15 +3693,16 @@
 				const BITMAPINFO *info, UINT coloruse )
 {
     X11DRV_DIB_IMAGEBITS_DESCR descr;
-    DWORD width;
     INT result;
-    int height;
+    LONG width, height;
     BOOL top_down;
     POINT pt;
+    void* colorPtr;
 
     if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
 			   &descr.infoBpp, &descr.compression ) == -1)
         return 0;
+
     top_down = (height < 0);
     if (top_down) height = -height;
 
@@ -3685,6 +3753,8 @@
     XSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[GetROP2(physDev->hdc) - 1]);
     wine_tsx11_unlock();
 
+    colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
+
     switch (descr.infoBpp)
     {
        case 1:
@@ -3698,17 +3768,17 @@
                break;
        case 15:
        case 16:
-               descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
-               descr.gMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 1) : 0x03e0;
-               descr.bMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 2) : 0x001f;
+               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.colorMap = 0;
                break;
 
        case 24:
        case 32:
-               descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors       : 0xff0000;
-               descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
-               descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
+               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.colorMap = 0;
                break;
     }
@@ -3750,8 +3820,9 @@
 {
   X11DRV_DIB_IMAGEBITS_DESCR descr;
   BITMAPOBJ *bmp;
-  int height, tmpheight;
+  LONG height, tmpheight;
   INT result;
+  void* colorPtr;
 
   descr.physDev = physDev;
 
@@ -3768,6 +3839,8 @@
 
   if (startscan + lines > height) lines = height - startscan;
 
+  colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
+
   switch (descr.infoBpp)
   {
        case 1:
@@ -3786,17 +3859,17 @@
                break;
        case 15:
        case 16:
-               descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
-               descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
-               descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
+               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.colorMap = 0;
                break;
 
        case 24:
        case 32:
-               descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors       : 0xff0000;
-               descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
-               descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
+               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.colorMap = 0;
                break;
 
@@ -3839,21 +3912,35 @@
   PALETTEENTRY palette[256];
   BITMAPOBJ *bmp;
   int height;
+  LONG tempHeight;
+  int bitmap_type;
+  BOOL core_header;
+  void* colorPtr;
 
   GetPaletteEntries( GetCurrentObject( physDev->hdc, OBJ_PAL ), 0, 256, palette );
 
   if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
 
   dib = (X11DRV_DIBSECTION *) bmp->dib;
+  
+  bitmap_type = DIB_GetBitmapInfo( (BITMAPINFOHEADER*) info, &descr.infoWidth, &tempHeight, &descr.infoBpp, &descr.compression);
+  descr.lines = tempHeight;
+  if (bitmap_type == -1)
+  {
+      ERR("Invalid bitmap\n");
+      lines = 0;
+      goto done;
+  }
+  core_header = (bitmap_type == 0);
+  colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
 
   TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
 	lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
-	(int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
-        startscan );
+	(int)descr.infoWidth, descr.lines, startscan);
 
   if( lines > bmp->bitmap.bmHeight ) lines = bmp->bitmap.bmHeight;
 
-  height = info->bmiHeader.biHeight;
+  height = descr.lines;
   if (height < 0) height = -height;
   if( lines > height ) lines = height;
   /* Top-down images have a negative biHeight, the scanlines of theses images
@@ -3862,7 +3949,7 @@
    * (the number of scan lines to copy).
    * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
    */
-  if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
+  if( descr.lines < 0 && lines > 0) lines = -lines;
 
   if( startscan >= bmp->bitmap.bmHeight )
   {
@@ -3870,13 +3957,6 @@
       goto done;
   }
 
-  if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
-                        &descr.infoBpp, &descr.compression ) == -1)
-  {
-      lines = 0;
-      goto done;
-  }
-
   descr.colorMap = NULL;
 
   switch (descr.infoBpp)
@@ -3886,12 +3966,12 @@
       case 8:
           descr.rMask= descr.gMask = descr.bMask = 0;
           if(coloruse == DIB_RGB_COLORS)
-              descr.colorMap = info->bmiColors;
+              descr.colorMap = colorPtr;
           else {
               int num_colors = 1 << descr.infoBpp, i;
               RGBQUAD *rgb;
               COLORREF colref;
-              WORD *index = (WORD*)info->bmiColors;
+              WORD *index = (WORD*)colorPtr;
               descr.colorMap = rgb = HeapAlloc(GetProcessHeap(), 0, num_colors * sizeof(RGBQUAD));
               for(i = 0; i < num_colors; i++, rgb++, index++) {
                   colref = X11DRV_PALETTE_ToLogical(X11DRV_PALETTE_ToPhysical(physDev, PALETTEINDEX(*index)));
@@ -3904,15 +3984,15 @@
           break;
       case 15:
       case 16:
-          descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
-          descr.gMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 1) : 0x03e0;
-          descr.bMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 2) : 0x001f;
+          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;
           break;
       case 24:
       case 32:
-          descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
-          descr.gMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 1) : 0x00ff00;
-          descr.bMask = (descr.compression == BI_BITFIELDS) ?  *((DWORD *)info->bmiColors + 2) : 0x0000ff;
+          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;
           break;
   }
 
@@ -3929,7 +4009,7 @@
   descr.xDest     = 0;
   descr.yDest     = 0;
   descr.xSrc      = 0;
-  descr.sizeImage = info->bmiHeader.biSizeImage;
+  descr.sizeImage = core_header ? 0 : info->bmiHeader.biSizeImage;
 
   if (descr.lines > 0)
   {
@@ -3951,25 +4031,25 @@
   X11DRV_DIB_GetImageBits( &descr );
   X11DRV_DIB_Unlock(bmp, TRUE);
 
-  if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
-      info->bmiHeader.biSizeImage = X11DRV_DIB_GetDIBWidthBytes( info->bmiHeader.biWidth,
-                                                                 info->bmiHeader.biBitCount )
-                                    * abs( info->bmiHeader.biHeight );
+  if(!core_header && info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
+      info->bmiHeader.biSizeImage = X11DRV_DIB_GetDIBImageBytes( descr.infoWidth,
+                                                                 descr.lines,
+                                                                 descr.infoBpp);
 
   if (descr.compression == BI_BITFIELDS)
   {
-    *(DWORD *)info->bmiColors = descr.rMask;
-    *((DWORD *)info->bmiColors+1) = descr.gMask;
-    *((DWORD *)info->bmiColors+2) = descr.bMask;
+    *(DWORD *) colorPtr      = descr.rMask;
+    *((DWORD *)colorPtr + 1) = descr.gMask;
+    *((DWORD *)colorPtr + 2) = descr.bMask;
   }
-  else
+  else if (!core_header)
   {
     /* if RLE or JPEG compression were supported,
      * this line would be invalid. */
     info->bmiHeader.biCompression = 0;
   }
 
-  if(descr.colorMap && descr.colorMap != info->bmiColors)
+  if(descr.colorMap && descr.colorMap != colorPtr)
       HeapFree(GetProcessHeap(), 0, descr.colorMap);
 done:
   GDI_ReleaseObj( hbitmap );
@@ -4014,7 +4094,7 @@
   X11DRV_DIB_IMAGEBITS_DESCR descr;
   int identity[2] = {0,1};
 
-  if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
+  if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, (DWORD*) &descr.lines,
 			 &descr.infoBpp, &descr.compression ) == -1)
     return;
 
@@ -4596,29 +4676,43 @@
   int nColorMap;
   RGBQUAD *colorTable = NULL;
 
-  /* Fill BITMAP32 structure with DIB data */
-  const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
+  /* Fill BITMAP structure with DIB data */
   INT effHeight, totalSize;
   BITMAP bm;
   LPVOID mapBits = NULL;
 
-  TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
-	bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
-	bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
+  int bitmap_type;
+  BOOL core_header;
+  LONG width, height;
+  WORD planes, bpp, compression;
+  DWORD sizeImage;
+  void* colorPtr;
 
-  effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
+  if (((bitmap_type = DIB_GetBitmapInfoEx((BITMAPINFOHEADER*) bmi,
+        &width, &height, &planes, &bpp, &compression, &sizeImage)) == -1))
+  {
+      ERR("Invalid bitmap\n");
+      return 0;
+  }
+  core_header = (bitmap_type == 0);
+  
+  TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, %s\n",
+        width, height, planes, bpp, 
+        sizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
+
+  effHeight = height >= 0 ? height : -height;
   bm.bmType = 0;
-  bm.bmWidth = bi->biWidth;
+  bm.bmWidth = width;
   bm.bmHeight = effHeight;
-  bm.bmWidthBytes = ovr_pitch ? ovr_pitch : X11DRV_DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
-  bm.bmPlanes = bi->biPlanes;
-  bm.bmBitsPixel = bi->biBitCount;
+  bm.bmWidthBytes = ovr_pitch ? ovr_pitch : X11DRV_DIB_GetDIBWidthBytes(bm.bmWidth, bpp);
+  bm.bmPlanes = planes;
+  bm.bmBitsPixel = bpp;
   bm.bmBits = NULL;
 
-  /* Get storage location for DIB bits.  Only use biSizeImage if it's valid and
+  /* Get storage location for DIB bits.  Only use sizeImage if it's valid and
      we're dealing with a compressed bitmap.  Otherwise, use width * height. */
-  if (bi->biSizeImage && (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8))
-      totalSize = bi->biSizeImage;
+  if (sizeImage && (compression == BI_RLE4 || compression == BI_RLE8))
+      totalSize = sizeImage;
   else
       totalSize = bm.bmWidthBytes * effHeight;
 
@@ -4650,6 +4744,7 @@
   if (bm.bmBits && bm.bmBitsPixel <= 8) {
       colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? physDev : NULL,
                                            usage, bm.bmBitsPixel, bmi, &nColorMap );
+   
       colorTable = X11DRV_DIB_BuildColorTable( physDev, usage, bm.bmBitsPixel, bmi );
   }
   /* Allocate Memory for DIB and fill structure */
@@ -4658,28 +4753,47 @@
   if (dib)
     {
       dib->dibSection.dsBm = bm;
-      dib->dibSection.dsBmih = *bi;
+
+      if (core_header)
+      {
+          /* Convert the BITMAPCOREHEADER to a BITMAPINFOHEADER.
+             The structure is already filled with zeros */
+          dib->dibSection.dsBmih.biSize = sizeof(BITMAPINFOHEADER);
+          dib->dibSection.dsBmih.biWidth = width;
+          dib->dibSection.dsBmih.biHeight = height;
+          dib->dibSection.dsBmih.biPlanes = planes;
+          dib->dibSection.dsBmih.biBitCount = bpp;
+          dib->dibSection.dsBmih.biCompression = compression;	  
+      }
+      else
+      {
+          /* Truncate extended bitmap headers (BITMAPV4HEADER etc.) */
+          dib->dibSection.dsBmih = *((BITMAPINFOHEADER*) bmi);
+          dib->dibSection.dsBmih.biSize = sizeof(BITMAPINFOHEADER);
+      }
+
       dib->dibSection.dsBmih.biSizeImage = totalSize;
+      colorPtr = (LPBYTE) bmi + (WORD) bmi->bmiHeader.biSize;
 
       /* Set dsBitfields values */
-       if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
+       if ( usage == DIB_PAL_COLORS || bpp <= 8)
        {
            dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
        }
-       else switch( bi->biBitCount )
+       else switch( bpp )
        {
            case 15:
            case 16:
-               dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
-               dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
-               dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
+               dib->dibSection.dsBitfields[0] = (compression == BI_BITFIELDS) ? *(DWORD *) colorPtr      : 0x7c00;
+               dib->dibSection.dsBitfields[1] = (compression == BI_BITFIELDS) ? *((DWORD *)colorPtr + 1) : 0x03e0;
+               dib->dibSection.dsBitfields[2] = (compression == BI_BITFIELDS) ? *((DWORD *)colorPtr + 2) : 0x001f;
                break;
 
            case 24:
            case 32:
-               dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors       : 0xff0000;
-               dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x00ff00;
-               dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x0000ff;
+               dib->dibSection.dsBitfields[0] = (compression == BI_BITFIELDS) ? *(DWORD *) colorPtr      : 0xff0000;
+               dib->dibSection.dsBitfields[1] = (compression == BI_BITFIELDS) ? *((DWORD *)colorPtr + 1) : 0x00ff00;
+               dib->dibSection.dsBitfields[2] = (compression == BI_BITFIELDS) ? *((DWORD *)colorPtr + 2) : 0x0000ff;
                break;
        }
       dib->dibSection.dshSection = section;
@@ -4694,8 +4808,8 @@
   /* Create Device Dependent Bitmap and add DIB pointer */
   if (dib)
     {
-      int depth = (bi->biBitCount == 1) ? 1 : GetDeviceCaps(physDev->hdc, BITSPIXEL);
-      res = CreateBitmap(bi->biWidth, effHeight, 1, depth, NULL);
+      int depth = (bpp == 1) ? 1 : GetDeviceCaps(physDev->hdc, BITSPIXEL);
+      res = CreateBitmap(width, effHeight, 1, depth, NULL);
 
       if (res)
 	{



More information about the wine-patches mailing list