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