2011/2/8 Jack Edmonds <jack@jack-desktop.>
Fixes bug 25698 and addresses one of the test cases in bug 24278 (possibly resolves bug 24278 but more testing is required to be sure).

dib.c: Fills BITMAPINFOHEADER with correct width and height when bits == NULL and copying from a top-to-bottom bitmap.
For top-to-bottom bitmaps, reverses the source pointer rather than the destination pointer.
Ignoring the case when both source and destination are top-to-bottom bitmaps and treating this as if the destination is only a top-to-bottom bitmap.
---
���dlls/gdi32/dib.c ��� ��� ��� ��� ���| ���113 ++++++++++++++++++++++++---------------------
���dlls/gdi32/tests/bitmap.c | ���112 ++++++++++++++++++++++++++++++++++++++++++++
���2 files changed, 173 insertions(+), 52 deletions(-)

diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c
index 5067e49..bf7a525 100644
--- a/dlls/gdi32/dib.c
+++ b/dlls/gdi32/dib.c
@@ -636,54 +636,6 @@ INT WINAPI GetDIBits(

��� ��� switch (bpp)
��� ��� {
- ��� ���case 0: ���/* query bitmap info only */
- ��� ��� ��� ���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.biSizeImage =
- ��� ��� ��� ��� ��� ��� ��� ���DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
- ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ���bmp->bitmap.bmHeight,
- ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ���bmp->bitmap.bmBitsPixel );
- ��� ��� ��� ��� ��� ���if (bmp->dib)
- ��� ��� ��� ��� ��� ���{
- ��� ��� ��� ��� ��� ��� ��� ���info->bmiHeader.biBitCount = bmp->dib->dsBm.bmBitsPixel;
- ��� ��� ��� ��� ��� ��� ��� ���switch (bmp->dib->dsBm.bmBitsPixel)
- ��� ��� ��� ��� ��� ��� ��� ���{
- ��� ��� ��� ��� ��� ��� ��� ���case 16:
- ��� ��� ��� ��� ��� ��� ��� ���case 32:
- ��� ��� ��� ��� ��� ��� ��� ��� ��� ���info->bmiHeader.biCompression = BI_BITFIELDS;
- ��� ��� ��� ��� ��� ��� ��� ��� ��� ���break;
- ��� ��� ��� ��� ��� ��� ��� ���default:
- ��� ��� ��� ��� ��� ��� ��� ��� ��� ���info->bmiHeader.biCompression = BI_RGB;
- ��� ��� ��� ��� ��� ��� ��� ��� ��� ���break;
- ��� ��� ��� ��� ��� ��� ��� ���}
- ��� ��� ��� ��� ��� ���}
- ��� ��� ��� ��� ��� ���else
- ��� ��� ��� ��� ��� ���{
- ��� ��� ��� ��� ��� ��� ��� ���info->bmiHeader.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
- ��� ��� ��� ��� ��� ��� ��� ���info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
- ��� ��� ��� ��� ��� ���}
- ��� ��� ��� ��� ��� ���info->bmiHeader.biXPelsPerMeter = 0;
- ��� ��� ��� ��� ��� ���info->bmiHeader.biYPelsPerMeter = 0;
- ��� ��� ��� ��� ��� ���info->bmiHeader.biClrUsed = 0;
- ��� ��� ��� ��� ��� ���info->bmiHeader.biClrImportant = 0;
-
- ��� ��� ��� ��� ��� ���/* Windows 2000 doesn't touch the additional struct members if
- ��� ��� ��� ��� ��� ��� ��� it's a BITMAPV4HEADER or a BITMAPV5HEADER */
- ��� ��� ��� ���}
- ��� ��� ��� ���lines = abs(bmp->bitmap.bmHeight);
- ��� ��� ��� ���goto done;
-
��� ��� case 1:
��� ��� case 4:
��� ��� case 8:
@@ -877,10 +829,10 @@ INT WINAPI GetDIBits(
��� ��� ��� ��� ��� ��� LPBYTE dbits = bits, sbits = (LPBYTE) bmp->dib->dsBm.bmBits + (startscan * srcwidthb);
��� ��� ��� ��� ��� ��� unsigned int x, y, width, widthb;

- ��� ��� ��� ��� ��� ���if ((height < 0) ^ (bmp->dib->dsBmih.biHeight < 0))
+ ��� ��� ��� ��� ��� ���if (bmp->dib->dsBmih.biHeight < 0)
��� ��� ��� ��� ��� ��� {
- ��� ��� ��� ��� ��� ��� ��� ���dbits = (LPBYTE)bits + (dstwidthb * (lines-1));
- ��� ��� ��� ��� ��� ��� ��� ���dstwidthb = -dstwidthb;
+ ��� ��� ��� ��� ��� ��� ��� ���sbits += (srcwidthb * (abs(bmp->dib->dsBmih.biHeight) - startscan - 1));
+ ��� ��� ��� ��� ��� ��� ��� ���srcwidthb = -srcwidthb;
��� ��� ��� ��� ��� ��� }

��� ��� ��� ��� ��� ��� switch( bpp ) {
@@ -1086,7 +1038,64 @@ INT WINAPI GetDIBits(
��� ��� ��� ��� ��� ��� }
��� ��� ��� ��� }
��� ��� }
- ��� ���else lines = abs(height);
+ ��� ���else /* query bitmap info only */
+ ��� ���{
+ ��� ��� ��� ���if (core_header)
+ ��� ��� ��� ���{
+ ��� ��� ��� ��� ��� ���BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
+ ��� ��� ��� ��� ��� ���if (bmp->dib)
+ ��� ��� ��� ��� ��� ���{
+ ��� ��� ��� ��� ��� ��� ��� ���coreheader->bcWidth = bmp->dib->dsBmih.biWidth;
+ ��� ��� ��� ��� ��� ��� ��� ���coreheader->bcHeight = bmp->dib->dsBmih.biHeight;
+ ��� ��� ��� ��� ��� ���}
+ ��� ��� ��� ��� ��� ���else
+ ��� ��� ��� ��� ��� ���{
+ ��� ��� ��� ��� ��� ��� ��� ���coreheader->bcWidth = bmp->bitmap.bmWidth;
+ ��� ��� ��� ��� ��� ��� ��� ���coreheader->bcHeight = bmp->bitmap.bmHeight;
+ ��� ��� ��� ��� ��� ���}
+ ��� ��� ��� ��� ��� ���coreheader->bcPlanes = 1;
+ ��� ��� ��� ��� ��� ���coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
+ ��� ��� ��� ���}
+ ��� ��� ��� ���else
+ ��� ��� ��� ���{
+ ��� ��� ��� ��� ��� ���if (bmp->dib)
+ ��� ��� ��� ��� ��� ���{
+ ��� ��� ��� ��� ��� ��� ��� ���info->bmiHeader.biHeight = bmp->dib->dsBmih.biHeight;
+ ��� ��� ��� ��� ��� ��� ��� ���info->bmiHeader.biWidth = bmp->dib->dsBmih.biWidth;
+ ��� ��� ��� ��� ��� ��� ��� ���info->bmiHeader.biBitCount = bmp->dib->dsBm.bmBitsPixel;
+ ��� ��� ��� ��� ��� ��� ��� ���switch (bmp->dib->dsBm.bmBitsPixel)
+ ��� ��� ��� ��� ��� ��� ��� ���{
+ ��� ��� ��� ��� ��� ��� ��� ���case 16:
+ ��� ��� ��� ��� ��� ��� ��� ���case 32:
+ ��� ��� ��� ��� ��� ��� ��� ��� ��� ���info->bmiHeader.biCompression = BI_BITFIELDS;
+ ��� ��� ��� ��� ��� ��� ��� ��� ��� ���break;
+ ��� ��� ��� ��� ��� ��� ��� ���default:
+ ��� ��� ��� ��� ��� ��� ��� ��� ��� ���info->bmiHeader.biCompression = BI_RGB;
+ ��� ��� ��� ��� ��� ��� ��� ��� ��� ���break;
+ ��� ��� ��� ��� ��� ��� ��� ���}
+ ��� ��� ��� ��� ��� ���}
+ ��� ��� ��� ��� ��� ���else
+ ��� ��� ��� ��� ��� ���{
+ ��� ��� ��� ��� ��� ��� ��� ���info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
+ ��� ��� ��� ��� ��� ��� ��� ���info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
+ ��� ��� ��� ��� ��� ��� ��� ���info->bmiHeader.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
+ ��� ��� ��� ��� ��� ��� ��� ���info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
+ ��� ��� ��� ��� ��� ���}
+ ��� ��� ��� ��� ��� ���info->bmiHeader.biPlanes = 1;
+ ��� ��� ��� ��� ��� ���info->bmiHeader.biSizeImage =
+ ��� ��� ��� ��� ��� ��� ��� ���DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
+ ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ���bmp->bitmap.bmHeight,
+ ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ��� ���bmp->bitmap.bmBitsPixel );
+ ��� ��� ��� ��� ��� ���info->bmiHeader.biXPelsPerMeter = 0;
+ ��� ��� ��� ��� ��� ���info->bmiHeader.biYPelsPerMeter = 0;
+ ��� ��� ��� ��� ��� ���info->bmiHeader.biClrUsed = 0;
+ ��� ��� ��� ��� ��� ���info->bmiHeader.biClrImportant = 0;
+
+ ��� ��� ��� ��� ��� ���/* Windows 2000 doesn't touch the additional struct members if
+ ��� ��� ��� ��� ��� ��� ��� it's a BITMAPV4HEADER or a BITMAPV5HEADER */
+ ��� ��� ��� ���}
+ ��� ��� ��� ���lines = abs(bmp->bitmap.bmHeight);
+ ��� ���}

