RESEND: CreateDIBitmap: Don't create monochrome bitmaps

Huw D M Davies h.davies1 at physics.ox.ac.uk
Mon Sep 6 11:14:43 CDT 2004


On Sun, Sep 05, 2004 at 05:45:39PM +0200, Michael Kaufmann wrote:
> This patch fixes a bug in CreateDIBitmap and changes all WINE code that 
> is relying on this bug. According to MSDN, CreateDIBitmap should create 
> a bitmap that has the same depth as the reference DC. It should not 
> return monochrome bitmaps, even if the DIB is black & white.

This looks almost right, except that CreateDIBitmap should return a
monochrome bitmap if the dc is monochrome - eg a memory dc with a
monochrome bitmap selected into it.  You can't use
GetDeviceCaps(hdc, BITSPIXEL) in this case since it returns the depth
of the dc that the memory dc was created from.

Attached is an amended patch that fixes this, and also adds a test for
CreateDIBitmap to exercise this behaviour - of course what it doesn't
do is to test the code in Wine that used to call CreateDIBitmap.

Huw.
-- 
Huw Davies
huw at codeweavers.com
Index: dlls/gdi/dib.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/dib.c,v
retrieving revision 1.3
diff -u -r1.3 dib.c
--- dlls/gdi/dib.c	12 Aug 2004 20:02:39 -0000	1.3
+++ dlls/gdi/dib.c	6 Sep 2004 16:01:53 -0000
@@ -773,95 +773,40 @@
 
 /***********************************************************************
  *           CreateDIBitmap    (GDI32.@)
+ *
+ * Creates a DDB (device dependent bitmap) from a DIB.
+ * The DDB will have the same color depth as the reference DC.
  */
 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
                             DWORD init, LPCVOID bits, const BITMAPINFO *data,
                             UINT coloruse )
 {
     HBITMAP handle;
-    BOOL fColor;
     DWORD width;
     int height;
     WORD bpp;
     WORD compr;
     DC *dc;
+    INT depth;
 
     if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
     if (height < 0) height = -height;
 
-    /* Check if we should create a monochrome or color bitmap. */
-    /* We create a monochrome bitmap only if it has exactly 2  */
-    /* colors, which are black followed by white, nothing else.  */
-    /* In all other cases, we create a color bitmap.           */
-
-    if (bpp != 1) fColor = TRUE;
-    else if ((coloruse != DIB_RGB_COLORS) || !data) fColor = FALSE;
-    else
+    if (GetObjectType(hdc) == OBJ_MEMDC)
     {
-        if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
-        {
-            RGBQUAD *rgb = data->bmiColors;
-            DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
-
-	    /* Check if the first color of the colormap is black */
-	    if ((col == RGB(0,0,0)))
-            {
-                rgb++;
-                col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
-		/* If the second color is white, create a monochrome bitmap */
-                fColor =  (col != RGB(0xff,0xff,0xff));
-            }
-	    /* Note : If the first color of the colormap is white
-	       followed by black, we have to create a color bitmap.
-	       If we don't the white will be displayed in black later on!*/
-            else fColor = TRUE;
-        }
-        else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
-        {
-            RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
-            DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
-            if ((col == RGB(0,0,0)))
-            {
-                rgb++;
-                col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
-                fColor = (col != RGB(0xff,0xff,0xff));
-            }
-            else fColor = TRUE;
-        }
-        else if (data->bmiHeader.biSize == sizeof(BITMAPV4HEADER))
-        { /* FIXME: correct ? */
-            RGBQUAD *rgb = data->bmiColors;
-            DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
+        BITMAP bm;
+        HBITMAP hbm;
 
-	    /* Check if the first color of the colormap is black */
-	    if ((col == RGB(0,0,0)))
-            {
-                rgb++;
-                col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
-		/* If the second color is white, create a monochrome bitmap */
-                fColor =  (col != RGB(0xff,0xff,0xff));
-            }
-	    /* Note : If the first color of the colormap is white
-	       followed by black, we have to create a color bitmap.
-	       If we don't the white will be displayed in black later on!*/
-            else fColor = TRUE;
-        }
-        else
-        {
-            ERR("(%ld): wrong/unknown size for data\n",
-                     data->bmiHeader.biSize );
-            return 0;
-        }
+        hbm = GetCurrentObject(hdc, OBJ_BITMAP);
+        GetObjectW(hbm, sizeof(bm), &bm);
+        depth = bm.bmBitsPixel;
     }
-
-    /* Now create the bitmap */
+    else
+        depth = GetDeviceCaps(hdc, BITSPIXEL);
 
     if (!(dc = DC_GetDCPtr( hdc ))) return 0;
 
-    if (fColor)
-        handle = CreateBitmap( width, height, GetDeviceCaps( hdc, PLANES ),
-                               GetDeviceCaps( hdc, BITSPIXEL ), NULL );
-    else handle = CreateBitmap( width, height, 1, 1, NULL );
+    handle = CreateBitmap( width, height, 1, depth, NULL );
 
     if (handle)
     {
Index: dlls/gdi/enhmetafile.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/enhmetafile.c,v
retrieving revision 1.2
diff -u -r1.2 enhmetafile.c
--- dlls/gdi/enhmetafile.c	31 Aug 2004 00:02:03 -0000	1.2
+++ dlls/gdi/enhmetafile.c	6 Sep 2004 16:01:53 -0000
@@ -196,6 +196,55 @@
    return NULL;
 }
 
+/***********************************************************************
+ *          is_dib_monochrome
+ *
+ * Returns whether a DIB can be converted to a monochrome DDB.
+ *
+ * A DIB can be converted if its color table contains only black and
+ * white. Black must be the first color in the color table.
+ *
+ * Note : If the first color in the color table is white followed by
+ *        black, we can't convert it to a monochrome DDB with
+ *        SetDIBits, because black and white would be inverted.
+ */
+static BOOL is_dib_monochrome( const BITMAPINFO* info )
+{
+    if (info->bmiHeader.biBitCount != 1) return FALSE;
+
+    if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+    {
+        RGBTRIPLE *rgb = ((BITMAPCOREINFO *) info)->bmciColors;
+    
+        /* Check if the first color is black */
+        if ((rgb->rgbtRed == 0) && (rgb->rgbtGreen == 0) && (rgb->rgbtBlue == 0))
+        {
+            rgb++;
+
+            /* Check if the second color is white */
+            return ((rgb->rgbtRed == 0xff) && (rgb->rgbtGreen == 0xff)
+                 && (rgb->rgbtBlue == 0xff));
+        }
+        else return FALSE;
+    }
+    else  /* assume BITMAPINFOHEADER */
+    {
+        RGBQUAD *rgb = info->bmiColors;
+
+        /* Check if the first color is black */
+        if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) &&
+            (rgb->rgbBlue == 0) && (rgb->rgbReserved == 0))
+        {
+            rgb++;
+
+            /* Check if the second color is white */
+            return ((rgb->rgbRed == 0xff) && (rgb->rgbGreen == 0xff)
+                 && (rgb->rgbBlue == 0xff) && (rgb->rgbReserved == 0));
+        }
+        else return FALSE;
+    }
+}
+
 /****************************************************************************
  *          EMF_Create_HENHMETAFILE
  */
