Vincent Povirk : windowscodecs: Implement PNG gAMA metadata reader.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Apr 7 10:11:27 CDT 2015


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

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Wed Apr  1 14:57:45 2015 -0500

windowscodecs: Implement PNG gAMA metadata reader.

---

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

diff --git a/dlls/windowscodecs/clsfactory.c b/dlls/windowscodecs/clsfactory.c
index a862338..9928be5 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_WICPngGamaMetadataReader, PngGamaReader_CreateInstance},
     {&CLSID_WICPngTextMetadataReader, PngTextReader_CreateInstance},
     {&CLSID_WICLSDMetadataReader, LSDReader_CreateInstance},
     {&CLSID_WICIMDMetadataReader, IMDReader_CreateInstance},
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index 679ad3d..2aac560 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -43,6 +43,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
 
 static const WCHAR wszPngInterlaceOption[] = {'I','n','t','e','r','l','a','c','e','O','p','t','i','o','n',0};
 
+static inline ULONG read_ulong_be(BYTE* data)
+{
+    return data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+}
+
 static HRESULT read_png_chunk(IStream *stream, BYTE *type, BYTE **data, ULONG *data_size)
 {
     BYTE header[8];
@@ -57,7 +62,7 @@ static HRESULT read_png_chunk(IStream *stream, BYTE *type, BYTE **data, ULONG *d
         return hr;
     }
 
-    *data_size = header[0] << 24 | header[1] << 16 | header[2] << 8 | header[3];
+    *data_size = read_ulong_be(&header[0]);
 
     memcpy(type, &header[4], 4);
 
@@ -155,6 +160,68 @@ HRESULT PngTextReader_CreateInstance(REFIID iid, void** ppv)
     return MetadataReader_Create(&TextReader_Vtbl, iid, ppv);
 }
 
+static HRESULT LoadGamaMetadata(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 gamma;
+    static const WCHAR ImageGamma[] = {'I','m','a','g','e','G','a','m','m','a',0};
+    LPWSTR name;
+    MetadataItem *result;
+
+    hr = read_png_chunk(stream, type, &data, &data_size);
+    if (FAILED(hr)) return hr;
+
+    if (data_size < 4)
+    {
+        HeapFree(GetProcessHeap(), 0, data);
+        return E_FAIL;
+    }
+
+    gamma = read_ulong_be(data);
+
+    HeapFree(GetProcessHeap(), 0, data);
+
+    result = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MetadataItem));
+    name = HeapAlloc(GetProcessHeap(), 0, sizeof(ImageGamma));
+    if (!result || !name)
+    {
+        HeapFree(GetProcessHeap(), 0, result);
+        HeapFree(GetProcessHeap(), 0, name);
+        return E_OUTOFMEMORY;
+    }
+
+    PropVariantInit(&result[0].schema);
+    PropVariantInit(&result[0].id);
+    PropVariantInit(&result[0].value);
+
+    memcpy(name, ImageGamma, sizeof(ImageGamma));
+
+    result[0].id.vt = VT_LPWSTR;
+    result[0].id.u.pwszVal = name;
+    result[0].value.vt = VT_UI4;
+    result[0].value.u.ulVal = gamma;
+
+    *items = result;
+    *item_count = 1;
+
+    return S_OK;
+}
+
+static const MetadataHandlerVtbl GamaReader_Vtbl = {
+    0,
+    &CLSID_WICPngGamaMetadataReader,
+    LoadGamaMetadata
+};
+
+HRESULT PngGamaReader_CreateInstance(REFIID iid, void** ppv)
+{
+    return MetadataReader_Create(&GamaReader_Vtbl, iid, ppv);
+}
+
 #ifdef SONAME_LIBPNG
 
 static void *libpng_handle;
diff --git a/dlls/windowscodecs/regsvr.c b/dlls/windowscodecs/regsvr.c
index 28469c7..ccb78b8 100644
--- a/dlls/windowscodecs/regsvr.c
+++ b/dlls/windowscodecs/regsvr.c
@@ -1502,6 +1502,21 @@ static const struct reader_containers pngtext_containers[] = {
     { NULL } /* list terminator */
 };
 
