[5/5] gdiplus: Add some tests for GdipBitmapLockBits/GdipBitmapUnlockBits.

Vincent Povirk madewokherd at gmail.com
Wed Jul 11 09:15:25 CDT 2012


Shouldn't your second LockBits in this loop always use
PixelFormat24bppRGB and ImageLockModeRead? As it is, if the
LockBits/UnlockBits is writing but not reading, you won't be able to
tell.

Also, you might want to try flags == 0 in some pixel format other than
24bppRGB. As I understand it, all modes without
ImageLockModeUserInputBuf are treated as read+write regardless of
flags when the bitmap is locked in its native format, as an
optimization. You may simply be running into that optimization.

On Wed, Jul 11, 2012 at 2:49 AM, Dmitry Timoshkov <dmitry at baikal.ru> wrote:
> With additional tests for flags set to ImageLockModeUserInputBuf only.
> ---
>  dlls/gdiplus/tests/image.c | 184 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 184 insertions(+)
>
> diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c
> index 29182aa..6ce100d 100644
> --- a/dlls/gdiplus/tests/image.c
> +++ b/dlls/gdiplus/tests/image.c
> @@ -3342,6 +3342,189 @@ todo_wine
>      GdipDisposeImage(image);
>  }
>
> +static void test_bitmapbits(void)
> +{
> +
> +    static const BYTE pixels_24[24] = {0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
> +                                       0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0};
> +    static const BYTE pixels_24_00[24] = {0,0,0, 0,0,0, 0,0,0, 0,0,0,
> +                                          0,0,0, 0,0,0, 0,0,0, 0,0,0};
> +    static const BYTE pixels_24_77[32] = {0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,0x77,0x77,0x77,0x77,
> +                                          0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,0x77,0x77,0x77,0x77};
> +    static const BYTE pixels_24_88[32] = {0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,0x88,0x88,0x88,0x88,
> +                                          0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,0x88,0x88,0x88,0x88};
> +#if 0 /* FIXME: these tests crash gdiplus in Wine */
> +    static const BYTE pixels_8[8] = {0x01,0,0x01,0,0x01,0,0x01,0};
> +    static const BYTE pixels_8_00[8] = {0,0,0,0,0,0,0,0};
> +    static const BYTE pixels_8_77[32] = {0x01,0,0x01,0,0x77,0x77,0x77,0x77,
> +                                         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
> +                                         0x01,0,0x01,0,0x77,0x77,0x77,0x77,
> +                                         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77};
> +    static const BYTE pixels_8_88[32] = {0x01,0,0x01,0,0x88,0x88,0x88,0x88,
> +                                         0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,
> +                                         0x01,0,0x01,0,0x88,0x88,0x88,0x88,
> +                                         0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88};
> +    static const BYTE pixels_a7[32] = {0xa7,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
> +                                       0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
> +                                       0xa7,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
> +                                       0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77};
> +    static const BYTE pixels_1[8] = {0xa0,0,0,0,0xa0,0,0,0};
> +#endif
> +    static const BYTE pixels_77[32] = {0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
> +                                       0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
> +                                       0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
> +                                       0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77};
> +    static const BYTE pixels_88[32] = {0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,
> +                                       0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,
> +                                       0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,
> +                                       0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88};
> +    static const struct test_data
> +    {
> +        PixelFormat format;
> +        ImageLockMode mode;
> +        UINT width, height, stride, size;
> +        const BYTE *pixels;
> +        const BYTE *pixels_unlocked;
> +    } td[] =
> +    {
> +        { PixelFormat24bppRGB, 0xfff0, 4, 2, 12, 24, pixels_24, pixels_24_00 },
> +        { PixelFormat24bppRGB, 0, 4, 2, 12, 24, pixels_24, pixels_24_00 },
> +
> +        { PixelFormat24bppRGB, ImageLockModeRead, 4, 2, 12, 24, pixels_24, pixels_24_00 },
> +        { PixelFormat24bppRGB, ImageLockModeWrite, 4, 2, 12, 24, pixels_24, pixels_24_00 },
> +        { PixelFormat24bppRGB, ImageLockModeRead|ImageLockModeWrite, 4, 2, 12, 24, pixels_24, pixels_24_00 },
> +        { PixelFormat24bppRGB, ImageLockModeRead|ImageLockModeUserInputBuf, 4, 2, 16, 32, pixels_24_77, pixels_24_88 },
> +        { PixelFormat24bppRGB, ImageLockModeWrite|ImageLockModeUserInputBuf, 4, 2, 16, 32, pixels_77, pixels_88 },
> +        { PixelFormat24bppRGB, ImageLockModeUserInputBuf, 4, 2, 16, 32, pixels_77, pixels_88 },
> +#if 0 /* FIXME: these tests crash gdiplus in Wine */
> +        { PixelFormat8bppIndexed, ImageLockModeRead, 4, 2, 4, 8, pixels_8, pixels_8 },
> +        { PixelFormat8bppIndexed, ImageLockModeWrite, 4, 2, 4, 8, pixels_8, pixels_8 },
> +        { PixelFormat8bppIndexed, ImageLockModeRead|ImageLockModeWrite, 4, 2, 4, 8, pixels_8, pixels_8_00 },
> +        { PixelFormat8bppIndexed, ImageLockModeRead|ImageLockModeUserInputBuf, 4, 2, 16, 32, pixels_8_77, pixels_8_88 },
> +        { PixelFormat8bppIndexed, ImageLockModeWrite|ImageLockModeUserInputBuf, 4, 2, 16, 32, pixels_77, pixels_88 },
> +        { PixelFormat8bppIndexed, ImageLockModeUserInputBuf, 4, 2, 16, 32, pixels_77, pixels_88 },
> +
> +        { PixelFormat1bppIndexed, ImageLockModeRead, 4, 2, 4, 8, pixels_1, pixels_1 },
> +        { PixelFormat1bppIndexed, ImageLockModeWrite, 4, 2, 4, 8, pixels_1, pixels_1 },
> +        { PixelFormat1bppIndexed, ImageLockModeRead|ImageLockModeWrite, 4, 2, 4, 8, pixels_1, pixels_1 },
> +        { PixelFormat1bppIndexed, ImageLockModeRead|ImageLockModeUserInputBuf, 4, 2, 16, 32, pixels_a7, pixels_a7 },
> +#endif
> +    };
> +    BYTE buf[32];
> +    GpStatus status;
> +    GpBitmap *bitmap;
> +    UINT i;
> +    BitmapData data;
> +    struct
> +    {
> +        ColorPalette pal;
> +        ARGB entries[1];
> +    } palette;
> +
> +    for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
> +    {
> +        BYTE pixels[sizeof(pixels_24)];
> +        memcpy(pixels, pixels_24, sizeof(pixels_24));
> +        status = GdipCreateBitmapFromScan0(4, 2, 12, PixelFormat24bppRGB, pixels, &bitmap);
> +        expect(Ok, status);
> +
> +        /* associate known palette with pixel data */
> +        palette.pal.Flags = PaletteFlagsGrayScale;
> +        palette.pal.Count = 2;
> +        palette.pal.Entries[0] = 0;
> +        palette.pal.Entries[1] = 0xffffffff;
> +        status = GdipSetImagePalette((GpImage *)bitmap, &palette.pal);
> +        expect(Ok, status);
> +
> +        memset(&data, 0xfe, sizeof(data));
> +        if (td[i].mode & ImageLockModeUserInputBuf)
> +        {
> +            memset(buf, 0x77, sizeof(buf));
> +            data.Scan0 = buf;
> +            data.Stride = 16;
> +        }
> +        status = GdipBitmapLockBits(bitmap, NULL, td[i].mode, td[i].format, &data);
> +        ok(status == Ok || broken(status == InvalidParameter) /* XP */, "%u: GdipBitmapLockBits error %d\n", i, status);
> +        if (status != Ok)
> +        {
> +            GdipDisposeImage((GpImage *)bitmap);
> +            continue;
> +        }
> +        ok(td[i].width == data.Width, "%u: expected %d, got %d\n", i, td[i].width, data.Width);
> +        ok(td[i].height == data.Height, "%u: expected %d, got %d\n", i, td[i].height, data.Height);
> +        ok(td[i].stride == data.Stride, "%u: expected %d, got %d\n", i, td[i].stride, data.Stride);
> +        ok(td[i].format == data.PixelFormat, "%u: expected %d, got %d\n", i, td[i].format, data.PixelFormat);
> +        ok(td[i].size == data.Height * data.Stride, "%u: expected %d, got %d\n", i, td[i].size, data.Height * data.Stride);
> +        if (td[i].mode & ImageLockModeUserInputBuf)
> +            ok(data.Scan0 == buf, "%u: got wrong buffer\n", i);
> +        if (td[i].size == data.Height * data.Stride)
> +        {
> +            int match = memcmp(data.Scan0, td[i].pixels, td[i].size) == 0;
> +            if ((td[i].mode & (ImageLockModeRead|ImageLockModeWrite|ImageLockModeUserInputBuf)) == ImageLockModeWrite && td[i].format != PixelFormat24bppRGB)
> +                ok(!match, "%u: data shouldn't match\n", i);
> +            else
> +            {
> +                /* copying to user buffer is very buggy even in win7 */
> +                ok(match || broken(!match && (td[i].mode & ImageLockModeUserInputBuf)),
> +                   "%u: data should match\n", i);
> +                if (!match)
> +                {
> +                    UINT j;
> +                    BYTE *bits = data.Scan0;
> +                    printf("%u: data mismatch for format %#x:", i, td[i].format);
> +                    for (j = 0; j < td[i].size; j++)
> +                        printf(" %02x", bits[j]);
> +                    printf("\n");
> +                }
> +            }
> +
> +            memset(data.Scan0, 0, td[i].size);
> +        }
> +
> +        status = GdipBitmapUnlockBits(bitmap, &data);
> +        ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
> +
> +        memset(&data, 0xfe, sizeof(data));
> +        if (td[i].mode & ImageLockModeUserInputBuf)
> +        {
> +            memset(buf, 0x88, sizeof(buf));
> +            data.Scan0 = buf;
> +            data.Stride = 16;
> +        }
> +        status = GdipBitmapLockBits(bitmap, NULL, td[i].mode, td[i].format, &data);
> +        ok(status == Ok, "%u: GdipBitmapLockBits error %d\n", i, status);
> +        ok(td[i].width == data.Width, "%u: expected %d, got %d\n", i, td[i].width, data.Width);
> +        ok(td[i].height == data.Height, "%u: expected %d, got %d\n", i, td[i].height, data.Height);
> +        ok(td[i].stride == data.Stride, "%u: expected %d, got %d\n", i, td[i].stride, data.Stride);
> +        ok(td[i].format == data.PixelFormat, "%u: expected %d, got %d\n", i, td[i].format, data.PixelFormat);
> +        ok(td[i].size == data.Height * data.Stride, "%u: expected %d, got %d\n", i, td[i].size, data.Height * data.Stride);
> +        if (td[i].mode & ImageLockModeUserInputBuf)
> +            ok(data.Scan0 == buf, "%u: got wrong buffer\n", i);
> +        /* copying indexed data without associated palette from BitmapData leads
> +           to funny effects, that's a design flaw with lock/unlock pixel data */
> +        if (td[i].size == data.Height * data.Stride && !(td[i].format & PixelFormatIndexed))
> +        {
> +            int match = memcmp(data.Scan0, td[i].pixels_unlocked, td[i].size) == 0;
> +            ok(match, "%u: data should match\n", i);
> +            if (!match)
> +            {
> +                UINT j;
> +                BYTE *bits = data.Scan0;
> +                printf("%u: data mismatch for format %#x:", i, td[i].format);
> +                for (j = 0; j < td[i].size; j++)
> +                    printf(" %02x", bits[j]);
> +                printf("\n");
> +            }
> +        }
> +
> +        status = GdipBitmapUnlockBits(bitmap, &data);
> +        ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
> +
> +        status = GdipDisposeImage((GpImage *)bitmap);
> +        expect(Ok, status);
> +    }
> +}
> +
>  START_TEST(image)
>  {
>      struct GdiplusStartupInput gdiplusStartupInput;
> @@ -3354,6 +3537,7 @@ START_TEST(image)
>
>      GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
>
> +    test_bitmapbits();
>      test_tiff_palette();
>      test_GdipGetAllPropertyItems();
>      test_tiff_properties();
> --
> 1.7.11.1
>
>
>



More information about the wine-devel mailing list