@@ -1619,11 +1668,30 @@
 
     case EMR_CREATEMONOBRUSH:
     {
-	PEMRCREATEMONOBRUSH pCreateMonoBrush = (PEMRCREATEMONOBRUSH)mr;
-	BITMAPINFO *pbi = (BITMAPINFO *)((BYTE *)mr + pCreateMonoBrush->offBmi);
-	HBITMAP hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
-		(BYTE *)mr + pCreateMonoBrush->offBits, pbi, pCreateMonoBrush->iUsage);
+        PEMRCREATEMONOBRUSH pCreateMonoBrush = (PEMRCREATEMONOBRUSH)mr;
+        BITMAPINFO *pbi = (BITMAPINFO *)((BYTE *)mr + pCreateMonoBrush->offBmi);
+        HBITMAP hBmp;
+
+        /* Need to check if the bitmap is monochrome, and if the
+           two colors are really black and white */
+        if (is_dib_monochrome(pbi))
+        {
+          /* Top-down DIBs have a negative height */
+          DWORD height = pbi->bmiHeader.biHeight;
+          if (height < 0) height = -height;
+
+          hBmp = CreateBitmap(pbi->bmiHeader.biWidth, height, 1, 1, NULL);
+          SetDIBits(hdc, hBmp, 0, pbi->bmiHeader.biHeight,
+              (BYTE *)mr + pCreateMonoBrush->offBits, pbi, pCreateMonoBrush->iUsage);
+        }
+	else
+	{
+	  hBmp = CreateDIBitmap(hdc, (BITMAPINFOHEADER *)pbi, CBM_INIT,
+              (BYTE *)mr + pCreateMonoBrush->offBits, pbi, pCreateMonoBrush->iUsage);
+        }
+
 	(handletable->objectHandle)[pCreateMonoBrush->ihBrush] = CreatePatternBrush(hBmp);
