From 755c19f3e710147f998a6278d369cc1d15f7d5a5 Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Wed, 20 Jun 2012 13:45:39 +0900 Subject: [PATCH] gdiplus: Implement GdipImageSelectActiveFrame. --- dlls/gdiplus/image.c | 114 ++++++++++++++++++++++++++++++------- dlls/gdiplus/tests/image.c | 4 +- 2 files changed, 97 insertions(+), 21 deletions(-) diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c index 7da052f16d0..52b37506929 100644 --- a/dlls/gdiplus/image.c +++ b/dlls/gdiplus/image.c @@ -1995,10 +1995,8 @@ static void move_bitmap(GpBitmap *dst, GpBitmap *src, BOOL clobber_palette) GdipFree(src); } -GpStatus WINGDIPAPI GdipDisposeImage(GpImage *image) +static GpStatus free_image_data(GpImage *image) { - TRACE("%p\n", image); - if(!image) return InvalidParameter; @@ -2033,6 +2031,18 @@ GpStatus WINGDIPAPI GdipDisposeImage(GpImage *image) if (image->stream) IStream_Release(image->stream); GdipFree(image->palette_entries); + + return Ok; +} + +GpStatus WINGDIPAPI GdipDisposeImage(GpImage *image) +{ + GpStatus status; + + TRACE("%p\n", image); + + status = free_image_data(image); + if (status != Ok) return status; image->type = ~0; GdipFree(image); @@ -2522,22 +2532,6 @@ GpStatus WINGDIPAPI GdipImageGetFrameDimensionsList(GpImage* image, return Ok; } -GpStatus WINGDIPAPI GdipImageSelectActiveFrame(GpImage *image, - GDIPCONST GUID* dimensionID, UINT frameidx) -{ - static int calls; - - TRACE("(%p, %s, %u)\n", image, debugstr_guid(dimensionID), frameidx); - - if(!image || !dimensionID) - return InvalidParameter; - - if(!(calls++)) - FIXME("not implemented\n"); - - return Ok; -} - GpStatus WINGDIPAPI GdipLoadImageFromFile(GDIPCONST WCHAR* filename, GpImage **image) { @@ -2862,6 +2856,88 @@ static GpStatus get_decoder_info(IStream* stream, const struct image_codec **res return GenericError; } +GpStatus WINGDIPAPI GdipImageSelectActiveFrame(GpImage *image, GDIPCONST GUID *dimensionID, + UINT frame) +{ + GpStatus stat; + LARGE_INTEGER seek; + HRESULT hr; + const struct image_codec *codec = NULL; + IStream *stream; + GpImage *new_image; + + TRACE("(%p,%s,%u)\n", image, debugstr_guid(dimensionID), frame); + + if (!image || !dimensionID) + return InvalidParameter; + + if (frame >= image->frame_count) + return InvalidParameter; + + if (image->type != ImageTypeBitmap && image->type != ImageTypeMetafile) + { + WARN("invalid image type %d\n", image->type); + return InvalidParameter; + } + + if (image->current_frame == frame) + return Ok; + + if (!image->stream) + { + TRACE("image doesn't have an associated stream\n"); + return Ok; + } + + hr = IStream_Clone(image->stream, &stream); + if (FAILED(hr)) + { + STATSTG statstg; + + hr = IStream_Stat(image->stream, &statstg, STATFLAG_NOOPEN); + if (FAILED(hr)) return hresult_to_status(hr); + + stat = GdipCreateStreamOnFile(statstg.pwcsName, GENERIC_READ, &stream); + if (stat != Ok) return stat; + } + + /* choose an appropriate image decoder */ + stat = get_decoder_info(stream, &codec); + if (stat != Ok) + { + IStream_Release(stream); + return stat; + } + + /* seek to the start of the stream */ + seek.QuadPart = 0; + hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL); + if (FAILED(hr)) + { + IStream_Release(stream); + return hresult_to_status(hr); + } + + /* call on the image decoder to do the real work */ + stat = codec->decode_func(stream, &codec->info.Clsid, frame, &new_image); + + if (stat == Ok) + { + memcpy(&new_image->format, &codec->info.FormatID, sizeof(GUID)); + free_image_data(image); + if (image->type == ImageTypeBitmap) + *(GpBitmap *)image = *(GpBitmap *)new_image; + else if (image->type == ImageTypeMetafile) + *(GpMetafile *)image = *(GpMetafile *)new_image; + new_image->type = ~0; + GdipFree(new_image); + return Ok; + } + + IStream_Release(stream); + return stat; +} + GpStatus WINGDIPAPI GdipLoadImageFromStream(IStream *source, GpImage **image) { GpStatus stat; diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c index 635b633d81b..84baaa3f762 100644 --- a/dlls/gdiplus/tests/image.c +++ b/dlls/gdiplus/tests/image.c @@ -2307,7 +2307,7 @@ static void test_multiframegif(void) color = 0xdeadbeef; GdipBitmapGetPixel(bmp, 0, 0, &color); expect(Ok, stat); - todo_wine expect(0xff000000, color); + expect(0xff000000, color); stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0); expect(Ok, stat); @@ -2338,7 +2338,7 @@ static void test_multiframegif(void) stat = GdipBitmapGetPixel(bmp, 0, 0, &color); expect(Ok, stat); - todo_wine expect(0xffffffff, color); + expect(0xffffffff, color); GdipDisposeImage((GpImage*)bmp); IStream_Release(stream);