dibs: keep the dib colour table

Huw D M Davies h.davies1 at physics.ox.ac.uk
Thu Sep 16 08:41:10 CDT 2004


        Huw Davies <huw at codeweavers.com>
        It's important to keep the original dib colour table and not
        just the colour mapping associated with a dib section - it's
        this table that GetDIBColorTable should retrieve.
        Add some GetDIBColorTable tests.
-- 
Huw Davies
huw at codeweavers.com
Index: dlls/x11drv/x11drv.h
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/x11drv.h,v
retrieving revision 1.35
diff -u -r1.35 x11drv.h
--- dlls/x11drv/x11drv.h	9 Sep 2004 00:30:29 -0000	1.35
+++ dlls/x11drv/x11drv.h	16 Sep 2004 13:36:47 -0000
@@ -261,6 +261,10 @@
     int         nColorMap;
     int        *colorMap;
 
+    /* Original dib color table converted to
+       rgb values if usage was DIB_PAL_COLORS */
+    RGBQUAD    *colorTable;
+
     /* Cached XImage */
     XImage     *image;
 
Index: dlls/x11drv/dib.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/dib.c,v
retrieving revision 1.16
diff -u -r1.16 dib.c
--- dlls/x11drv/dib.c	10 Sep 2004 19:35:56 -0000	1.16
+++ dlls/x11drv/dib.c	16 Sep 2004 13:36:48 -0000
@@ -324,7 +324,50 @@
                                    isInfo, colorPtr, 0, colors);
 }
 
+/***********************************************************************
+ *           X11DRV_DIB_BuildColorTable
+ *
+ * Build the dib color table. This either keeps a copy of the bmiColors array if
+ * usage is DIB_RGB_COLORS, or looks up the palette indicies if usage is
+ * DIB_PAL_COLORS.
+ * Should not be called for a >8-bit deep bitmap.
+ */
+static RGBQUAD *X11DRV_DIB_BuildColorTable( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
+                                            const BITMAPINFO *info )
+{
+    RGBQUAD *colorTable;
+    int colors, i;
+
+    colors = info->bmiHeader.biClrUsed;
+    if (!colors) colors = 1 << info->bmiHeader.biBitCount;
 
+    if (colors > 256) {
+        ERR("called with >256 colors!\n");
+        return NULL;
+    }
+
+    if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) )))
+	return NULL;
+
+    if(coloruse == DIB_RGB_COLORS)
+        memcpy(colorTable, info->bmiColors, colors * sizeof(RGBQUAD));
+    else {
+        HPALETTE hpal = GetCurrentObject(physDev->hdc, OBJ_PAL);
+        PALETTEENTRY pal_ents[256];
+        WORD *index;
+
+        GetPaletteEntries(hpal, 0, 256, pal_ents);
+        for(i = 0, index = (WORD*)info->bmiColors; 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;
+            colorTable[i].rgbReserved = 0;
+        }
+    }
+    return colorTable;
+}
+        
+    
 /***********************************************************************
  *           X11DRV_DIB_MapColor
  */
@@ -3972,6 +4015,7 @@
 {
   X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
   X11DRV_DIB_IMAGEBITS_DESCR descr;
+  int identity[2] = {0,1};
 
   if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
 			 &descr.infoBpp, &descr.compression ) == -1)
@@ -3985,6 +4029,9 @@
   descr.bits      = dib->dibSection.dsBm.bmBits;
   descr.depth     = bmp->bitmap.bmBitsPixel;
 
+  if(descr.infoBpp == 1)
+      descr.colorMap = (void*)identity;
+
   switch (descr.infoBpp)
   {
     case 1:
@@ -4550,6 +4597,7 @@
   X11DRV_DIBSECTION *dib = NULL;
   int *colorMap = NULL;
   int nColorMap;
+  RGBQUAD *colorTable = NULL;
 
   /* Fill BITMAP32 structure with DIB data */
   const BITMAPINFOHEADER *bi = &bmi->bmiHeader;
@@ -4602,10 +4650,11 @@
   }
 
   /* Create Color Map */