+
 	/* CreatePatternBrush created a copy of the bitmap */
 	DeleteObject(hBmp);
 	break;
@@ -1652,7 +1720,7 @@
             SelectObject(hdcSrc, hBrushOld);
             DeleteObject(hBrush);
 
-            hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
+            hBmp = CreateDIBitmap(hdcSrc, (BITMAPINFOHEADER *)pbi, CBM_INIT,
                                   (BYTE *)mr + pBitBlt->offBitsSrc, pbi, pBitBlt->iUsageSrc);
             hBmpOld = SelectObject(hdcSrc, hBmp);
 
@@ -1694,7 +1762,7 @@
             SelectObject(hdcSrc, hBrushOld);
             DeleteObject(hBrush);
 
-            hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
+            hBmp = CreateDIBitmap(hdcSrc, (BITMAPINFOHEADER *)pbi, CBM_INIT,
                                   (BYTE *)mr + pStretchBlt->offBitsSrc, pbi, pStretchBlt->iUsageSrc);
             hBmpOld = SelectObject(hdcSrc, hBmp);
 
@@ -1728,11 +1796,13 @@
 	DeleteObject(hBrush);
 
 	pbi = (BITMAPINFO *)((BYTE *)mr + pMaskBlt->offBmiMask);
-	hBmpMask = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
-			      (BYTE *)mr + pMaskBlt->offBitsMask, pbi, pMaskBlt->iUsageMask);
+	hBmpMask = CreateBitmap(pbi->bmiHeader.biWidth, pbi->bmiHeader.biHeight,
+	             1, 1, NULL);
+	SetDIBits(hdc, hBmpMask, 0, pbi->bmiHeader.biHeight,
+	  (BYTE *)mr + pMaskBlt->offBitsMask, pbi, pMaskBlt->iUsageMask);
 
 	pbi = (BITMAPINFO *)((BYTE *)mr + pMaskBlt->offBmiSrc);
-	hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
+	hBmp = CreateDIBitmap(hdc, (BITMAPINFOHEADER *)pbi, CBM_INIT,
 			      (BYTE *)mr + pMaskBlt->offBitsSrc, pbi, pMaskBlt->iUsageSrc);
 	hBmpOld = SelectObject(hdcSrc, hBmp);
 	MaskBlt(hdc,
@@ -1778,11 +1848,13 @@
 	DeleteObject(hBrush);
 
 	pbi = (BITMAPINFO *)((BYTE *)mr + pPlgBlt->offBmiMask);
-	hBmpMask = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
-			      (BYTE *)mr + pPlgBlt->offBitsMask, pbi, pPlgBlt->iUsageMask);
+	hBmpMask = CreateBitmap(pbi->bmiHeader.biWidth, pbi->bmiHeader.biHeight,
+	             1, 1, NULL);
+	SetDIBits(hdc, hBmpMask, 0, pbi->bmiHeader.biHeight,
+	  (BYTE *)mr + pPlgBlt->offBitsMask, pbi, pPlgBlt->iUsageMask);
 
 	pbi = (BITMAPINFO *)((BYTE *)mr + pPlgBlt->offBmiSrc);
