[WINDOWSCODECS_WINETEST] Sync with Wine Staging 1.7.55. CORE-10536
[reactos.git] / rostests / winetests / windowscodecs / gifformat.c
index ca7d9d2..4b75d06 100644 (file)
@@ -31,6 +31,8 @@
 #include <wincodec.h>
 #include <wine/test.h>
 
+HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT, IWICImagingFactory**);
+
 static const char gif_global_palette[] = {
 /* LSD */'G','I','F','8','7','a',0x01,0x00,0x01,0x00,0xa1,0x02,0x00,
 /* palette */0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,
@@ -61,28 +63,35 @@ static const char gif_local_palette[] = {
 0x02,0x02,0x44,0x01,0x00,0x3b
 };
 
+/* Generated with ImageMagick:
+ * convert -delay 100 -size 2x2 xc:red \
+ *     -dispose none -page +0+0 -size 2x1 xc:white \
+ *     test.gif
+ */
+static const char gif_frame_sizes[] = {
+    0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x02, 0x00,
+    0x02, 0x00, 0xf1, 0x00, 0x00, 0xff, 0x00, 0x00,
+    0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
+    0x00, 0x21, 0xf9, 0x04, 0x00, 0x64, 0x00, 0x00,
+    0x00, 0x21, 0xff, 0x0b, 0x4e, 0x45, 0x54, 0x53,
+    0x43, 0x41, 0x50, 0x45, 0x32, 0x2e, 0x30, 0x03,
+    0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+    0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x03,
+    0x44, 0x34, 0x05, 0x00, 0x21, 0xf9, 0x04, 0x04,
+    0x64, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+    0x00, 0x02, 0x00, 0x01, 0x00, 0x80, 0xff, 0xff,
+    0xff, 0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x0a,
+    0x00, 0x3b
+};
+
 static IWICImagingFactory *factory;
 
-static const char *debugstr_guid(const GUID *guid)
-{
-    static char buf[50];
-
-    if (!guid) return "(null)";
-    sprintf(buf, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
-            guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
-            guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
-            guid->Data4[5], guid->Data4[6], guid->Data4[7]);
-    return buf;
-}
-
-static IWICBitmapDecoder *create_decoder(const void *image_data, UINT image_size)
+static IStream *create_stream(const void *image_data, UINT image_size)
 {
     HGLOBAL hmem;
     BYTE *data;
     HRESULT hr;
-    IWICBitmapDecoder *decoder = NULL;
     IStream *stream;
-    GUID format;
 
     hmem = GlobalAlloc(0, image_size);
     data = GlobalLock(hmem);
@@ -92,15 +101,30 @@ static IWICBitmapDecoder *create_decoder(const void *image_data, UINT image_size
     hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
     ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
 
+    return stream;
+}
+
+static IWICBitmapDecoder *create_decoder(const void *image_data, UINT image_size)
+{
+    HRESULT hr;
+    IWICBitmapDecoder *decoder;
+    IStream *stream;
+    GUID format;
+    LONG refcount;
+
+    stream = create_stream(image_data, image_size);
+    if (!stream) return NULL;
+
     hr = IWICImagingFactory_CreateDecoderFromStream(factory, stream, NULL, 0, &decoder);
     ok(hr == S_OK, "CreateDecoderFromStream error %#x\n", hr);
 
     hr = IWICBitmapDecoder_GetContainerFormat(decoder, &format);
     ok(hr == S_OK, "GetContainerFormat error %#x\n", hr);
     ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
-       "wrong container format %s\n", debugstr_guid(&format));
+       "wrong container format %s\n", wine_dbgstr_guid(&format));
 
-    IStream_Release(stream);
+    refcount = IStream_Release(stream);
+    ok(refcount > 0, "expected stream refcount > 0\n");
 
     return decoder;
 }
