gdi32/dib.c: Write true bitmap height into info and copy scanlines in the correct order.

Nicolas Le Cam niko.lecam at gmail.com
Tue Feb 8 03:21:41 CST 2011


2011/2/8 Jack Edmonds <jack at 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20110208/ccb89a78/attachment-0001.htm>


More information about the wine-devel mailing list