-	hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
+	hBmp = CreateDIBitmap(hdcSrc, (BITMAPINFOHEADER *)pbi, CBM_INIT,
 			      (BYTE *)mr + pPlgBlt->offBitsSrc, pbi, pPlgBlt->iUsageSrc);
 	hBmpOld = SelectObject(hdcSrc, hBmp);
 	PlgBlt(hdc,
Index: dlls/gdi/tests/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/gdi/tests/Makefile.in,v
retrieving revision 1.3
diff -u -r1.3 Makefile.in
--- dlls/gdi/tests/Makefile.in	1 Sep 2004 17:29:28 -0000	1.3
+++ dlls/gdi/tests/Makefile.in	6 Sep 2004 16:01:53 -0000
@@ -6,6 +6,7 @@
 IMPORTS   = user32 gdi32
 
 CTESTS = \
+	bitmap.c \
 	gdiobj.c \
 	generated.c \
 	metafile.c
Index: windows/cursoricon.c
===================================================================
RCS file: /home/wine/wine/windows/cursoricon.c,v
retrieving revision 1.72
diff -u -r1.72 cursoricon.c
--- windows/cursoricon.c	31 Aug 2004 00:02:02 -0000	1.72
+++ windows/cursoricon.c	6 Sep 2004 16:01:54 -0000
@@ -224,6 +224,56 @@
 }
 
 
+/***********************************************************************
+ *          is_dib_monochrome
+ *
+ * Returns whether a DIB can be converted to a monochrome DDB.
+ *
+ * A DIB can be converted if its color table contains only black and
+ * white. Black must be the first color in the color table.
+ *
+ * Note : If the first color in the color table is white followed by
+ *        black, we can't convert it to a monochrome DDB with
+ *        SetDIBits, because black and white would be inverted.
+ */
+static BOOL is_dib_monochrome( const BITMAPINFO* info )
+{
+    if (info->bmiHeader.biBitCount != 1) return FALSE;
+
+    if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+    {
+        RGBTRIPLE *rgb = ((BITMAPCOREINFO *) info)->bmciColors;
+    
+        /* Check if the first color is black */
+        if ((rgb->rgbtRed == 0) && (rgb->rgbtGreen == 0) && (rgb->rgbtBlue == 0))
+        {
+            rgb++;
+
+            /* Check if the second color is white */
+            return ((rgb->rgbtRed == 0xff) && (rgb->rgbtGreen == 0xff)
+                 && (rgb->rgbtBlue == 0xff));
+        }
+        else return FALSE;
+    }
+    else  /* assume BITMAPINFOHEADER */
+    {
+        RGBQUAD *rgb = info->bmiColors;
+
+        /* Check if the first color is black */
+        if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) &&
+            (rgb->rgbBlue == 0) && (rgb->rgbReserved == 0))
+        {
+            rgb++;
+
+            /* Check if the second color is white */
+            return ((rgb->rgbRed == 0xff) && (rgb->rgbGreen == 0xff)
+                 && (rgb->rgbBlue == 0xff) && (rgb->rgbReserved == 0));
+        }
+        else return FALSE;
+    }
+}
+
+
 /**********************************************************************
  *	    CURSORICON_FindSharedIcon
  */
@@ -657,8 +707,17 @@
                 }
 		if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
 	      }