@@ -144,7 +168,7 @@ static void test_global_gif_palette(void)
     hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
     ok(hr == S_OK, "GetPixelFormat error %#x\n", hr);
     ok(IsEqualGUID(&format, &GUID_WICPixelFormat8bppIndexed),
-       "wrong pixel format %s\n", debugstr_guid(&format));
+       "wrong pixel format %s\n", wine_dbgstr_guid(&format));
 
     hr = IWICBitmapFrameDecode_CopyPalette(frame, palette);
     ok(hr == S_OK, "CopyPalette error %#x\n", hr);
@@ -206,7 +230,7 @@ static void test_global_gif_palette_2frames(void)
     hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
     ok(hr == S_OK, "GetPixelFormat error %#x\n", hr);
     ok(IsEqualGUID(&format, &GUID_WICPixelFormat8bppIndexed),
-       "wrong pixel format %s\n", debugstr_guid(&format));
+       "wrong pixel format %s\n", wine_dbgstr_guid(&format));
 
     hr = IWICBitmapFrameDecode_CopyPalette(frame, palette);
     ok(hr == S_OK, "CopyPalette error %#x\n", hr);
@@ -249,7 +273,7 @@ static void test_global_gif_palette_2frames(void)
     hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
     ok(hr == S_OK, "GetPixelFormat error %#x\n", hr);
     ok(IsEqualGUID(&format, &GUID_WICPixelFormat8bppIndexed),
-       "wrong pixel format %s\n", debugstr_guid(&format));
+       "wrong pixel format %s\n", wine_dbgstr_guid(&format));
 
     hr = IWICBitmapFrameDecode_CopyPalette(frame, palette);
     ok(hr == S_OK, "CopyPalette error %#x\n", hr);
@@ -277,8 +301,9 @@ static void test_local_gif_palette(void)
     IWICBitmapDecoder *decoder;
     IWICBitmapFrameDecode *frame;
     IWICPalette *palette;
+    WICBitmapPaletteType type;
     GUID format;
-    UINT count, ret;
+    UINT count, ret, i;
     WICColor color[256];
 
     decoder = create_decoder(gif_local_palette, sizeof(gif_local_palette));
@@ -289,8 +314,27 @@ static void test_local_gif_palette(void)
 
     /* global palette */
     hr = IWICBitmapDecoder_CopyPalette(decoder, palette);
-    ok(hr == WINCODEC_ERR_FRAMEMISSING,
-       "expected WINCODEC_ERR_FRAMEMISSING, got %#x\n", hr);
+    ok(hr == S_OK || broken(hr == WINCODEC_ERR_FRAMEMISSING), "CopyPalette %#x\n", hr);
+    if (hr == S_OK)
+    {
+        type = -1;
+        hr = IWICPalette_GetType(palette, &type);
+        ok(hr == S_OK, "GetType error %#x\n", hr);
+        ok(type == WICBitmapPaletteTypeCustom, "expected WICBitmapPaletteTypeCustom, got %#x\n", type);
+
+        hr = IWICPalette_GetColorCount(palette, &count);
+        ok(hr == S_OK, "GetColorCount error %#x\n", hr);
+        ok(count == 256, "expected 256, got %u\n", count);
+
+        hr = IWICPalette_GetColors(palette, count, color, &ret);
+        ok(hr == S_OK, "GetColors error %#x\n", hr);
+        ok(ret == count, "expected %u, got %u\n", count, ret);
+        ok(color[0] == 0xff000000, "expected 0xff000000, got %#x\n", color[0]);
+        ok(color[1] == 0x00ffffff, "expected 0x00ffffff, got %#x\n", color[1]);
+
+        for (i = 2; i < 256; i++)
+            ok(color[i] == 0xff000000, "expected 0xff000000, got %#x\n", color[i]);
+    }
 
     /* frame palette */
     hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
@@ -299,7 +343,7 @@ static void test_local_gif_palette(void)
     hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
     ok(hr == S_OK, "GetPixelFormat error %#x\n", hr);
     ok(IsEqualGUID(&format, &GUID_WICPixelFormat8bppIndexed),
-       "wrong pixel format %s\n", debugstr_guid(&format));
+       "wrong pixel format %s\n", wine_dbgstr_guid(&format));
 
     hr = IWICBitmapFrameDecode_CopyPalette(frame, palette);
     ok(hr == S_OK, "CopyPalette error %#x\n", hr);