��� ��� /* The knowledge base article Q81498 ("DIBs and Their Uses") states that
��� ��� ��� ���if bits == NULL and bpp != 0, only biSizeImage and the color table are
diff --git a/dlls/gdi32/tests/bitmap.c b/dlls/gdi32/tests/bitmap.c
index d0d7a9c..a76d437 100644
--- a/dlls/gdi32/tests/bitmap.c
+++ b/dlls/gdi32/tests/bitmap.c
@@ -3050,6 +3050,116 @@ static void test_32bit_bitmap_blt(void)
��� ��� DeleteDC(hdcScreen);
���}

+static void test_GetDIBits_info_query(void)
+{
+ ��� ���BITMAPINFO bi;
+ ��� ���HBITMAP bmp;
+ ��� ���HDC hdc;
+ ��� ���int *picture;
+
+ ��� ���hdc = GetDC(NULL);
+
+ ��� ���bi.bmiHeader.biSize=sizeof(bi.bmiHeader);
+ ��� ���bi.bmiHeader.biWidth=2;
+ ��� ���bi.bmiHeader.biHeight=2;
+ ��� ���bi.bmiHeader.biPlanes=1;
+ ��� ���bi.bmiHeader.biBitCount=32;
+ ��� ���bi.bmiHeader.biCompression=BI_RGB;
+ ��� ���bmp = CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, (void**)&picture, NULL, 0);
+ ��� ���/*Clear the structure to make sure that we really are testing that the structure is being written to.*/
+ ��� ���memset(&bi, 0, sizeof(bi));
+ ��� ���/*Test with a BITMAPINFOHEADER.*/
+ ��� ���bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ ��� ���GetDIBits(hdc, bmp, 0, 0, NULL, &bi, DIB_RGB_COLORS);
+ ��� ���ok(bi.bmiHeader.biHeight == 2, "Height should be 2.");
+ ��� ���ok(bi.bmiHeader.biWidth == 2, "Width should be 2.");
+ ��� ���/*Clear the structure to make sure that we really are testing that the structure is being written to.*/
+ ��� ���memset(&bi, 0, sizeof(bi));
+ ��� ���/*Now test with a BITMAPCOREHEADER.*/
+ ��� ���bi.bmiHeader.biSize=sizeof(BITMAPCOREHEADER);
+ ��� ���GetDIBits(hdc, bmp, 0, 0, NULL, &bi, DIB_RGB_COLORS);
+ ��� ���ok(((BITMAPCOREHEADER*)&bi)->bcHeight == 2, "Height should be 2.");
+ ��� ���ok(((BITMAPCOREHEADER*)&bi)->bcWidth == 2, "Width should be 2.");
+ ��� ���/*Clean up.*/
+ ��� ���DeleteObject(bmp);
+
+ ��� ���/*Test top to bottom bitmap.*/
+ ��� ���bi.bmiHeader.biSize=sizeof(bi.bmiHeader);
+ ��� ���bi.bmiHeader.biWidth=2;
+ ��� ���bi.bmiHeader.biHeight=-2;
+ ��� ���bi.bmiHeader.biPlanes=1;
+ ��� ���bi.bmiHeader.biBitCount=32;
+ ��� ���bi.bmiHeader.biCompression=BI_RGB;
+ ��� ���bmp = CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, (void**)&picture, NULL, 0);
+ ��� ���/*Clear the structure to make sure that we really are testing that the structure is being written to.*/
+ ��� ���memset(&bi, 0, sizeof(bi));
+ ��� ���/*Test with a BITMAPINFOHEADER.*/
+ ��� ���bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
+ ��� ���GetDIBits(hdc, bmp, 0, 0, NULL, &bi, DIB_RGB_COLORS);
+ ��� ���ok(bi.bmiHeader.biHeight == -2, "Height should be -2.");
+ ��� ���ok(bi.bmiHeader.biWidth == 2, "Width should be 2.");
+ ��� ���/*Clear the structure to make sure that we really are testing that the structure is being written to.*/
+ ��� ���memset(&bi, 0, sizeof(bi));
+ ��� ���/*Now test with a BITMAPCOREHEADER.*/
+ ��� ���bi.bmiHeader.biSize=sizeof(BITMAPCOREHEADER);
+ ��� ���GetDIBits(hdc, bmp, 0, 0, NULL, &bi, DIB_RGB_COLORS);
+ ��� ���ok(((BITMAPCOREHEADER*)&bi)->bcHeight == (WORD)-2, "Height should be -2.");
+ ��� ���ok(((BITMAPCOREHEADER*)&bi)->bcWidth == (WORD)2, "Width should be 2.");
+ ��� ���/*Clean up.*/
+ ��� ���DeleteObject(bmp);
+}
+
+static void test_GetDIBits_single_pixel_destination(void)
+{
+ ��� ���BITMAPINFO bi;
+ ��� ���HBITMAP bmptb, bmpbt;
+ ��� ���HDC hdc;
+ ��� ���int pixelOut;
+ ��� ���int *picture;
+ ��� ���bi.bmiHeader.biSize=sizeof(bi.bmiHeader);
+ ��� ���bi.bmiHeader.biWidth=2;
+ ��� ���bi.bmiHeader.biHeight=2;
+ ��� ���bi.bmiHeader.biPlanes=1;
+ ��� ���bi.bmiHeader.biBitCount=32;
+ ��� ���bi.bmiHeader.biCompression=BI_RGB;
+
+ ��� ���/*Get the device context for the screen.*/
+ ��� ���hdc=GetDC(NULL);
+
+ ��� ���/*Create the bottom to top image (image's bottom scan line is at the top in memory).*/
+ ��� ���bmpbt=CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, (void**)&picture, NULL, 0);
+ ��� ���/*Now that we have a pointer to the pixels, we write to them.*/
+ ��� ���picture[0]=1;
+ ��� ���picture[1]=2;
+ ��� ���picture[2]=3;
+ ��� ���picture[3]=4;
+ ��� ���/*Create the top to bottom image (images' bottom scan line is at the bottom in memory).*/
+ ��� ���bi.bmiHeader.biHeight=-2; /*We specify that we want a top to bottom image by specifying a negative height.*/
+ ��� ���bmptb=CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, (void**)&picture, NULL, 0);
+ ��� ���/*Write to this top to bottom bitmap.*/
+ ��� ���picture[0]=1;
+ ��� ���picture[1]=2;
+ ��� ���picture[2]=3;
+ ��� ��� ��� picture[3]=4;
+
+ ��� ���bi.bmiHeader.biWidth=1;
+
+ ��� ���bi.bmiHeader.biHeight=2;
+ ��� ���GetDIBits(hdc, bmpbt, 0, 1, &pixelOut, &bi, DIB_RGB_COLORS);
+ ��� ���ok(pixelOut==1, "Bottom-up -> bottom-up should have first scanline.");
+ ��� ���GetDIBits(hdc, bmptb, 0, 1, &pixelOut, &bi, DIB_RGB_COLORS);
+ ��� ���ok(pixelOut==3, "Top-down -> bottom-up should have last scanline.");
+
+ ��� ���bi.bmiHeader.biHeight=-2;
+ ��� ���GetDIBits(hdc, bmpbt, 0, 1, &pixelOut, &bi, DIB_RGB_COLORS);
+ ��� ���ok(pixelOut==1, "Bottom-up -> top-down should have first scanline.");
+ ��� ���GetDIBits(hdc, bmptb, 0, 1, &pixelOut, &bi, DIB_RGB_COLORS);
+ ��� ���ok(pixelOut==3, "Top-down -> top-down should have last scanline.");
+
+ ��� ���DeleteObject(bmpbt);
+ ��� ���DeleteObject(bmptb);
+}
+
���START_TEST(bitmap)
���{
��� ��� HMODULE hdll;
@@ -3080,4 +3190,6 @@ START_TEST(bitmap)
��� ��� test_bitmapinfoheadersize();
��� ��� test_get16dibits();
��� ��� test_clipping();
+ ��� ���test_GetDIBits_single_pixel_destination();
+ ��� ���test_GetDIBits_info_query();
���}
--
1.7.1




Hi Jack,

You forgot trailing \n in the ok() calls.

--
Nicolas Le Cam