From 5855ff78462f04dc7388560b7ca265274e43e711 Mon Sep 17 00:00:00 2001 From: Akihiro Sagawa Date: Thu, 8 Nov 2018 22:17:01 +0900 Subject: [PATCH] gdiplus/tests: Add more PNG color format tests. Signed-off-by: Akihiro Sagawa Signed-off-by: Vincent Povirk Signed-off-by: Alexandre Julliard --- dlls/gdiplus/tests/image.c | 229 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 188 insertions(+), 41 deletions(-) diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c index 88d195f6c97..ca7874771b0 100644 --- a/dlls/gdiplus/tests/image.c +++ b/dlls/gdiplus/tests/image.c @@ -3217,7 +3217,7 @@ static LONG obj_refcount(void *obj) return IUnknown_Release((IUnknown *)obj); } -static GpImage *load_image(const BYTE *image_data, UINT image_size) +static GpImage *load_image(const BYTE *image_data, UINT image_size, BOOL valid_data, BOOL todo_load) { IStream *stream; HGLOBAL hmem; @@ -3241,8 +3241,12 @@ static GpImage *load_image(const BYTE *image_data, UINT image_size) ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount); status = GdipLoadImageFromStream(stream, &image); - ok(status == Ok || broken(status == InvalidParameter), /* XP */ - "GdipLoadImageFromStream error %d\n", status); + todo_wine_if(todo_load) + if (valid_data) + ok(status == Ok || broken(status == InvalidParameter), /* XP */ + "GdipLoadImageFromStream error %d\n", status); + else + ok(status != Ok, "GdipLoadImageFromStream should fail\n"); if (status != Ok) { IStream_Release(stream); @@ -3313,7 +3317,7 @@ static void test_image_properties(void) for (i = 0; i < ARRAY_SIZE(td); i++) { - image = load_image(td[i].image_data, td[i].image_size); + image = load_image(td[i].image_data, td[i].image_size, TRUE, FALSE); if (!image) { trace("%u: failed to load image data\n", i); @@ -3606,7 +3610,7 @@ static void test_tiff_properties(void) PROPID *prop_id; PropertyItem *prop_item; - image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data)); + image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data), TRUE, FALSE); if (!image) { win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n"); @@ -3718,7 +3722,7 @@ static void test_GdipGetAllPropertyItems(void) PropertyItem *prop_item; const char *item_data; - image = load_image(tiffimage, sizeof(tiffimage)); + image = load_image(tiffimage, sizeof(tiffimage), TRUE, FALSE); ok(image != 0, "Failed to load TIFF image data\n"); if (!image) return; @@ -3866,7 +3870,7 @@ static void test_tiff_palette(void) ARGB *entries = palette.pal.Entries; /* 1bpp TIFF without palette */ - image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data)); + image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data), TRUE, FALSE); if (!image) { win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n"); @@ -4517,7 +4521,7 @@ static void test_gif_properties(void) PropertyItem *prop_item; const char *item_data; - image = load_image(animatedgif, sizeof(animatedgif)); + image = load_image(animatedgif, sizeof(animatedgif), TRUE, FALSE); if (!image) /* XP fails to load this GIF image */ { trace("Failed to load GIF image data\n"); @@ -5101,65 +5105,208 @@ static void test_imageabort(void) static const char png_1x1_data[] = { 0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a, 0x00,0x00,0x00,0x0d,'I','H','D','R',0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,0xde, + 0x00,0x00,0x03,0x00,'P','L','T','E', + 0x01,0x01,0x01,0x02,0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08, + 0x09,0x09,0x09,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x0e,0x0e,0x0e,0x0f,0x0f,0x0f,0x10,0x10,0x10, + 0x11,0x11,0x11,0x12,0x12,0x12,0x13,0x13,0x13,0x14,0x14,0x14,0x15,0x15,0x15,0x16,0x16,0x16,0x17,0x17,0x17,0x18,0x18,0x18, + 0x19,0x19,0x19,0x1a,0x1a,0x1a,0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1d,0x1d,0x1d,0x1e,0x1e,0x1e,0x1f,0x1f,0x1f,0x20,0x20,0x20, + 0x21,0x21,0x21,0x22,0x22,0x22,0x23,0x23,0x23,0x24,0x24,0x24,0x25,0x25,0x25,0x26,0x26,0x26,0x27,0x27,0x27,0x28,0x28,0x28, + 0x29,0x29,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2b,0x2c,0x2c,0x2c,0x2d,0x2d,0x2d,0x2e,0x2e,0x2e,0x2f,0x2f,0x2f,0x30,0x30,0x30, + 0x31,0x31,0x31,0x32,0x32,0x32,0x33,0x33,0x33,0x34,0x34,0x34,0x35,0x35,0x35,0x36,0x36,0x36,0x37,0x37,0x37,0x38,0x38,0x38, + 0x39,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,0x3b,0x3c,0x3c,0x3c,0x3d,0x3d,0x3d,0x3e,0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x40, + 0x41,0x41,0x41,0x42,0x42,0x42,0x43,0x43,0x43,0x44,0x44,0x44,0x45,0x45,0x45,0x46,0x46,0x46,0x47,0x47,0x47,0x48,0x48,0x48, + 0x49,0x49,0x49,0x4a,0x4a,0x4a,0x4b,0x4b,0x4b,0x4c,0x4c,0x4c,0x4d,0x4d,0x4d,0x4e,0x4e,0x4e,0x4f,0x4f,0x4f,0x50,0x50,0x50, + 0x51,0x51,0x51,0x52,0x52,0x52,0x53,0x53,0x53,0x54,0x54,0x54,0x55,0x55,0x55,0x56,0x56,0x56,0x57,0x57,0x57,0x58,0x58,0x58, + 0x59,0x59,0x59,0x5a,0x5a,0x5a,0x5b,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,0x5d,0x5e,0x5e,0x5e,0x5f,0x5f,0x5f,0x60,0x60,0x60, + 0x61,0x61,0x61,0x62,0x62,0x62,0x63,0x63,0x63,0x64,0x64,0x64,0x65,0x65,0x65,0x66,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x68, + 0x69,0x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b,0x6b,0x6c,0x6c,0x6c,0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,0x6f,0x6f,0x6f,0x70,0x70,0x70, + 0x71,0x71,0x71,0x72,0x72,0x72,0x73,0x73,0x73,0x74,0x74,0x74,0x75,0x75,0x75,0x76,0x76,0x76,0x77,0x77,0x77,0x78,0x78,0x78, + 0x79,0x79,0x79,0x7a,0x7a,0x7a,0x7b,0x7b,0x7b,0x7c,0x7c,0x7c,0x7d,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x80,0x80,0x80, + 0x01,0x01,0x01,0x02,0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08, + 0x09,0x09,0x09,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x0e,0x0e,0x0e,0x0f,0x0f,0x0f,0x10,0x10,0x10, + 0x11,0x11,0x11,0x12,0x12,0x12,0x13,0x13,0x13,0x14,0x14,0x14,0x15,0x15,0x15,0x16,0x16,0x16,0x17,0x17,0x17,0x18,0x18,0x18, + 0x19,0x19,0x19,0x1a,0x1a,0x1a,0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1d,0x1d,0x1d,0x1e,0x1e,0x1e,0x1f,0x1f,0x1f,0x20,0x20,0x20, + 0x21,0x21,0x21,0x22,0x22,0x22,0x23,0x23,0x23,0x24,0x24,0x24,0x25,0x25,0x25,0x26,0x26,0x26,0x27,0x27,0x27,0x28,0x28,0x28, + 0x29,0x29,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2b,0x2c,0x2c,0x2c,0x2d,0x2d,0x2d,0x2e,0x2e,0x2e,0x2f,0x2f,0x2f,0x30,0x30,0x30, + 0x31,0x31,0x31,0x32,0x32,0x32,0x33,0x33,0x33,0x34,0x34,0x34,0x35,0x35,0x35,0x36,0x36,0x36,0x37,0x37,0x37,0x38,0x38,0x38, + 0x39,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,0x3b,0x3c,0x3c,0x3c,0x3d,0x3d,0x3d,0x3e,0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x40, + 0x41,0x41,0x41,0x42,0x42,0x42,0x43,0x43,0x43,0x44,0x44,0x44,0x45,0x45,0x45,0x46,0x46,0x46,0x47,0x47,0x47,0x48,0x48,0x48, + 0x49,0x49,0x49,0x4a,0x4a,0x4a,0x4b,0x4b,0x4b,0x4c,0x4c,0x4c,0x4d,0x4d,0x4d,0x4e,0x4e,0x4e,0x4f,0x4f,0x4f,0x50,0x50,0x50, + 0x51,0x51,0x51,0x52,0x52,0x52,0x53,0x53,0x53,0x54,0x54,0x54,0x55,0x55,0x55,0x56,0x56,0x56,0x57,0x57,0x57,0x58,0x58,0x58, + 0x59,0x59,0x59,0x5a,0x5a,0x5a,0x5b,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,0x5d,0x5e,0x5e,0x5e,0x5f,0x5f,0x5f,0x60,0x60,0x60, + 0x61,0x61,0x61,0x62,0x62,0x62,0x63,0x63,0x63,0x64,0x64,0x64,0x65,0x65,0x65,0x66,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x68, + 0x69,0x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b,0x6b,0x6c,0x6c,0x6c,0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,0x6f,0x6f,0x6f,0x70,0x70,0x70, + 0x71,0x71,0x71,0x72,0x72,0x72,0x73,0x73,0x73,0x74,0x74,0x74,0x75,0x75,0x75,0x76,0x76,0x76,0x77,0x77,0x77,0x78,0x78,0x78, + 0x79,0x79,0x79,0x7a,0x7a,0x7a,0x7b,0x7b,0x7b,0x7c,0x7c,0x7c,0x7d,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x80,0x80,0x80, + 0x76,0xb6,0x24,0x31, + 0x00,0x00,0x00,0x02,'t','R','N','S',0xff,0x00,0xe5,0xb7,0x30,0x4a, 0x00,0x00,0x00,0x0c,'I','D','A','T',0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,0xe7, 0x00,0x00,0x00,0x00,'I','E','N','D',0xae,0x42,0x60,0x82 }; +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_RGB 2 +#define PNG_COLOR_TYPE_PALETTE 3 +#define PNG_COLOR_TYPE_GRAY_ALPHA 4 +#define PNG_COLOR_TYPE_RGB_ALPHA 6 + static void test_png_color_formats(void) { static const struct { char bit_depth, color_type; - PixelFormat format; - UINT flags; + struct { + PixelFormat format; + ImageFlags flags; + BOOL todo; + BOOL todo_load; + } t[3]; } td[] = { - /* 2 - PNG_COLOR_TYPE_RGB */ - { 8, 2, PixelFormat24bppRGB, ImageFlagsColorSpaceRGB }, - /* 0 - PNG_COLOR_TYPE_GRAY */ - { 1, 0, PixelFormat1bppIndexed, ImageFlagsColorSpaceRGB }, - { 2, 0, PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }, - { 4, 0, PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }, - { 8, 0, PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }, - { 16, 0, PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }, + /* 0 */ + { 1, PNG_COLOR_TYPE_RGB }, + { 2, PNG_COLOR_TYPE_RGB }, + { 4, PNG_COLOR_TYPE_RGB }, + { 8, PNG_COLOR_TYPE_RGB, + {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE }, + { PixelFormat24bppRGB, ImageFlagsColorSpaceRGB }, + { PixelFormat24bppRGB, ImageFlagsColorSpaceRGB }}}, + /* libpng refuses to load our test image complaining about extra compressed data, + * but libpng is still able to load the image with other combination of type/depth + * making RGB 16 bpp case special for some reason. Therefore todo = TRUE. + */ + { 16, PNG_COLOR_TYPE_RGB, + {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE, TRUE }, + { PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE, TRUE }, + { PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE, TRUE }}}, + + /* 5 */ + { 1, PNG_COLOR_TYPE_GRAY, + {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE }, + { PixelFormat1bppIndexed, ImageFlagsColorSpaceRGB }, + { PixelFormat1bppIndexed, ImageFlagsColorSpaceRGB }}}, + { 2, PNG_COLOR_TYPE_GRAY, + {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB }, + { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }, + { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }}}, + { 4, PNG_COLOR_TYPE_GRAY, + {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB }, + { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }, + { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }}}, + { 8, PNG_COLOR_TYPE_GRAY, + {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE }, + { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }, + { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }}}, + { 16, PNG_COLOR_TYPE_GRAY, + {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB }, + { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }, + { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }}}, + + /* 10 */ + { 1, PNG_COLOR_TYPE_PALETTE, + {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE }, + { PixelFormat1bppIndexed, ImageFlagsColorSpaceRGB }, + { 0, 0 }}}, + { 2, PNG_COLOR_TYPE_PALETTE, + {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB }, + { PixelFormat32bppARGB, ImageFlagsColorSpaceRGB }, + { 0, 0 }}}, + { 4, PNG_COLOR_TYPE_PALETTE, + {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB }, + { PixelFormat4bppIndexed, ImageFlagsColorSpaceRGB, TRUE }, + { 0, 0 }}}, + { 8, PNG_COLOR_TYPE_PALETTE, + {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE }, + { PixelFormat8bppIndexed, ImageFlagsColorSpaceRGB }, + { 0, 0 }}}, + { 16, PNG_COLOR_TYPE_PALETTE }, }; BYTE buf[sizeof(png_1x1_data)]; GpStatus status; GpImage *image; ImageType type; PixelFormat format; - UINT flags; - int i; + ImageFlags flags; + BOOL valid; + int i, j, PLTE_off = 0, tRNS_off = 0; + const ImageFlags color_space_mask = ImageFlagsColorSpaceRGB | ImageFlagsColorSpaceCMYK | ImageFlagsColorSpaceGRAY | ImageFlagsColorSpaceYCBCR | ImageFlagsColorSpaceYCCK; + + memcpy(buf, png_1x1_data, sizeof(png_1x1_data)); + buf[24] = 2; + buf[25] = PNG_COLOR_TYPE_PALETTE; + image = load_image(buf, sizeof(buf), TRUE, FALSE); + status = GdipGetImageFlags(image, &flags); + expect(status, Ok); + ok((flags & color_space_mask) == ImageFlagsColorSpaceRGB || broken(flags == 0x12006) /* before win7 */, + "flags = %#x\n", flags); + if ((flags & color_space_mask) != ImageFlagsColorSpaceRGB) { + GdipDisposeImage(image); + win_skip("broken PNG color space support\n"); + return; + } + GdipDisposeImage(image); - for (i = 0; i < ARRAY_SIZE(td); i++) + for (i = 0; i < sizeof(png_1x1_data) - 4; i++) { - memcpy(buf, png_1x1_data, sizeof(png_1x1_data)); - buf[24] = td[i].bit_depth; - buf[25] = td[i].color_type; + if (!memcmp(buf + i, "tRNS", 4)) + tRNS_off = i; + else if (!memcmp(buf + i, "PLTE", 4)) + PLTE_off = i; + } - image = load_image(buf, sizeof(buf)); - ok(image != NULL, "%d: failed to load image data\n", i); - if (!image) continue; + ok(PLTE_off && tRNS_off, "PLTE offset %d, tRNS offset %d\n", PLTE_off, tRNS_off); + if (!PLTE_off || !tRNS_off) return; - status = GdipGetImageType(image, &type); - ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status); - ok(type == ImageTypeBitmap, "%d: wrong image type %d\n", i, type); + /* In order to test the image data with and without PLTE and tRNS + * chunks, we mask the chunk name with private one (tEST). + */ - status = GdipGetImagePixelFormat(image, &format); - expect(Ok, status); - ok(format == td[i].format || - broken(td[i].bit_depth == 1 && td[i].color_type == 0 && format == PixelFormat32bppARGB), /* XP */ - "%d: expected %#x, got %#x\n", i, td[i].format, format); + for (i = 0; i < ARRAY_SIZE(td); i++) + { + for (j = 0; j < 3; j++) + { + memcpy(buf, png_1x1_data, sizeof(png_1x1_data)); + buf[24] = td[i].bit_depth; + buf[25] = td[i].color_type; + if (j >=1) memcpy(buf + tRNS_off, "tEST", 4); + if (j >=2) memcpy(buf + PLTE_off, "tEST", 4); + + valid = (td[i].t[j].format != 0) || (td[i].t[j].flags != 0); + image = load_image(buf, sizeof(buf), valid, td[i].t[j].todo_load); + todo_wine_if(td[i].t[j].todo_load) + if (valid) + ok(image != NULL, "%d %d: failed to load image data\n", i, j); + else + { + ok(image == NULL, "%d %d: succeed to load image data\n", i, j); + if (image) GdipDisposeImage(image); + image = NULL; + } + if (!image) continue; - status = GdipGetImageFlags(image, &flags); - expect(Ok, status); - ok((flags & td[i].flags) == td[i].flags || - broken(td[i].bit_depth == 1 && td[i].color_type == 0 && (flags & ImageFlagsColorSpaceGRAY)), /* XP */ - "%d: expected %#x, got %#x\n", i, td[i].flags, flags); + status = GdipGetImageType(image, &type); + ok(status == Ok, "%d %d: GdipGetImageType error %d\n", i, j, status); + ok(type == ImageTypeBitmap, "%d %d: wrong image type %d\n", i, j, type); - GdipDisposeImage(image); + status = GdipGetImagePixelFormat(image, &format); + expect(Ok, status); + todo_wine_if(td[i].t[j].todo) + ok(format == td[i].t[j].format, + "%d %d: expected %#x, got %#x\n", i, j, td[i].t[j].format, format); + + status = GdipGetImageFlags(image, &flags); + expect(Ok, status); + ok((flags & color_space_mask) == td[i].t[j].flags, + "%d %d: expected %#x, got %#x\n", i, j, td[i].t[j].flags, flags); + GdipDisposeImage(image); + } } } +#undef PNG_COLOR_TYPE_GRAY +#undef PNG_COLOR_TYPE_RGB +#undef PNG_COLOR_TYPE_PALETTE +#undef PNG_COLOR_TYPE_GRAY_ALPHA +#undef PNG_COLOR_TYPE_RGB_ALPHA static void test_GdipLoadImageFromStream(void) { -- 2.11.4.GIT