+static const BYTE gAMA[] = "gAMA";
+
+static const struct metadata_pattern pnggama_metadata_pattern[] = {
+    { 4, 4, gAMA, mask_all, 4 },
+    { 0 }
+};
+
+static const struct reader_containers pnggama_containers[] = {
+    {
+        &GUID_ContainerFormatPng,
+        pnggama_metadata_pattern
+    },
+    { NULL } /* list terminator */
+};
+
 static const struct metadata_pattern lsd_metadata_patterns[] = {
     { 0, 6, gif87a_magic, mask_all, 0 },
     { 0, 6, gif89a_magic, mask_all, 0 },
@@ -1597,6 +1612,16 @@ static struct regsvr_metadatareader const metadatareader_list[] = {
         1, 1, 0,
         ifd_containers
     },
+    {   &CLSID_WICPngGamaMetadataReader,
+        "The Wine Project",
+        "Chunk gAMA Reader",
+        "1.0.0.0",
+        "1.0.0.0",
+        &GUID_VendorMicrosoft,
+        &GUID_MetadataFormatChunkgAMA,
+        0, 0, 0,
+        pnggama_containers
+    },
     {   &CLSID_WICPngTextMetadataReader,
         "The Wine Project",
         "Chunk tEXt Reader",
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c
index 9f192b3..1818b26 100644
--- a/dlls/windowscodecs/tests/metadata.c
+++ b/dlls/windowscodecs/tests/metadata.c
@@ -427,7 +427,7 @@ static void test_metadata_gAMA(void)
 
     hr = CoCreateInstance(&CLSID_WICPngGamaMetadataReader, NULL, CLSCTX_INPROC_SERVER,
         &IID_IWICMetadataReader, (void**)&reader);
-    todo_wine ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG) /*winxp*/, "CoCreateInstance failed, hr=%x\n", hr);
+    ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG) /*winxp*/, "CoCreateInstance failed, hr=%x\n", hr);
     if (FAILED(hr)) return;
 
     load_stream((IUnknown*)reader, metadata_gAMA, sizeof(metadata_gAMA), WICPersistOptionsDefault);
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index a2f3ded..4efcd46 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -151,6 +151,7 @@ extern HRESULT MetadataReader_Create(const MetadataHandlerVtbl *vtable, REFIID i
 
 extern HRESULT UnknownMetadataReader_CreateInstance(REFIID iid, void** ppv) DECLSPEC_HIDDEN;
 extern HRESULT IfdMetadataReader_CreateInstance(REFIID iid, void **ppv) DECLSPEC_HIDDEN;
+extern HRESULT PngGamaReader_CreateInstance(REFIID iid, void** ppv) DECLSPEC_HIDDEN;
 extern HRESULT PngTextReader_CreateInstance(REFIID iid, void** ppv) DECLSPEC_HIDDEN;
 extern HRESULT LSDReader_CreateInstance(REFIID iid, void **ppv) DECLSPEC_HIDDEN;
 extern HRESULT IMDReader_CreateInstance(REFIID iid, void **ppv) DECLSPEC_HIDDEN;
diff --git a/dlls/windowscodecs/windowscodecs_wincodec.idl b/dlls/windowscodecs/windowscodecs_wincodec.idl
index 489d74b..089bb39 100644
--- a/dlls/windowscodecs/windowscodecs_wincodec.idl
+++ b/dlls/windowscodecs/windowscodecs_wincodec.idl
@@ -140,6 +140,13 @@ coclass WICUnknownMetadataReader { interface IWICMetadataReader; }
 coclass WICIfdMetadataReader { interface IWICIfdMetadataReader; }
 
 [
+    helpstring("WIC Png gAMA Metadata Reader"),
+    threading(both),
+    uuid(3692ca39-e082-4350-9e1f-3704cb083cd5)
+]
+coclass WICPngGamaMetadataReader { interface IWICMetadataReader; }
+
+[
     helpstring("WIC Png tEXt Metadata Reader"),
     threading(both),
     uuid(4b59afcc-b8c3-408a-b670-89e5fab6fda7)




More information about the wine-cvs mailing list