-  if (bm.bmBits && bm.bmBitsPixel <= 8)
+  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 */
   if (bm.bmBits)
     dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
@@ -4642,6 +4691,7 @@
       dib->status    = DIB_Status_None;
       dib->nColorMap = nColorMap;
       dib->colorMap  = colorMap;
+      dib->colorTable = colorTable;
     }
 
   /* Create Device Dependent Bitmap and add DIB pointer */
@@ -4692,6 +4742,7 @@
 
       if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
       if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
+      if (colorTable) { HeapFree(GetProcessHeap(), 0, colorTable); colorTable = NULL; }
       if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
       if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
       if (res) { DeleteObject(res); res = 0; }
@@ -4740,6 +4791,8 @@
 
   if (dib->colorMap)
     HeapFree(GetProcessHeap(), 0, dib->colorMap);
+  if (dib->colorTable)
+    HeapFree(GetProcessHeap(), 0, dib->colorTable);
 
   DeleteCriticalSection(&(dib->lock));
 }
@@ -4757,7 +4810,7 @@
     if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC ))) return 0;
     dib = (X11DRV_DIBSECTION *) bmp->dib;
 
-    if (dib && dib->colorMap) {
+    if (dib && dib->colorMap && start < dib->nColorMap) {
         UINT end = count + start;
         if (end > dib->nColorMap) end = dib->nColorMap;
         /*
@@ -4766,6 +4819,7 @@
          * of the bitmap object.
          */
         X11DRV_DIB_Lock(bmp, DIB_Status_AppMod, FALSE);
+        memcpy(dib->colorTable + start, colors, (end - start) * sizeof(RGBQUAD));
         X11DRV_DIB_GenColorMap( physDev, dib->colorMap, DIB_RGB_COLORS,
                                 dib->dibSection.dsBm.bmBitsPixel,
                                 TRUE, colors, start, end );
@@ -4789,17 +4843,10 @@
     if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC ))) return 0;
     dib = (X11DRV_DIBSECTION *) bmp->dib;
 
-    if (dib && dib->colorMap) {
-        UINT i, end = count + start;
-        if (end > dib->nColorMap) end = dib->nColorMap;
-        for (i = start; i < end; i++,colors++) {
-            COLORREF col = X11DRV_PALETTE_ToLogical( dib->colorMap[i] );
-            colors->rgbBlue  = GetBValue(col);
-            colors->rgbGreen = GetGValue(col);
-            colors->rgbRed   = GetRValue(col);
-            colors->rgbReserved = 0;
-        }
-        ret = end-start;
+    if (dib && dib->colorTable && start < dib->nColorMap) {
+        if (start + count > dib->nColorMap) count = dib->nColorMap - start;
+        memcpy(colors, dib->colorTable + start, count * sizeof(RGBQUAD));
+        ret = count;
     }
     GDI_ReleaseObj( hBitmap );
     return ret;
Index: dlls/gdi/tests/bitmap.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/tests/bitmap.c,v
retrieving revision 1.1
diff -u -r1.1 bitmap.c
--- dlls/gdi/tests/bitmap.c	13 Sep 2004 19:37:03 -0000	1.1
+++ dlls/gdi/tests/bitmap.c	16 Sep 2004 13:36:48 -0000
@@ -155,7 +155,96 @@
     ReleaseDC(0, hdc);
 }
 
