Vincent Povirk : windowscodecs: Implement PNG tEXt metadata reader.

Alexandre Julliard julliard at winehq.org
Tue Sep 11 16:59:05 CDT 2012


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

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Mon Sep 10 17:01:15 2012 -0500

windowscodecs: Implement PNG tEXt metadata reader.

---

 dlls/windowscodecs/clsfactory.c               |    1 +
 dlls/windowscodecs/metadatahandler.c          |    7 ++-
 dlls/windowscodecs/pngformat.c                |  112 +++++++++++++++++++++++++
 dlls/windowscodecs/regsvr.c                   |   25 ++++++
 dlls/windowscodecs/tests/metadata.c           |    2 +-
 dlls/windowscodecs/wincodecs_private.h        |    4 +
 dlls/windowscodecs/windowscodecs_wincodec.idl |    7 ++
 7 files changed, 156 insertions(+), 2 deletions(-)

diff --git a/dlls/windowscodecs/clsfactory.c b/dlls/windowscodecs/clsfactory.c
index 40d1547..91c75b7 100644
--- a/dlls/windowscodecs/clsfactory.c
+++ b/dlls/windowscodecs/clsfactory.c
@@ -61,6 +61,7 @@ static const classinfo wic_classes[] = {
     {&CLSID_WineTgaDecoder, TgaDecoder_CreateInstance},
     {&CLSID_WICUnknownMetadataReader, UnknownMetadataReader_CreateInstance},
     {&CLSID_WICIfdMetadataReader, IfdMetadataReader_CreateInstance},
+    {&CLSID_WICPngTextMetadataReader, PngTextReader_CreateInstance},
     {0}};
 
 typedef struct {
diff --git a/dlls/windowscodecs/metadatahandler.c b/dlls/windowscodecs/metadatahandler.c
index 084facf..5e50cb9 100644
--- a/dlls/windowscodecs/metadatahandler.c
+++ b/dlls/windowscodecs/metadatahandler.c
@@ -255,6 +255,11 @@ static int propvar_cmp(const PROPVARIANT *v1, const PROPVARIANT *v2)
 {
     LONGLONG value1, value2;
 
+    if (v1->vt == VT_LPSTR && v2->vt == VT_LPSTR)
+    {
+        return lstrcmpA(v1->u.pszVal, v2->u.pszVal);
+    }
+
     if (!get_int_value(v1, &value1)) return -1;
     if (!get_int_value(v2, &value2)) return -1;
 
@@ -446,7 +451,7 @@ static const IWICPersistStreamVtbl MetadataHandler_PersistStream_Vtbl = {
     MetadataHandler_SaveEx
 };
 
-static HRESULT MetadataReader_Create(const MetadataHandlerVtbl *vtable, IUnknown *pUnkOuter, REFIID iid, void** ppv)
+HRESULT MetadataReader_Create(const MetadataHandlerVtbl *vtable, IUnknown *pUnkOuter, REFIID iid, void** ppv)
 {
     MetadataHandler *This;
     HRESULT hr;
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index 683da2d..3eae4b7 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -40,6 +40,118 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
 
+static HRESULT read_png_chunk(IStream *stream, BYTE *type, BYTE **data, ULONG *data_size)
+{
+    BYTE header[8];
+    HRESULT hr;
+    ULONG bytesread;
+
+    hr = IStream_Read(stream, header, 8, &bytesread);
+    if (FAILED(hr) || bytesread < 8)
+    {
+        if (SUCCEEDED(hr))
+            hr = E_FAIL;
+        return hr;
+    }
+
+    *data_size = header[0] << 24 | header[1] << 16 | header[2] << 8 | header[3];
+
+    memcpy(type, &header[4], 4);
+
+    if (data)
+    {
+        *data = HeapAlloc(GetProcessHeap(), 0, *data_size);
+        if (!*data)
+            return E_OUTOFMEMORY;
+
+        hr = IStream_Read(stream, *data, *data_size, &bytesread);
+
+        if (FAILED(hr) || bytesread < *data_size)
+        {
+            if (SUCCEEDED(hr))
+                hr = E_FAIL;
+            HeapFree(GetProcessHeap(), 0, *data);
+            *data = NULL;
+            return hr;
+        }
+
+        /* FIXME: Verify the CRC? */
+    }
+
+    return S_OK;
+}
+
+static HRESULT LoadTextMetadata(IStream *stream, const GUID *preferred_vendor,
+    DWORD persist_options, MetadataItem **items, DWORD *item_count)
+{
+    HRESULT hr;
+    BYTE type[4];
+    BYTE *data;
+    ULONG data_size;
+    ULONG name_len, value_len;
+    BYTE *name_end_ptr;
+    LPSTR name, value;
+    MetadataItem *result;
+
+    hr = read_png_chunk(stream, type, &data, &data_size);
+    if (FAILED(hr)) return hr;
+
+    name_end_ptr = memchr(data, 0, data_size);
+
+    name_len = name_end_ptr - data;
+
+    if (!name_end_ptr || name_len > 79)
+    {
+        HeapFree(GetProcessHeap(), 0, data);
+        return E_FAIL;
+    }
+
+    value_len = data_size - name_len - 1;
+
+    result = HeapAlloc(GetProcessHeap(), 0, sizeof(MetadataItem));
+    name = HeapAlloc(GetProcessHeap(), 0, name_len + 1);
+    value = HeapAlloc(GetProcessHeap(), 0, value_len + 1);
+    if (!result || !name || !value)
+    {
+        HeapFree(GetProcessHeap(), 0, data);
+        HeapFree(GetProcessHeap(), 0, result);
+        HeapFree(GetProcessHeap(), 0, name);
+        HeapFree(GetProcessHeap(), 0, value);
+        return E_OUTOFMEMORY;
+    }
+
+    PropVariantInit(&result[0].schema);
+    PropVariantInit(&result[0].id);
+    PropVariantInit(&result[0].value);
+
+    memcpy(name, data, name_len + 1);
+    memcpy(value, name_end_ptr + 1, value_len);
+    value[value_len] = 0;
+
+    result[0].id.vt = VT_LPSTR;
+    result[0].id.pszVal = name;
+    result[0].value.vt = VT_LPSTR;
+    result[0].value.pszVal = value;
+
+    *items = result;
+    *item_count = 1;
+
+    HeapFree(GetProcessHeap(), 0, data);
+
+    return S_OK;
+}
+
+static const MetadataHandlerVtbl TextReader_Vtbl = {
+    0,
+    &CLSID_WICPngTextMetadataReader,
+    LoadTextMetadata
+};
+
+HRESULT PngTextReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
+{
+    return MetadataReader_Create(&TextReader_Vtbl, pUnkOuter, iid, ppv);
+}
+
 #ifdef SONAME_LIBPNG
 
 static void *libpng_handle;
diff --git a/dlls/windowscodecs/regsvr.c b/dlls/windowscodecs/regsvr.c
index a422747..cb11430 100644
--- a/dlls/windowscodecs/regsvr.c
+++ b/dlls/windowscodecs/regsvr.c
@@ -1503,6 +1503,21 @@ static const struct reader_containers ifd_containers[] = {
     { NULL } /* list terminator */
 };
 
+static const BYTE tEXt[] = "tEXt";
+
+static const struct metadata_pattern pngtext_metadata_pattern[] = {
+    { 4, 4, tEXt, mask_all, 4 },
+    { 0 }
+};
+
+static const struct reader_containers pngtext_containers[] = {
+    {
+        &GUID_ContainerFormatPng,
+        pngtext_metadata_pattern
+    },
+    { NULL } /* list terminator */
+};
+
 static struct regsvr_metadatareader const metadatareader_list[] = {
     {   &CLSID_WICUnknownMetadataReader,
         "The Wine Project",
@@ -1525,6 +1540,16 @@ static struct regsvr_metadatareader const metadatareader_list[] = {
         1, 1, 0,
         ifd_containers
     },
+    {   &CLSID_WICPngTextMetadataReader,
+        "The Wine Project",
+        "Unknown Metadata Reader",
+        "1.0.0.0",
+        "1.0.0.0",
+        &GUID_VendorMicrosoft,
+        &GUID_MetadataFormatChunktEXt,
+        0, 0, 0,
+        pngtext_containers
+    },
     { NULL }			/* list terminator */
 };
 
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c
index 4bb33ae..229753c 100644
--- a/dlls/windowscodecs/tests/metadata.c
+++ b/dlls/windowscodecs/tests/metadata.c
@@ -303,7 +303,7 @@ static void test_metadata_tEXt(void)
 
     hr = CoCreateInstance(&CLSID_WICPngTextMetadataReader, NULL, CLSCTX_INPROC_SERVER,
         &IID_IWICMetadataReader, (void**)&reader);
-    todo_wine ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
+    ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
     if (FAILED(hr)) return;
 
     hr = IWICMetadataReader_GetCount(reader, NULL);
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index 0bee818..37f9c90 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -90,7 +90,11 @@ typedef struct _MetadataHandlerVtbl
         ULARGE_INTEGER *size);
 } MetadataHandlerVtbl;
 
+extern HRESULT MetadataReader_Create(const MetadataHandlerVtbl *vtable, IUnknown *pUnkOuter, REFIID iid, void** ppv) DECLSPEC_HIDDEN;
+
 extern HRESULT UnknownMetadataReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv) DECLSPEC_HIDDEN;
 extern HRESULT IfdMetadataReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppv) DECLSPEC_HIDDEN;
 
+extern HRESULT PngTextReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv) DECLSPEC_HIDDEN;
+
 #endif /* WINCODECS_PRIVATE_H */
diff --git a/dlls/windowscodecs/windowscodecs_wincodec.idl b/dlls/windowscodecs/windowscodecs_wincodec.idl
index bc4c994..6d5bd2d 100644
--- a/dlls/windowscodecs/windowscodecs_wincodec.idl
+++ b/dlls/windowscodecs/windowscodecs_wincodec.idl
@@ -135,3 +135,10 @@ coclass WICUnknownMetadataReader { interface IWICMetadataReader; }
     uuid(8f914656-9d0a-4eb2-9019-0bf96d8a9ee6)
 ]
 coclass WICIfdMetadataReader { interface IWICIfdMetadataReader; }
+
+[
+    helpstring("WIC Png tEXt Metadata Reader"),
+    threading(both),
+    uuid(4b59afcc-b8c3-408a-b670-89e5fab6fda7)
+]
+coclass WICPngTextMetadataReader { interface IWICMetadataReader; }




More information about the wine-cvs mailing list