2011/2/8 Jack Edmonds <jack(a)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