+static void test_dibsections(void)
+{
+    HDC hdc, hdcmem;
+    HBITMAP hdib, oldbm;
+    char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
+    BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
+    BYTE *bits;
+    RGBQUAD rgb[256];
+    int ret;
+    char logpalbuf[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)];
+    LOGPALETTE *plogpal = (LOGPALETTE*)logpalbuf;
+    WORD *index;
+    HPALETTE hpal, oldpal;
+
+    hdc = GetDC(0);
+    memset(pbmi, 0, sizeof(bmibuf));
+    pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader);
+    pbmi->bmiHeader.biHeight = 16;
+    pbmi->bmiHeader.biWidth = 16;
+    pbmi->bmiHeader.biBitCount = 1;
+    pbmi->bmiHeader.biPlanes = 1;
+    pbmi->bmiHeader.biCompression = BI_RGB;
+    pbmi->bmiColors[0].rgbRed = 0xff;
+    pbmi->bmiColors[0].rgbGreen = 0;
+    pbmi->bmiColors[0].rgbBlue = 0;
+    pbmi->bmiColors[1].rgbRed = 0;
+    pbmi->bmiColors[1].rgbGreen = 0;
+    pbmi->bmiColors[1].rgbBlue = 0xff;
+
+    hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
+    ok(hdib != NULL, "CreateDIBSection failed\n");
+
+    hdcmem = CreateCompatibleDC(hdc);
+    oldbm = SelectObject(hdcmem, hdib);
+
+    ret = GetDIBColorTable(hdcmem, 0, 2, rgb);
+    ok(ret == 2, "GetDIBColorTable returned %d\n", ret);
+    ok(!memcmp(rgb, pbmi->bmiColors, 2 * sizeof(RGBQUAD)),
+       "GetDIBColorTable returns table 0: r%02x g%02x b%02x res%02x 1: r%02x g%02x b%02x res%02x\n",
+       rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue, rgb[0].rgbReserved,
+       rgb[1].rgbRed, rgb[1].rgbGreen, rgb[1].rgbBlue, rgb[1].rgbReserved);
+
+    ret = GetDIBColorTable(hdc, 0, 2, rgb);
+    ok(ret == 0, "GetDIBColorTable returned %d\n", ret);
+
+    SelectObject(hdcmem, oldbm);
+    DeleteObject(hdib);
+
+    /* Now create a palette and a palette indexed dib section */
+    memset(plogpal, 0, sizeof(logpalbuf));
+    plogpal->palVersion = 0x300;
+    plogpal->palNumEntries = 2;
+    plogpal->palPalEntry[0].peRed = 0xff;
+    plogpal->palPalEntry[0].peBlue = 0xff;
+    plogpal->palPalEntry[1].peGreen = 0xff;
+
+    index = (WORD*)pbmi->bmiColors;
+    *index++ = 0;
+    *index = 1;
+    hpal = CreatePalette(plogpal);
+    ok(hpal != NULL, "CreatePalette failed\n");
+    oldpal = SelectPalette(hdc, hpal, TRUE);
+    hdib = CreateDIBSection(hdc, pbmi, DIB_PAL_COLORS, (void**)&bits, NULL, 0);
+    ok(hdib != NULL, "CreateDIBSection failed\n");
+
+    /* The colour table has already been grabbed from the dc, so we select back the
+       old palette */
+
+    SelectPalette(hdc, oldpal, TRUE);
+    oldbm = SelectObject(hdcmem, hdib);
+
+    ret = GetDIBColorTable(hdcmem, 0, 2, rgb);
+    ok(ret == 2, "GetDIBColorTable returned %d\n", ret);
+    ok(rgb[0].rgbRed == 0xff && rgb[0].rgbBlue == 0xff && rgb[0].rgbGreen == 0 &&
+       rgb[1].rgbRed == 0    && rgb[1].rgbBlue == 0    && rgb[1].rgbGreen == 0xff,
+       "GetDIBColorTable returns table 0: r%02x g%02x b%02x res%02x 1: r%02x g%02x b%02x res%02x\n",
+       rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue, rgb[0].rgbReserved,
+       rgb[1].rgbRed, rgb[1].rgbGreen, rgb[1].rgbBlue, rgb[1].rgbReserved);
+
+
+    SelectObject(hdcmem, oldbm);
+    DeleteObject(hdib);
+
+
+    DeleteDC(hdcmem);
+    ReleaseDC(0, hdc);
+}    
+
 START_TEST(bitmap)
 {
     test_createdibitmap();
+    test_dibsections();
 }



More information about the wine-patches mailing list