-	    } else hXorBits = CreateDIBitmap( screen_dc, &pInfo->bmiHeader,
-		CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
+	    } else {
+              if (is_dib_monochrome(bmi)) {
+                  hXorBits = CreateBitmap(width, height, 1, 1, NULL);
+                  SetDIBits(screen_dc, hXorBits, 0, height,
+                     (char*)bmi + size, pInfo, DIB_RGB_COLORS);
+              }
+	      else
+                  hXorBits = CreateDIBitmap(screen_dc, &pInfo->bmiHeader,
+                     CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS); 
+	    }
+
 	    if( hXorBits )
 	    {
 		char* xbits = (char *)bmi + size +
@@ -700,9 +759,13 @@
                 }
 		if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
 	      }
-	    } else hAndBits = CreateDIBitmap( screen_dc, &pInfo->bmiHeader,
-	      CBM_INIT, xbits, pInfo, DIB_RGB_COLORS );
+	    } else {
+              hAndBits = CreateBitmap(width, height, 1, 1, NULL);
+              
+              if (hAndBits) SetDIBits(screen_dc, hAndBits, 0, height,
+                             xbits, pInfo, DIB_RGB_COLORS);
 
+	    }
 		if( !hAndBits ) DeleteObject( hXorBits );
 	    }
 	    HeapFree( GetProcessHeap(), 0, pInfo );
@@ -1170,7 +1233,7 @@
         iinfo.hbmColor = CreateDIBitmap( hdc, &bmi.bmiHeader,
                                          CBM_INIT, lpXORbits,
                                          &bmi, DIB_RGB_COLORS );
-
+        
         hIcon=CreateIconIndirect(&iinfo);
         DeleteObject(iinfo.hbmMask);
         DeleteObject(iinfo.hbmColor);
@@ -1957,7 +2020,7 @@
 /**********************************************************************
  *       BITMAP_Load
  */
-static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
+static HBITMAP BITMAP_Load( HINSTANCE instance, LPCWSTR name, UINT loadflags )
 {
     HBITMAP hbitmap = 0;
     HRSRC hRsrc;
@@ -1975,6 +2038,7 @@
           if (HIWORD(name)) return 0;
           instance = user32_module;
       }
+
       if (!(hRsrc = FindResourceW( instance, name, (LPWSTR)RT_BITMAP ))) return 0;
       if (!(handle = LoadResource( instance, hRsrc ))) return 0;
 
@@ -1985,8 +2049,10 @@
         if (!(ptr = map_fileW( name ))) return 0;
         info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
     }
+
     size = bitmap_info_size(info, DIB_RGB_COLORS);
     if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
+
     if (fix_info) {
       BYTE pix;
 
@@ -1994,9 +2060,11 @@
       pix = *((LPBYTE)info + size);
       DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
       if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
+
       if (screen_dc)
       {
         char *bits = (char *)info + size;
+
 	if (loadflags & LR_CREATEDIBSECTION) {
           DIBSECTION dib;
 	  hbitmap = CreateDIBSection(screen_dc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
@@ -2005,14 +2073,28 @@
                     DIB_RGB_COLORS);
         }
         else {
-          hbitmap = CreateDIBitmap( screen_dc, &fix_info->bmiHeader, CBM_INIT,
-                                      bits, fix_info, DIB_RGB_COLORS );
+            /* If it's possible, create a monochrome bitmap */
+
+            DWORD height = fix_info->bmiHeader.biHeight;
+            if (height < 0) height = -height;
+
+            if (is_dib_monochrome(fix_info))
+              hbitmap = CreateBitmap(fix_info->bmiHeader.biWidth, height, 1, 1, NULL);
+            else
+              hbitmap = CreateBitmap(fix_info->bmiHeader.biWidth, height,
+                          GetDeviceCaps(screen_dc, PLANES),
+                          GetDeviceCaps(screen_dc, BITSPIXEL), NULL);
+
+            SetDIBits(screen_dc, hbitmap, 0, height, bits, info, DIB_RGB_COLORS);
 	}
       }
+
       GlobalUnlock(hFix);
       GlobalFree(hFix);
     }
+
     if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
+
     return hbitmap;
 }
 
