Decoding a GIF with no color table currently crashes on Wine. Windows supports such files, and the GIF spec explicitly allows it.
From: Jeff Smith whydoubt@gmail.com
--- dlls/windowscodecs/tests/gifformat.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/dlls/windowscodecs/tests/gifformat.c b/dlls/windowscodecs/tests/gifformat.c index 8488f486a11..3f60d35a70f 100644 --- a/dlls/windowscodecs/tests/gifformat.c +++ b/dlls/windowscodecs/tests/gifformat.c @@ -130,7 +130,7 @@ static void test_global_gif_palette(void) IWICBitmapFrameDecode *frame; IWICPalette *palette; GUID format; - UINT count, ret; + UINT count, ret, i; WICColor color[256];
decoder = create_decoder(gif_global_palette, sizeof(gif_global_palette)); @@ -147,6 +147,8 @@ static void test_global_gif_palette(void) ok(hr == S_OK, "GetColorCount error %#lx\n", hr); ok(count == 4, "expected 4, got %u\n", count);
+ for (i = 0; i < 256; i++) + color[i] = 0xdeadbeef; hr = IWICPalette_GetColors(palette, count, color, &ret); ok(hr == S_OK, "GetColors error %#lx\n", hr); ok(ret == count, "expected %u, got %u\n", count, ret); @@ -154,6 +156,8 @@ static void test_global_gif_palette(void) ok(color[1] == 0x00040506, "expected 0x00040506, got %#x\n", color[1]); ok(color[2] == 0xff070809, "expected 0xff070809, got %#x\n", color[2]); ok(color[3] == 0xff0a0b0c, "expected 0xff0a0b0c, got %#x\n", color[3]); + for (i = 4; i < 256; i++) + ok(color[i] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", color[i]);
/* frame palette */ hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame); @@ -171,6 +175,8 @@ static void test_global_gif_palette(void) ok(hr == S_OK, "GetColorCount error %#lx\n", hr); ok(count == 4, "expected 4, got %u\n", count);
+ for (i = 0; i < 256; i++) + color[i] = 0xdeadbeef; hr = IWICPalette_GetColors(palette, count, color, &ret); ok(hr == S_OK, "GetColors error %#lx\n", hr); ok(ret == count, "expected %u, got %u\n", count, ret); @@ -178,6 +184,8 @@ static void test_global_gif_palette(void) ok(color[1] == 0x00040506, "expected 0x00040506, got %#x\n", color[1]); ok(color[2] == 0xff070809, "expected 0xff070809, got %#x\n", color[2]); ok(color[3] == 0xff0a0b0c, "expected 0xff0a0b0c, got %#x\n", color[3]); + for (i = 4; i < 256; i++) + ok(color[i] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", color[i]);
IWICPalette_Release(palette); IWICBitmapFrameDecode_Release(frame); @@ -320,12 +328,13 @@ static void test_local_gif_palette(void) ok(hr == S_OK, "GetColorCount error %#lx\n", hr); ok(count == 256, "expected 256, got %u\n", count);
+ for (i = 0; i < 256; i++) + color[i] = 0xdeadbeef; hr = IWICPalette_GetColors(palette, count, color, &ret); ok(hr == S_OK, "GetColors error %#lx\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]); } @@ -351,6 +360,8 @@ static void test_local_gif_palette(void) ok(hr == S_OK, "GetType error %#lx\n", hr); ok(type == WICBitmapPaletteTypeCustom, "expected WICBitmapPaletteTypeCustom, got %#x\n", type);
+ for (i = 0; i < 256; i++) + color[i] = 0xdeadbeef; hr = IWICPalette_GetColors(palette, count, color, &ret); ok(hr == S_OK, "GetColors error %#lx\n", hr); ok(ret == count, "expected %u, got %u\n", count, ret); @@ -358,6 +369,8 @@ static void test_local_gif_palette(void) ok(color[1] == 0x00040506, "expected 0x00040506, got %#x\n", color[1]); ok(color[2] == 0xff070809, "expected 0xff070809, got %#x\n", color[2]); ok(color[3] == 0xff0a0b0c, "expected 0xff0a0b0c, got %#x\n", color[3]); + for (i = 4; i < 256; i++) + ok(color[i] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", color[i]);
IWICPalette_Release(palette); IWICBitmapFrameDecode_Release(frame);
From: Jeff Smith whydoubt@gmail.com
--- dlls/windowscodecs/gifformat.c | 92 +++++++++++++++------------------- 1 file changed, 40 insertions(+), 52 deletions(-)
diff --git a/dlls/windowscodecs/gifformat.c b/dlls/windowscodecs/gifformat.c index f0048d12da9..c7e0f83c856 100644 --- a/dlls/windowscodecs/gifformat.c +++ b/dlls/windowscodecs/gifformat.c @@ -701,14 +701,49 @@ static HRESULT WINAPI GifFrameDecode_GetResolution(IWICBitmapFrameDecode *iface, return S_OK; }
+static void copy_palette(ColorMapObject *cm, Extensions *extensions, int count, WICColor *colors) +{ + int i; + + if (cm) + { + for (i = 0; i < count; i++) + { + colors[i] = 0xff000000 | /* alpha */ + cm->Colors[i].Red << 16 | + cm->Colors[i].Green << 8 | + cm->Colors[i].Blue; + } + } + else + { + colors[0] = 0xff000000; + colors[1] = 0xffffffff; + for (i = 2; i < count; i++) + colors[i] = 0xff000000; + } + + /* look for the transparent color extension */ + for (i = 0; i < extensions->ExtensionBlockCount; i++) + { + ExtensionBlock *eb = extensions->ExtensionBlocks + i; + if (eb->Function == GRAPHICS_EXT_FUNC_CODE && + eb->ByteCount == 8 && eb->Bytes[3] & 1) + { + int trans = (unsigned char)eb->Bytes[6]; + colors[trans] &= 0xffffff; /* set alpha to 0 */ + break; + } + } +} + static HRESULT WINAPI GifFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface, IWICPalette *pIPalette) { GifFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface); WICColor colors[256]; ColorMapObject *cm = This->frame->ImageDesc.ColorMap; - int i, trans; - ExtensionBlock *eb; + TRACE("(%p,%p)\n", iface, pIPalette);
if (!cm) cm = This->parent->gif->SColorMap; @@ -719,24 +754,7 @@ static HRESULT WINAPI GifFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface, return E_FAIL; }
- for (i = 0; i < cm->ColorCount; i++) { - colors[i] = 0xff000000| /* alpha */ - cm->Colors[i].Red << 16| - cm->Colors[i].Green << 8| - cm->Colors[i].Blue; - } - - /* look for the transparent color extension */ - for (i = 0; i < This->frame->Extensions.ExtensionBlockCount; ++i) { - eb = This->frame->Extensions.ExtensionBlocks + i; - if (eb->Function == GRAPHICS_EXT_FUNC_CODE && eb->ByteCount == 8) { - if (eb->Bytes[3] & 1) { - trans = (unsigned char)eb->Bytes[6]; - colors[trans] &= 0xffffff; /* set alpha to 0 */ - break; - } - } - } + copy_palette(cm, &This->frame->Extensions, count, cm->ColorCount);
return IWICPalette_InitializeCustom(pIPalette, colors, cm->ColorCount); } @@ -1170,8 +1188,7 @@ static HRESULT WINAPI GifDecoder_CopyPalette(IWICBitmapDecoder *iface, IWICPalet GifDecoder *This = impl_from_IWICBitmapDecoder(iface); WICColor colors[256]; ColorMapObject *cm; - int i, trans, count; - ExtensionBlock *eb; + int count;
TRACE("(%p,%p)\n", iface, palette);
@@ -1187,41 +1204,12 @@ static HRESULT WINAPI GifDecoder_CopyPalette(IWICBitmapDecoder *iface, IWICPalet return E_FAIL; }
- for (i = 0; i < cm->ColorCount; i++) - { - colors[i] = 0xff000000 | /* alpha */ - cm->Colors[i].Red << 16 | - cm->Colors[i].Green << 8 | - cm->Colors[i].Blue; - } - count = cm->ColorCount; } else - { - colors[0] = 0xff000000; - colors[1] = 0xffffffff; - - for (i = 2; i < 256; i++) - colors[i] = 0xff000000; - count = 256; - }
- /* look for the transparent color extension */ - for (i = 0; i < This->gif->SavedImages[This->current_frame].Extensions.ExtensionBlockCount; i++) - { - eb = This->gif->SavedImages[This->current_frame].Extensions.ExtensionBlocks + i; - if (eb->Function == GRAPHICS_EXT_FUNC_CODE && eb->ByteCount == 8) - { - if (eb->Bytes[3] & 1) - { - trans = (unsigned char)eb->Bytes[6]; - colors[trans] &= 0xffffff; /* set alpha to 0 */ - break; - } - } - } + copy_palette(cm, &This->gif->SavedImages[This->current_frame].Extensions, count, colors);
return IWICPalette_InitializeCustom(palette, colors, count); }
From: Jeff Smith whydoubt@gmail.com
--- dlls/windowscodecs/gifformat.c | 32 ++++++------ dlls/windowscodecs/tests/gifformat.c | 78 ++++++++++++++++++++++++++++ dlls/windowscodecs/ungif.c | 1 + dlls/windowscodecs/ungif.h | 1 + 4 files changed, 97 insertions(+), 15 deletions(-)
diff --git a/dlls/windowscodecs/gifformat.c b/dlls/windowscodecs/gifformat.c index c7e0f83c856..152c51eac76 100644 --- a/dlls/windowscodecs/gifformat.c +++ b/dlls/windowscodecs/gifformat.c @@ -743,20 +743,27 @@ static HRESULT WINAPI GifFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface, GifFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface); WICColor colors[256]; ColorMapObject *cm = This->frame->ImageDesc.ColorMap; + int count;
TRACE("(%p,%p)\n", iface, pIPalette);
- if (!cm) cm = This->parent->gif->SColorMap; + if (cm) + count = cm->ColorCount; + else + { + cm = This->parent->gif->SColorMap; + count = This->parent->gif->SColorTableSize; + }
- if (cm->ColorCount > 256) + if (count > 256) { - ERR("GIF contains %i colors???\n", cm->ColorCount); + ERR("GIF contains %i colors???\n", count); return E_FAIL; }
- copy_palette(cm, &This->frame->Extensions, count, cm->ColorCount); + copy_palette(cm, &This->frame->Extensions, count, colors);
- return IWICPalette_InitializeCustom(pIPalette, colors, cm->ColorCount); + return IWICPalette_InitializeCustom(pIPalette, colors, count); }
static HRESULT copy_interlaced_pixels(const BYTE *srcbuffer, @@ -1196,18 +1203,13 @@ static HRESULT WINAPI GifDecoder_CopyPalette(IWICBitmapDecoder *iface, IWICPalet return WINCODEC_ERR_WRONGSTATE;
cm = This->gif->SColorMap; - if (cm) - { - if (cm->ColorCount > 256) - { - ERR("GIF contains invalid number of colors: %d\n", cm->ColorCount); - return E_FAIL; - } + count = This->gif->SColorTableSize;
- count = cm->ColorCount; + if (count > 256) + { + ERR("GIF contains invalid number of colors: %d\n", count); + return E_FAIL; } - else - count = 256;
copy_palette(cm, &This->gif->SavedImages[This->current_frame].Extensions, count, colors);
diff --git a/dlls/windowscodecs/tests/gifformat.c b/dlls/windowscodecs/tests/gifformat.c index 3f60d35a70f..4185d306e46 100644 --- a/dlls/windowscodecs/tests/gifformat.c +++ b/dlls/windowscodecs/tests/gifformat.c @@ -57,6 +57,13 @@ static const char gif_local_palette[] = { 0x02,0x02,0x44,0x01,0x00,0x3b };
+static const char gif_no_palette[] = { +/* LSD */'G','I','F','8','7','a',0x01,0x00,0x01,0x00,0x21,0x02,0x00, +/* GCE */0x21,0xf9,0x04,0x01,0x05,0x00,0x01,0x00, /* index 1 */ +/* IMD */0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00, +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 \ @@ -377,6 +384,75 @@ static void test_local_gif_palette(void) IWICBitmapDecoder_Release(decoder); }
+static void test_no_gif_palette(void) +{ + HRESULT hr; + IWICBitmapDecoder *decoder; + IWICBitmapFrameDecode *frame; + IWICPalette *palette; + GUID format; + UINT count, ret, i; + WICColor color[256]; + + decoder = create_decoder(gif_no_palette, sizeof(gif_no_palette)); + ok(decoder != 0, "Failed to load GIF image data\n"); + + hr = IWICImagingFactory_CreatePalette(factory, &palette); + ok(hr == S_OK, "CreatePalette error %#lx\n", hr); + + /* global palette */ + hr = IWICBitmapDecoder_CopyPalette(decoder, palette); + ok(hr == S_OK, "CopyPalette error %#lx\n", hr); + + hr = IWICPalette_GetColorCount(palette, &count); + ok(hr == S_OK, "GetColorCount error %#lx\n", hr); + ok(count == 4, "expected 4, got %u\n", count); + + for (i = 0; i < 256; i++) + color[i] = 0xdeadbeef; + hr = IWICPalette_GetColors(palette, count, color, &ret); + ok(hr == S_OK, "GetColors error %#lx\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]); + ok(color[2] == 0xff000000, "expected 0xff000000, got %#x\n", color[2]); + ok(color[3] == 0xff000000, "expected 0xff000000, got %#x\n", color[3]); + for (i = 4; i < 256; i++) + ok(color[i] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", color[i]); + + /* frame palette */ + hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame); + ok(hr == S_OK, "GetFrame error %#lx\n", hr); + + hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format); + ok(hr == S_OK, "GetPixelFormat error %#lx\n", hr); + ok(IsEqualGUID(&format, &GUID_WICPixelFormat8bppIndexed), + "wrong pixel format %s\n", wine_dbgstr_guid(&format)); + + hr = IWICBitmapFrameDecode_CopyPalette(frame, palette); + ok(hr == S_OK, "CopyPalette error %#lx\n", hr); + + hr = IWICPalette_GetColorCount(palette, &count); + ok(hr == S_OK, "GetColorCount error %#lx\n", hr); + ok(count == 4, "expected 4, got %u\n", count); + + for (i = 0; i < 256; i++) + color[i] = 0xdeadbeef; + hr = IWICPalette_GetColors(palette, count, color, &ret); + ok(hr == S_OK, "GetColors error %#lx\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]); + ok(color[2] == 0xff000000, "expected 0xff000000, got %#x\n", color[2]); + ok(color[3] == 0xff000000, "expected 0xff000000, got %#x\n", color[3]); + for (i = 4; i < 256; i++) + ok(color[i] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", color[i]); + + IWICPalette_Release(palette); + IWICBitmapFrameDecode_Release(frame); + IWICBitmapDecoder_Release(decoder); +} + static void test_gif_frame_sizes(void) { static const BYTE frame0[] = {0, 1, 0xfe, 0xfe, 2, 3, 0xfe, 0xfe}; @@ -590,6 +666,7 @@ START_TEST(gifformat) test_global_gif_palette(); test_global_gif_palette_2frames(); test_local_gif_palette(); + test_no_gif_palette(); test_gif_frame_sizes(); test_gif_notrailer();
@@ -603,6 +680,7 @@ START_TEST(gifformat) test_global_gif_palette(); test_global_gif_palette_2frames(); test_local_gif_palette(); + test_no_gif_palette(); test_gif_frame_sizes(); test_truncated_gif();
diff --git a/dlls/windowscodecs/ungif.c b/dlls/windowscodecs/ungif.c index 0f5ed6e25d5..1fb16e52f15 100644 --- a/dlls/windowscodecs/ungif.c +++ b/dlls/windowscodecs/ungif.c @@ -320,6 +320,7 @@ DGifGetScreenDesc(GifFileType * GifFile) { GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1; SortFlag = (Buf[0] & 0x08) != 0; BitsPerPixel = (Buf[0] & 0x07) + 1; + GifFile->SColorTableSize = 1 << BitsPerPixel; GifFile->SBackGroundColor = Buf[1]; GifFile->SAspectRatio = Buf[2]; if (Buf[0] & 0x80) { /* Do we have global color map? */ diff --git a/dlls/windowscodecs/ungif.h b/dlls/windowscodecs/ungif.h index ae8269226df..f61a7eb1e16 100644 --- a/dlls/windowscodecs/ungif.h +++ b/dlls/windowscodecs/ungif.h @@ -114,6 +114,7 @@ typedef struct { typedef struct GifFileType { GifWord SWidth, SHeight, /* Screen dimensions. */ SColorResolution, /* How many colors can we generate? */ + SColorTableSize, /* Calculated color table size, even if not present */ SBackGroundColor, /* I hope you understand this one... */ SAspectRatio; /* Pixel aspect ratio, in 1/64 units, starting at 1:4. */ ColorMapObject *SColorMap; /* NULL if not exists. */