[WINDOWSCODECS_WINETEST] Sync with Wine Staging 1.7.55. CORE-10536
[reactos.git] / rostests / winetests / windowscodecs / gifformat.c
index a66cfd0..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,16 +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 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);
@@ -80,6 +101,20 @@ 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);
 
@@ -88,7 +123,8 @@ static IWICBitmapDecoder *create_decoder(const void *image_data, UINT image_size
     ok(IsEqualGUID(&format, &GUID_ContainerFormatGif),
        "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;
 }
@@ -334,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;
@@ -347,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);
 }