From 131a7b03e8fc2b609a4aef30a0bc9d71153722da Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Wed, 1 Apr 2015 14:57:45 -0500 Subject: [PATCH] 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 a862338adb3..9928be5924f 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 679ad3db915..2aac560840d 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 28469c7541e..ccb78b824cd 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 9f192b36e8c..1818b2694a2 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 a2f3ded784c..4efcd46b654 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 489d74bc5c7..089bb39dc95 100644 --- a/dlls/windowscodecs/windowscodecs_wincodec.idl +++ b/dlls/windowscodecs/windowscodecs_wincodec.idl @@ -139,6 +139,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),