[5/5] gdiplus: Implement GdipImageSelectActiveFrame.

Dmitry Timoshkov dmitry at baikal.ru
Tue Jun 19 02:52:02 CDT 2012


---
 dlls/gdiplus/image.c       | 112 +++++++++++++++++++++++++++++++++++++--------
 dlls/gdiplus/tests/image.c |   4 +-
 2 files changed, 95 insertions(+), 21 deletions(-)

diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c
index 7da052f..9dada84 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,86 @@ 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;
+        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 635b633..84baaa3 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);
-- 
1.7.11




More information about the wine-patches mailing list