Dmitry Timoshkov : windowscodecs: Create Image Descriptor metadata block for a GIF frame.

Alexandre Julliard julliard at winehq.org
Thu Sep 13 14:39:22 CDT 2012


Module: wine
Branch: master
Commit: 003c20467c355a3b251c685252456d2991faa412
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=003c20467c355a3b251c685252456d2991faa412

Author: Dmitry Timoshkov <dmitry at baikal.ru>
Date:   Thu Sep 13 10:26:04 2012 +0900

windowscodecs: Create Image Descriptor metadata block for a GIF frame.

---

 dlls/windowscodecs/gifformat.c      |  164 +++++++++++++++++++++++++++++++----
 dlls/windowscodecs/tests/metadata.c |    4 +-
 2 files changed, 150 insertions(+), 18 deletions(-)

diff --git a/dlls/windowscodecs/gifformat.c b/dlls/windowscodecs/gifformat.c
index 66c56a8..62bdc6f 100644
--- a/dlls/windowscodecs/gifformat.c
+++ b/dlls/windowscodecs/gifformat.c
@@ -149,25 +149,27 @@ HRESULT LSDReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppv)
     return MetadataReader_Create(&LSDReader_Vtbl, pUnkOuter, iid, ppv);
 }
 
+#include "pshpack1.h"
+struct image_descriptor
+{
+    USHORT left;
+    USHORT top;
+    USHORT width;
+    USHORT height;
+    BYTE packed;
+    /* local_color_table_flag : 1;
+     * interlace_flag : 1;
+     * sort_flag : 1;
+     * reserved : 2;
+     * local_color_table_size : 3;
+     */
+};
+#include "poppack.h"
+
 static HRESULT load_IMD_metadata(IStream *stream, const GUID *vendor, DWORD options,
                                  MetadataItem **items, DWORD *count)
 {
-#include "pshpack1.h"
-    struct image_descriptor
-    {
-        USHORT left;
-        USHORT top;
-        USHORT width;
-        USHORT height;
-        BYTE packed;
-        /* local_color_table_flag : 1;
-         * interlace_flag : 1;
-         * sort_flag : 1;
-         * reserved : 2;
-         * local_color_table_size : 3;
-         */
-    } imd_data;
-#include "poppack.h"
+    struct image_descriptor imd_data;
     HRESULT hr;
     ULONG bytesread, i;
     MetadataItem *result;
@@ -353,6 +355,7 @@ typedef struct {
 
 typedef struct {
     IWICBitmapFrameDecode IWICBitmapFrameDecode_iface;
+    IWICMetadataBlockReader IWICMetadataBlockReader_iface;
     LONG ref;
     SavedImage *frame;
     GifDecoder *parent;
@@ -373,6 +376,11 @@ static inline GifFrameDecode *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDec
     return CONTAINING_RECORD(iface, GifFrameDecode, IWICBitmapFrameDecode_iface);
 }
 
+static inline GifFrameDecode *frame_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface)
+{
+    return CONTAINING_RECORD(iface, GifFrameDecode, IWICMetadataBlockReader_iface);
+}
+
 static HRESULT WINAPI GifFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
     void **ppv)
 {
@@ -387,6 +395,10 @@ static HRESULT WINAPI GifFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface
     {
         *ppv = &This->IWICBitmapFrameDecode_iface;
     }
+    else if (IsEqualIID(&IID_IWICMetadataBlockReader, iid))
+    {
+        *ppv = &This->IWICMetadataBlockReader_iface;
+    }
     else
     {
         *ppv = NULL;
@@ -604,6 +616,125 @@ static const IWICBitmapFrameDecodeVtbl GifFrameDecode_Vtbl = {
     GifFrameDecode_GetThumbnail
 };
 
+static HRESULT WINAPI GifFrameDecode_Block_QueryInterface(IWICMetadataBlockReader *iface,
+    REFIID iid, void **ppv)
+{
+    GifFrameDecode *This = frame_from_IWICMetadataBlockReader(iface);
+    return IWICBitmapFrameDecode_QueryInterface(&This->IWICBitmapFrameDecode_iface, iid, ppv);
+}
+
+static ULONG WINAPI GifFrameDecode_Block_AddRef(IWICMetadataBlockReader *iface)
+{
+    GifFrameDecode *This = frame_from_IWICMetadataBlockReader(iface);
+    return IWICBitmapFrameDecode_AddRef(&This->IWICBitmapFrameDecode_iface);
+}
+
+static ULONG WINAPI GifFrameDecode_Block_Release(IWICMetadataBlockReader *iface)
+{
+    GifFrameDecode *This = frame_from_IWICMetadataBlockReader(iface);
+    return IWICBitmapFrameDecode_Release(&This->IWICBitmapFrameDecode_iface);
+}
+
+static HRESULT WINAPI GifFrameDecode_Block_GetContainerFormat(IWICMetadataBlockReader *iface,
+    GUID *guid)
+{
+    TRACE("(%p,%p)\n", iface, guid);
+
+    if (!guid) return E_INVALIDARG;
+
+    *guid = GUID_ContainerFormatGif;
+    return S_OK;
+}
+
+static HRESULT WINAPI GifFrameDecode_Block_GetCount(IWICMetadataBlockReader *iface,
+    UINT *count)
+{
+    TRACE("%p,%p\n", iface, count);
+
+    if (!count) return E_INVALIDARG;
+
+    *count = 1;
+    return S_OK;
+}
+
+static HRESULT create_IMD_metadata_reader(GifFrameDecode *This, IWICMetadataReader **reader)
+{
+    HRESULT hr;
+    IWICMetadataReader *metadata_reader;
+    IWICPersistStream *persist;
+    IStream *stream;
+    struct image_descriptor IMD_data;
+
+    /* FIXME: Use IWICComponentFactory_CreateMetadataReader once it's implemented */
+
+    hr = CoCreateInstance(&CLSID_WICIMDMetadataReader, NULL, CLSCTX_INPROC_SERVER,
+                          &IID_IWICMetadataReader, (void **)&metadata_reader);
+    if (FAILED(hr)) return hr;
+
+    hr = IWICMetadataReader_QueryInterface(metadata_reader, &IID_IWICPersistStream, (void **)&persist);
+    if (FAILED(hr))
+    {
+        IWICMetadataReader_Release(metadata_reader);
+        return hr;
+    }
+
+    /* recreate IMD structure from GIF decoder data */
+    IMD_data.left = This->frame->ImageDesc.Left;
+    IMD_data.top = This->frame->ImageDesc.Top;
+    IMD_data.width = This->frame->ImageDesc.Width;
+    IMD_data.height = This->frame->ImageDesc.Height;
+    IMD_data.packed = 0;
+    /* interlace_flag */
+    IMD_data.packed |= This->frame->ImageDesc.Interlace ? (1 << 6) : 0;
+    if (This->frame->ImageDesc.ColorMap)
+    {
+        /* local_color_table_flag */
+        IMD_data.packed |= 1 << 7;
+        /* local_color_table_size */
+        IMD_data.packed |= This->frame->ImageDesc.ColorMap->BitsPerPixel;
+        /* FIXME: sort_flag */
+    }
+
+    stream = create_stream(&IMD_data, sizeof(IMD_data));
+    IWICPersistStream_LoadEx(persist, stream, NULL, WICPersistOptionsDefault);
+    IStream_Release(stream);
+
+    IWICPersistStream_Release(persist);
+
+    *reader = metadata_reader;
+    return S_OK;
+}
+
+static HRESULT WINAPI GifFrameDecode_Block_GetReaderByIndex(IWICMetadataBlockReader *iface,
+    UINT index, IWICMetadataReader **reader)
+{
+    GifFrameDecode *This = frame_from_IWICMetadataBlockReader(iface);
+
+    TRACE("(%p,%u,%p)\n", iface, index, reader);
+
+    if (!reader || index != 0) return E_INVALIDARG;
+
+    return create_IMD_metadata_reader(This, reader);
+}
+
+static HRESULT WINAPI GifFrameDecode_Block_GetEnumerator(IWICMetadataBlockReader *iface,
+    IEnumUnknown **enumerator)
+{
+    FIXME("(%p,%p): stub\n", iface, enumerator);
+    return E_NOTIMPL;
+}
+
+static const IWICMetadataBlockReaderVtbl GifFrameDecode_BlockVtbl =
+{
+    GifFrameDecode_Block_QueryInterface,
+    GifFrameDecode_Block_AddRef,
+    GifFrameDecode_Block_Release,
+    GifFrameDecode_Block_GetContainerFormat,
+    GifFrameDecode_Block_GetCount,
+    GifFrameDecode_Block_GetReaderByIndex,
+    GifFrameDecode_Block_GetEnumerator
+};
+
 static HRESULT WINAPI GifDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
     void **ppv)
 {
@@ -824,6 +955,7 @@ static HRESULT WINAPI GifDecoder_GetFrame(IWICBitmapDecoder *iface,
     if (!result) return E_OUTOFMEMORY;
 
     result->IWICBitmapFrameDecode_iface.lpVtbl = &GifFrameDecode_Vtbl;
+    result->IWICMetadataBlockReader_iface.lpVtbl = &GifFrameDecode_BlockVtbl;
     result->ref = 1;
     result->frame = &This->gif->SavedImages[index];
     IWICBitmapDecoder_AddRef(iface);
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c
index 6bdecee..39c5144 100644
--- a/dlls/windowscodecs/tests/metadata.c
+++ b/dlls/windowscodecs/tests/metadata.c
@@ -1088,7 +1088,6 @@ static void test_metadata_gif(void)
     ok(hr == S_OK, "GetFrame error %#x\n", hr);
 
     hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void **)&blockreader);
-todo_wine
     ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* before Win7 */, "QueryInterface error %#x\n", hr);
 
     if (SUCCEEDED(hr))
@@ -1190,7 +1189,6 @@ todo_wine
     ok(hr == S_OK, "GetFrame error %#x\n", hr);
 
     hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void **)&blockreader);
-todo_wine
     ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* before Win7 */, "QueryInterface error %#x\n", hr);
 
     if (SUCCEEDED(hr))
@@ -1208,6 +1206,7 @@ todo_wine
 
         hr = IWICMetadataBlockReader_GetCount(blockreader, &count);
         ok(hr == S_OK, "GetCount error %#x\n", hr);
+todo_wine
         ok(count == 2, "expected 2, got %u\n", count);
 
         hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 0, &reader);
@@ -1229,6 +1228,7 @@ todo_wine
         }
 
         hr = IWICMetadataBlockReader_GetReaderByIndex(blockreader, 1, &reader);
+todo_wine
         ok(hr == S_OK, "GetReaderByIndex error %#x\n", hr);
 
         if (SUCCEEDED(hr))




More information about the wine-cvs mailing list