From: Nikolay Sivov nsivov@codeweavers.com
--- dlls/windowscodecs/clsfactory.c | 1 + dlls/windowscodecs/pngformat.c | 108 ++++++++++++++++++ dlls/windowscodecs/regsvr.c | 25 ++++ dlls/windowscodecs/tests/metadata.c | 50 ++++---- dlls/windowscodecs/wincodecs_private.h | 1 + dlls/windowscodecs/windowscodecs_wincodec.idl | 7 ++ 6 files changed, 169 insertions(+), 23 deletions(-)
diff --git a/dlls/windowscodecs/clsfactory.c b/dlls/windowscodecs/clsfactory.c index 716fc8b6bde..b84021ddabe 100644 --- a/dlls/windowscodecs/clsfactory.c +++ b/dlls/windowscodecs/clsfactory.c @@ -70,6 +70,7 @@ static const classinfo wic_classes[] = { {&CLSID_WICExifMetadataWriter, ExifMetadataWriter_CreateInstance}, {&CLSID_WICApp1MetadataReader, App1MetadataReader_CreateInstance}, {&CLSID_WICApp1MetadataWriter, App1MetadataWriter_CreateInstance}, + {&CLSID_WICPngBkgdMetadataReader, PngBkgdReader_CreateInstance}, {&CLSID_WICPngChrmMetadataReader, PngChrmReader_CreateInstance}, {&CLSID_WICPngGamaMetadataReader, PngGamaReader_CreateInstance}, {&CLSID_WICPngHistMetadataReader, PngHistReader_CreateInstance}, diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c index 2e344c3da2d..2707fdc5c4c 100644 --- a/dlls/windowscodecs/pngformat.c +++ b/dlls/windowscodecs/pngformat.c @@ -506,6 +506,114 @@ HRESULT PngTimeReader_CreateInstance(REFIID iid, void** ppv) return MetadataReader_Create(&TimeReader_Vtbl, iid, ppv); }
+static HRESULT create_bkgd_item(const PROPVARIANT *value, MetadataItem **ret) +{ + MetadataItem *item; + HRESULT hr; + + if (!(item = calloc(1, sizeof(*item)))) + return E_OUTOFMEMORY; + + if (FAILED(hr = init_propvar_from_string(L"BackgroundColor", &item->id))) + { + free(item); + return hr; + } + + item->value = *value; + *ret = item; + + return S_OK; +} + +static HRESULT LoadBkgdMetadata(MetadataHandler *handler, IStream *stream, const GUID *preferred_vendor, + DWORD persist_options) +{ + MetadataItem *result; + PROPVARIANT value; + ULONG data_size; + BYTE type[4]; + HRESULT hr; + BYTE *data; + + hr = read_png_chunk(stream, type, &data, &data_size); + if (FAILED(hr)) return hr; + + PropVariantInit(&value); + if (data_size == 1) + { + value.vt = VT_UI1; + value.bVal = *data; + } + else if (data_size == 2) + { + value.vt = VT_UI2; + value.uiVal = read_ushort_be(data); + } + else if (data_size == 6) + { + value.vt = VT_UI2 | VT_VECTOR; + value.caui.cElems = 3; + if (!(value.caui.pElems = CoTaskMemAlloc(3 * sizeof(USHORT)))) + { + hr = E_OUTOFMEMORY; + } + else + { + BYTE *ptr = data; + for (int i = 0; i < value.caui.cElems; ++i, ptr += 2) + value.caui.pElems[i] = read_ushort_be(ptr); + } + } + else + { + hr = WINCODEC_ERR_BADMETADATAHEADER; + } + + free(data); + + if (SUCCEEDED(hr)) + hr = create_bkgd_item(&value, &result); + + if (FAILED(hr)) + return hr; + + MetadataHandler_FreeItems(handler); + handler->items = result; + handler->item_count = 1; + + return S_OK; +} + +static HRESULT CreateBkgdHandler(MetadataHandler *handler) +{ + MetadataItem *item; + PROPVARIANT value; + HRESULT hr; + + PropVariantInit(&value); + if (FAILED(hr = create_bkgd_item(&value, &item))) + return hr; + + handler->items = item; + handler->item_count = 1; + + return S_OK; +} + +static const MetadataHandlerVtbl BkgdReader_Vtbl = +{ + 0, + &CLSID_WICPngBkgdMetadataReader, + LoadBkgdMetadata, + CreateBkgdHandler, +}; + +HRESULT PngBkgdReader_CreateInstance(REFIID iid, void** ppv) +{ + return MetadataReader_Create(&BkgdReader_Vtbl, iid, ppv); +} + HRESULT PngDecoder_CreateInstance(REFIID iid, void** ppv) { HRESULT hr; diff --git a/dlls/windowscodecs/regsvr.c b/dlls/windowscodecs/regsvr.c index 59bc8263b7d..4e34b2cfd95 100644 --- a/dlls/windowscodecs/regsvr.c +++ b/dlls/windowscodecs/regsvr.c @@ -1813,6 +1813,21 @@ static const struct reader_containers pngtime_containers[] = { { NULL } /* list terminator */ };
+static const BYTE bKGD[] = "bKGD"; + +static const struct metadata_pattern pngbkgd_metadata_pattern[] = { + { 4, 4, bKGD, mask_all, 4 }, + { 0 } +}; + +static const struct reader_containers pngbkgd_containers[] = { + { + &GUID_ContainerFormatPng, + pngbkgd_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 }, @@ -1988,6 +2003,16 @@ static struct regsvr_metadatareader const metadatareader_list[] = { 0, 0, 0, pngtime_containers }, + { &CLSID_WICPngBkgdMetadataReader, + "The Wine Project", + "Chunk bKGD Reader", + "1.0.0.0", + "1.0.0.0", + &GUID_VendorMicrosoft, + &GUID_MetadataFormatChunkbKGD, + 0, 0, 0, + pngbkgd_containers + }, { &CLSID_WICLSDMetadataReader, "The Wine Project", "Logical Screen Descriptor Reader", diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index a7fb30bc8d3..e3386b7b0da 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -1770,9 +1770,7 @@ static void test_metadata_bKGD(void)
hr = CoCreateInstance(&CLSID_WICPngBkgdMetadataReader, NULL, CLSCTX_INPROC_SERVER, &IID_IWICMetadataReader, (void **)&reader); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (FAILED(hr)) return;
hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, &IID_IWICComponentFactory, (void **)&factory); @@ -1823,40 +1821,44 @@ static void test_metadata_bKGD(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IEnumString_Next(enum_string, 1, &str, NULL); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(!wcscmp(str, L"/bKGD"), "Unexpected query %s.\n", wine_dbgstr_w(str)); CoTaskMemFree(str); IEnumString_Release(enum_string);
PropVariantInit(&value); hr = IWICMetadataQueryReader_GetMetadataByName(query_reader, L"/bKGD", &value); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (hr == S_OK) + { + ok(value.vt == VT_UNKNOWN, "Unexpected value type %d.\n", value.vt); + hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataQueryReader, (void **)&query_reader2); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + PropVariantClear(&value);
- ok(value.vt == VT_UNKNOWN, "Unexpected value type %d.\n", value.vt); - hr = IUnknown_QueryInterface(value.punkVal, &IID_IWICMetadataQueryReader, (void **)&query_reader2); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - PropVariantClear(&value); - - hr = IWICMetadataQueryReader_GetEnumerator(query_reader2, &enum_string); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IWICMetadataQueryReader_GetEnumerator(query_reader2, &enum_string); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- str = NULL; - hr = IEnumString_Next(enum_string, 1, &str, &fetched); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(fetched == 1, "Unexpected count %lu.\n", fetched); + str = NULL; + hr = IEnumString_Next(enum_string, 1, &str, &fetched); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(fetched == 1, "Unexpected count %lu.\n", fetched);
- ok(!wcscmp(str, L"/BackgroundColor"), "Unexpected query %s.\n", wine_dbgstr_w(str)); - CoTaskMemFree(str); + ok(!wcscmp(str, L"/BackgroundColor"), "Unexpected query %s.\n", wine_dbgstr_w(str)); + CoTaskMemFree(str);
- IEnumString_Release(enum_string); + IEnumString_Release(enum_string);
- PropVariantInit(&value); - hr = IWICMetadataQueryReader_GetMetadataByName(query_reader2, L"/backgroundcolor", &value); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(value.vt == VT_UI1, "Unexpected type %d.\n", value.vt); - ok(value.bVal == 0x12, "Unexpected value %u.\n", value.bVal); - PropVariantClear(&value); + PropVariantInit(&value); + hr = IWICMetadataQueryReader_GetMetadataByName(query_reader2, L"/backgroundcolor", &value); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(value.vt == VT_UI1, "Unexpected type %d.\n", value.vt); + ok(value.bVal == 0x12, "Unexpected value %u.\n", value.bVal); + PropVariantClear(&value);
- IWICMetadataQueryReader_Release(query_reader2); + IWICMetadataQueryReader_Release(query_reader2); + }
IWICMetadataQueryReader_Release(query_reader);
@@ -1880,7 +1882,9 @@ static void test_metadata_bKGD(void)
hr = CoCreateInstance(&CLSID_WICPngBkgdMetadataWriter, NULL, CLSCTX_INPROC_SERVER, &IID_IWICMetadataWriter, (void **)&writer); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (FAILED(hr)) return;
check_interface(writer, &IID_IWICMetadataWriter, TRUE); check_interface(writer, &IID_IWICMetadataReader, TRUE); diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index 3c2bb2bcfeb..46be6f31751 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -259,6 +259,7 @@ extern HRESULT ExifMetadataReader_CreateInstance(REFIID iid, void **ppv); extern HRESULT ExifMetadataWriter_CreateInstance(REFIID iid, void **ppv); extern HRESULT App1MetadataReader_CreateInstance(REFIID iid, void **ppv); extern HRESULT App1MetadataWriter_CreateInstance(REFIID iid, void **ppv); +extern HRESULT PngBkgdReader_CreateInstance(REFIID iid, void** ppv); extern HRESULT PngChrmReader_CreateInstance(REFIID iid, void** ppv); extern HRESULT PngGamaReader_CreateInstance(REFIID iid, void** ppv); extern HRESULT PngHistReader_CreateInstance(REFIID iid, void** ppv); diff --git a/dlls/windowscodecs/windowscodecs_wincodec.idl b/dlls/windowscodecs/windowscodecs_wincodec.idl index abdbd87e87b..f182de84b0c 100644 --- a/dlls/windowscodecs/windowscodecs_wincodec.idl +++ b/dlls/windowscodecs/windowscodecs_wincodec.idl @@ -245,6 +245,13 @@ coclass WICPngTextMetadataReader { interface IWICMetadataReader; } ] coclass WICPngTimeMetadataReader { interface IWICMetadataReader; }
+[ + helpstring("WIC Png bKGD Metadata Reader"), + threading(both), + uuid(0ce7a4a6-03e8-4a60-9d15-282ef32ee7da) +] +coclass WICPngBkgdMetadataReader { interface IWICMetadataReader; } + [ helpstring("WIC LSD Metadata Reader"), threading(both),