--- /dev/null	2003-01-30 10:24:37.000000000 +0000
+++ dlls/gdi/tests/bitmap.c	2004-09-06 16:33:10.000000000 +0100
@@ -0,0 +1,151 @@
+/*
+ * Unit test suite for bitmaps
+ *
+ * Copyright 2004 Huw Davies
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdarg.h>
+#include <assert.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+
+#include "wine/test.h"
+
+
+static void test_createdibitmap(void)
+{
+    HDC hdc, hdcmem;
+    BITMAPINFOHEADER bmih;
+    BITMAP bm;
+    HBITMAP hbm, hbm_colour, hbm_old;
+    INT screen_depth;
+
+    hdc = GetDC(0);
+    screen_depth = GetDeviceCaps(hdc, BITSPIXEL);
+    memset(&bmih, 0, sizeof(bmih));
+    bmih.biSize = sizeof(bmih);
+    bmih.biWidth = 10;
+    bmih.biHeight = 10;
+    bmih.biPlanes = 1;
+    bmih.biBitCount = 32;
+    bmih.biCompression = BI_RGB;
+ 
+    /* First create an un-initalised bitmap.  The depth of the bitmap
+       should match that of the hdc and not that supplied in bmih.
+    */
+
+    /* First try 32 bits */
+    hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
+    ok(hbm != NULL, "CreateDIBitmap failed\n");
+    ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
+
+    ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
+    DeleteObject(hbm);
+    
+    /* Then 16 */
+    bmih.biBitCount = 16;
+    hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
+    ok(hbm != NULL, "CreateDIBitmap failed\n");
+    ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
+
+    ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
+    DeleteObject(hbm);
+
+    /* Then 1 */
+    bmih.biBitCount = 1;
+    hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
+    ok(hbm != NULL, "CreateDIBitmap failed\n");
+    ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
+
+    ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
+    DeleteObject(hbm);
+
+    /* Now with a monochrome dc we expect a monochrome bitmap */
+    hdcmem = CreateCompatibleDC(hdc);
+
+    /* First try 32 bits */
+    bmih.biBitCount = 32;
+    hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
+    ok(hbm != NULL, "CreateDIBitmap failed\n");
+    ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
+
+    ok(bm.bmBitsPixel == 1, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, 1);
+    DeleteObject(hbm);
+    
+    /* Then 16 */
+    bmih.biBitCount = 16;
+    hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
+    ok(hbm != NULL, "CreateDIBitmap failed\n");
+    ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
+
+    ok(bm.bmBitsPixel == 1, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, 1);
+    DeleteObject(hbm);
+    
+    /* Then 1 */
+    bmih.biBitCount = 1;
+    hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
+    ok(hbm != NULL, "CreateDIBitmap failed\n");
+    ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
+
+    ok(bm.bmBitsPixel == 1, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, 1);
+    DeleteObject(hbm);
+
+    /* Now select a polychrome bitmap into the dc and we expect
+       screen_depth bitmaps again */
+    hbm_colour = CreateCompatibleBitmap(hdc, 1, 1);
+    hbm_old = SelectObject(hdcmem, hbm_colour);
+
+    /* First try 32 bits */
+    bmih.biBitCount = 32;
+    hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
+    ok(hbm != NULL, "CreateDIBitmap failed\n");
+    ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
+
+    ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
+    DeleteObject(hbm);
+    
+    /* Then 16 */
+    bmih.biBitCount = 16;
+    hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
+    ok(hbm != NULL, "CreateDIBitmap failed\n");
+    ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
+
+    ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
+    DeleteObject(hbm);
+    
+    /* Then 1 */
+    bmih.biBitCount = 1;
+    hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
+    ok(hbm != NULL, "CreateDIBitmap failed\n");
+    ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
+
+    ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
+    DeleteObject(hbm);
+    
+    SelectObject(hdcmem, hbm_old);
+    DeleteObject(hbm_colour);
+    DeleteDC(hdcmem);
+    ReleaseDC(0, hdc);
+}
+
+START_TEST(bitmap)
+{
+    test_createdibitmap();
+}



More information about the wine-patches mailing list