@@ -308,6 +352,11 @@ static void test_local_gif_palette(void)
     ok(hr == S_OK, "GetColorCount error %#x\n", hr);
     ok(count == 4, "expected 4, got %u\n", count);
 
+    type = -1;
+    hr = IWICPalette_GetType(palette, &type);
+    ok(hr == S_OK, "GetType error %#x\n", hr);
+    ok(type == WICBitmapPaletteTypeCustom, "expected WICBitmapPaletteTypeCustom, got %#x\n", type);
+
     hr = IWICPalette_GetColors(palette, count, color, &ret);
     ok(hr == S_OK, "GetColors error %#x\n", hr);
     ok(ret == count, "expected %u, got %u\n", count, ret);
@@ -321,6 +370,132 @@ static void test_local_gif_palette(void)
     IWICBitmapDecoder_Release(decoder);
 }
 
+static void test_gif_frame_sizes(void)
+{
+    static const BYTE frame0[] = {0, 1, 0xfe, 0xfe, 2, 3, 0xfe, 0xfe};
+    static const BYTE frame1[] = {0, 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
+
+    IWICBitmapDecoder *decoder;
+    IWICBitmapFrameDecode *frame;
+    UINT width, height;
+    BYTE buf[8];
+    HRESULT hr;
+
+    decoder = create_decoder(gif_frame_sizes, sizeof(gif_frame_sizes));
+    ok(decoder != 0, "Failed to load GIF image data\n");
+
+    hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
+    ok(hr == S_OK, "GetFrame error %#x\n", hr);
+
+    hr = IWICBitmapFrameDecode_GetSize(frame, &width, &height);
+    ok(hr == S_OK, "GetSize error %x\n", hr);
+    ok(width == 2, "width = %d\n", width);
+    ok(height == 2, "height = %d\n", height);
+
+    memset(buf, 0xfe, sizeof(buf));
+    hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, 4, sizeof(buf), buf);
+    ok(hr == S_OK, "CopyPixels error %x\n", hr);
+    ok(!memcmp(buf, frame0, sizeof(buf)), "buf = %x %x %x %x %x %x %x %x\n",
+            buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
+
+    IWICBitmapFrameDecode_Release(frame);
+
+    hr = IWICBitmapDecoder_GetFrame(decoder, 1, &frame);
+    ok(hr == S_OK, "GetFrame error %#x\n", hr);
+
+    hr = IWICBitmapFrameDecode_GetSize(frame, &width, &height);
+    ok(hr == S_OK, "GetSize error %x\n", hr);
+    ok(width == 2, "width = %d\n", width);
+    ok(height == 1, "height = %d\n", height);
+
+    memset(buf, 0xfe, sizeof(buf));
+    hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, 4, sizeof(buf), buf);
+    ok(hr == S_OK, "CopyPixels error %x\n", hr);
+    ok(!memcmp(buf, frame1, sizeof(buf)), "buf = %x %x %x %x %x %x %x %x\n",
+            buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
+
+    IWICBitmapFrameDecode_Release(frame);
+
+    IWICBitmapDecoder_Release(decoder);
+}
+
+static const char gif_with_trailer_1[] = {
+/* LSD */'G','I','F','8','7','a',0x01,0x00,0x01,0x00,0x80,0x00,0x00,
+/* palette */0xff,0xff,0xff,0xff,0xff,0xff,
+/* IMD */0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,
+/* image data */0x02,0x02,0x44,0x01,0x00,0x3b
+};
+static const char gif_with_trailer_2[] = {
+/* LSD */'G','I','F','8','7','a',0x01,0x00,0x01,0x00,0x00,0x00,0x00,
+/* IMD */0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,
+/* image data */0x02,0x02,0x44,0x3b
+};
+static const char gif_without_trailer_1[] = {
+/* LSD */'G','I','F','8','7','a',0x01,0x00,0x01,0x00,0x80,0x00,0x00,
+/* palette */0xff,0xff,0xff,0xff,0xff,0xff,
+/* IMD */0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,
+/* image data */0x02,0x02,0x44,0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef
+};
+
+static const char gif_without_trailer_2[] = {
+/* LSD */'G','I','F','8','7','a',0x01,0x00,0x01,0x00,0x00,0x00,0x00,
+/* IMD */0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,
+/* image data */0x02,0x02,0x44,0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef
+};
+
+static void test_truncated_gif(void)
+{
+    HRESULT hr;
+    IStream *stream;
+    IWICBitmapDecoder *decoder;
+    GUID format;
+
+    stream = create_stream(gif_with_trailer_1, sizeof(gif_with_trailer_1));
+    if (!stream) return;
+
+    hr = IWICImagingFactory_CreateDecoderFromStream(factory, stream, NULL, 0, &decoder);
+    ok(hr == S_OK, "CreateDecoderFromStream error %#x\n", hr);
+    hr = IWICBitmapDecoder_GetContainerFormat(decoder, &format);
+    ok(hr == S_OK, "GetContainerFormat error %#x\n", hr);
+    ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
+       "wrong container format %s\n", wine_dbgstr_guid(&format));
+    IWICBitmapDecoder_Release(decoder);
+    IStream_Release(stream);
+
+    stream = create_stream(gif_with_trailer_2, sizeof(gif_with_trailer_2));
+    if (!stream) return;
+    hr = IWICImagingFactory_CreateDecoderFromStream(factory, stream, NULL, 0, &decoder);
+    ok(hr == S_OK, "CreateDecoderFromStream error %#x\n", hr);
+    hr = IWICBitmapDecoder_GetContainerFormat(decoder, &format);
+    ok(hr == S_OK, "GetContainerFormat error %#x\n", hr);
+    ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
+       "wrong container format %s\n", wine_dbgstr_guid(&format));
+    IWICBitmapDecoder_Release(decoder);
+    IStream_Release(stream);
+
+    stream = create_stream(gif_without_trailer_1, sizeof(gif_without_trailer_1));
+    if (!stream) return;
+    hr = IWICImagingFactory_CreateDecoderFromStream(factory, stream, NULL, 0, &decoder);
+    ok(hr == S_OK, "CreateDecoderFromStream error %#x\n", hr);
+    hr = IWICBitmapDecoder_GetContainerFormat(decoder, &format);
+    ok(hr == S_OK, "GetContainerFormat error %#x\n", hr);
+    ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
+       "wrong container format %s\n", wine_dbgstr_guid(&format));
+    IWICBitmapDecoder_Release(decoder);
+    IStream_Release(stream);
+
+    stream = create_stream(gif_without_trailer_2, sizeof(gif_without_trailer_2));
+    if (!stream) return;
+    hr = IWICImagingFactory_CreateDecoderFromStream(factory, stream, NULL, 0, &decoder);
+    ok(hr == S_OK, "CreateDecoderFromStream error %#x\n", hr);
+    hr = IWICBitmapDecoder_GetContainerFormat(decoder, &format);
+    ok(hr == S_OK, "GetContainerFormat error %#x\n", hr);
+    ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
+       "wrong container format %s\n", wine_dbgstr_guid(&format));
+    IWICBitmapDecoder_Release(decoder);
+    IStream_Release(stream);
+}
+
 START_TEST(gifformat)
 {
     HRESULT hr;
@@ -334,7 +509,20 @@ START_TEST(gifformat)
     test_global_gif_palette();
     test_global_gif_palette_2frames();
     test_local_gif_palette();
+    test_gif_frame_sizes();
 
     IWICImagingFactory_Release(factory);
     CoUninitialize();
+
+    /* run the same tests with no COM initialization */
+    hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
+    ok(hr == S_OK, "WICCreateImagingFactory_Proxy error %#x\n", hr);
+
+    test_global_gif_palette();
+    test_global_gif_palette_2frames();
+    test_local_gif_palette();
+    test_gif_frame_sizes();
+    test_truncated_gif();
+
+    IWICImagingFactory_Release(factory);
 }