Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
-- v2: windowscodecs/metadata: Implement bKGD chunk reader. windowscodecs/metadata: Add default item for the GifComment handler. windowscodecs/tests: Add more tests for initial reader contents. windowscodecs/metadata: Create default items for the tIME handler. windowscodecs/metadata: Create default item for the hIST handler. windowscodecs/metadata: Create default items for the cHRM handler.
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/metadatahandler.c | 2 +- dlls/windowscodecs/pngformat.c | 97 ++++++++++++++++---------- dlls/windowscodecs/tests/metadata.c | 3 - dlls/windowscodecs/wincodecs_private.h | 1 + 4 files changed, 63 insertions(+), 40 deletions(-)
diff --git a/dlls/windowscodecs/metadatahandler.c b/dlls/windowscodecs/metadatahandler.c index d087a0640d7..2e12d815943 100644 --- a/dlls/windowscodecs/metadatahandler.c +++ b/dlls/windowscodecs/metadatahandler.c @@ -48,7 +48,7 @@ static inline MetadataHandler *impl_from_IWICStreamProvider(IWICStreamProvider * return CONTAINING_RECORD(iface, MetadataHandler, IWICStreamProvider_iface); }
-static void clear_metadata_item(MetadataItem *item) +void clear_metadata_item(MetadataItem *item) { PropVariantClear(&item->schema); PropVariantClear(&item->id); diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c index ebf8e1477d7..7a1c72b231f 100644 --- a/dlls/windowscodecs/pngformat.c +++ b/dlls/windowscodecs/pngformat.c @@ -191,14 +191,10 @@ HRESULT PngGamaReader_CreateInstance(REFIID iid, void** ppv) return MetadataReader_Create(&GamaReader_Vtbl, iid, ppv); }
-static HRESULT LoadChrmMetadata(MetadataHandler *handler, IStream *stream, const GUID *preferred_vendor, - DWORD persist_options) +static HRESULT create_chrm_items(const ULONG *values, MetadataItem **ret) { - HRESULT hr; - BYTE type[4]; - BYTE *data; - ULONG data_size; - static const WCHAR names[8][12] = { + static const WCHAR *names[8] = + { L"WhitePointX", L"WhitePointY", L"RedX", @@ -208,8 +204,43 @@ static HRESULT LoadChrmMetadata(MetadataHandler *handler, IStream *stream, const L"BlueX", L"BlueY", }; - LPWSTR dyn_names[8] = {0}; + MetadataItem *items; + HRESULT hr = S_OK; + + if (!(items = calloc(ARRAY_SIZE(names), sizeof(*items)))) + return E_OUTOFMEMORY; + + for (int i = 0; i < ARRAY_SIZE(names); ++i) + { + if (FAILED(hr = init_propvar_from_string(names[i], &items[i].id))) + break; + + items[i].value.vt = VT_UI4; + items[i].value.ulVal = values[i]; + } + + if (FAILED(hr)) + { + for (int i = 0; i < ARRAY_SIZE(names); ++i) + clear_metadata_item(&items[i]); + free(items); + items = NULL; + } + + *ret = items; + + return hr; +} + +static HRESULT LoadChrmMetadata(MetadataHandler *handler, IStream *stream, const GUID *preferred_vendor, + DWORD persist_options) +{ + HRESULT hr; + BYTE type[4]; + BYTE *data; + ULONG data_size; MetadataItem *result; + ULONG values[8]; int i;
hr = read_png_chunk(stream, type, &data, &data_size); @@ -221,39 +252,32 @@ static HRESULT LoadChrmMetadata(MetadataHandler *handler, IStream *stream, const return E_FAIL; }
- result = calloc(8, sizeof(MetadataItem)); - for (i=0; i<8; i++) - { - SHStrDupW(names[i], &dyn_names[i]); - if (!dyn_names[i]) break; - } - if (!result || i < 8) - { - free(result); - for (i=0; i<8; i++) - CoTaskMemFree(dyn_names[i]); - free(data); - return E_OUTOFMEMORY; - } - - for (i=0; i<8; i++) - { - PropVariantInit(&result[i].schema); + for (i = 0; i < ARRAY_SIZE(values); ++i) + values[i] = read_ulong_be(&data[i*4]);
- PropVariantInit(&result[i].id); - result[i].id.vt = VT_LPWSTR; - result[i].id.pwszVal = dyn_names[i]; + free(data);
- PropVariantInit(&result[i].value); - result[i].value.vt = VT_UI4; - result[i].value.ulVal = read_ulong_be(&data[i*4]); - } + if (FAILED(hr = create_chrm_items(values, &result))) + return hr;
MetadataHandler_FreeItems(handler); handler->items = result; - handler->item_count = 8; + handler->item_count = ARRAY_SIZE(values);
- free(data); + return S_OK; +} + +static HRESULT CreateChrmHandler(MetadataHandler *handler) +{ + const ULONG values[8] = { 31270, 32900, 64000, 33000, 30000, 60000, 15000, 6000 }; + MetadataItem *items; + HRESULT hr; + + if (FAILED(hr = create_chrm_items(values, &items))) + return hr; + + handler->items = items; + handler->item_count = ARRAY_SIZE(values);
return S_OK; } @@ -261,7 +285,8 @@ static HRESULT LoadChrmMetadata(MetadataHandler *handler, IStream *stream, const static const MetadataHandlerVtbl ChrmReader_Vtbl = { 0, &CLSID_WICPngChrmMetadataReader, - LoadChrmMetadata + LoadChrmMetadata, + CreateChrmHandler, };
HRESULT PngChrmReader_CreateInstance(REFIID iid, void** ppv) diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index af8c1d94480..54fe37345b7 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -1328,7 +1328,6 @@ static void test_metadata_cHRM(void)
hr = IWICMetadataReader_GetCount(reader, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(count == 8, "unexpected count %i.\n", count);
for (i = 0; i < count; ++i) @@ -1347,13 +1346,11 @@ static void test_metadata_cHRM(void) id.vt = VT_LPSTR; id.pszVal = (char *)"RedX"; hr = IWICMetadataReader_GetValue(reader, NULL, &id, NULL); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
id.vt = VT_LPSTR; id.pszVal = (char *)"REDX"; hr = IWICMetadataReader_GetValue(reader, NULL, &id, NULL); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
id.vt = VT_UI2; diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index 71c011e4e6f..3c2bb2bcfeb 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -247,6 +247,7 @@ typedef struct MetadataHandler
extern HRESULT MetadataReader_Create(const MetadataHandlerVtbl *vtable, REFIID iid, void** ppv); extern void MetadataHandler_FreeItems(MetadataHandler *handler); +extern void clear_metadata_item(MetadataItem *item);
extern HRESULT UnknownMetadataReader_CreateInstance(REFIID iid, void** ppv); extern HRESULT UnknownMetadataWriter_CreateInstance(REFIID iid, void** ppv);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/pngformat.c | 55 ++++++++++++++++++++--------- dlls/windowscodecs/tests/metadata.c | 9 ++++- 2 files changed, 46 insertions(+), 18 deletions(-)
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c index 7a1c72b231f..91a9ee0de22 100644 --- a/dlls/windowscodecs/pngformat.c +++ b/dlls/windowscodecs/pngformat.c @@ -294,6 +294,27 @@ HRESULT PngChrmReader_CreateInstance(REFIID iid, void** ppv) return MetadataReader_Create(&ChrmReader_Vtbl, iid, ppv); }
+static HRESULT create_hist_item(USHORT *data, ULONG count, MetadataItem **item) +{ + HRESULT hr; + + if (!(*item = calloc(1, sizeof(**item)))) + return E_OUTOFMEMORY; + + hr = init_propvar_from_string(L"Frequencies", &(*item)->id); + if (FAILED(hr)) + { + free(*item); + return hr; + } + + (*item)->value.vt = VT_UI2 | VT_VECTOR; + (*item)->value.caui.cElems = count; + (*item)->value.caui.pElems = data; + + return S_OK; +} + static HRESULT LoadHistMetadata(MetadataHandler *handler, IStream *stream, const GUID *preferred_vendor, DWORD persist_options) { @@ -301,7 +322,6 @@ static HRESULT LoadHistMetadata(MetadataHandler *handler, IStream *stream, const BYTE type[4]; BYTE *data; ULONG data_size, element_count, i; - LPWSTR name; MetadataItem *result; USHORT *elements;
@@ -320,28 +340,28 @@ static HRESULT LoadHistMetadata(MetadataHandler *handler, IStream *stream, const
free(data);
- result = calloc(1, sizeof(MetadataItem)); - SHStrDupW(L"Frequencies", &name); - if (!result || !name) { - free(result); - CoTaskMemFree(name); + if (FAILED(hr = create_hist_item(elements, element_count, &result))) + { CoTaskMemFree(elements); return E_OUTOFMEMORY; }
- PropVariantInit(&result[0].schema); - PropVariantInit(&result[0].id); - PropVariantInit(&result[0].value); + MetadataHandler_FreeItems(handler); + handler->items = result; + handler->item_count = 1; + + return S_OK; +}
- result[0].id.vt = VT_LPWSTR; - result[0].id.pwszVal = name; +static HRESULT CreateHistHandler(MetadataHandler *handler) +{ + MetadataItem *item; + HRESULT hr;
- result[0].value.vt = VT_UI2|VT_VECTOR; - result[0].value.caui.cElems = element_count; - result[0].value.caui.pElems = elements; + if (FAILED(hr = create_hist_item(NULL, 0, &item))) + return hr;
- MetadataHandler_FreeItems(handler); - handler->items = result; + handler->items = item; handler->item_count = 1;
return S_OK; @@ -350,7 +370,8 @@ static HRESULT LoadHistMetadata(MetadataHandler *handler, IStream *stream, const static const MetadataHandlerVtbl HistReader_Vtbl = { 0, &CLSID_WICPngHistMetadataReader, - LoadHistMetadata + LoadHistMetadata, + CreateHistHandler, };
HRESULT PngHistReader_CreateInstance(REFIID iid, void** ppv) diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 54fe37345b7..f8f440ea658 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -1484,9 +1484,15 @@ static void test_metadata_hIST(void)
hr = IWICMetadataReader_GetCount(reader, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(count == 1, "Unexpected count %u.\n", count);
+ PropVariantInit(&value); + hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, &value); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(value.vt == (VT_UI2|VT_VECTOR), "Unexpected value type %u.\n", value.vt); + ok(!value.caui.cElems, "Unexpected cElems %lu.\n", value.caub.cElems); + ok(!value.caui.pElems, "Unexpected value %p.\n", value.caui.pElems); + load_stream(reader, metadata_hIST, sizeof(metadata_hIST), WICPersistOptionDefault);
hr = IWICMetadataReader_GetMetadataFormat(reader, &format); @@ -1497,6 +1503,7 @@ static void test_metadata_hIST(void) ok(hr == S_OK, "GetCount failed, hr=%lx\n", hr); ok(count == 1, "unexpected count %i\n", count);
+ PropVariantInit(&value); hr = IWICMetadataReader_GetValueByIndex(reader, 0, &schema, &id, &value); ok(hr == S_OK, "GetValue failed, hr=%lx\n", hr);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/pngformat.c | 128 ++++++++++++++++++---------- dlls/windowscodecs/tests/metadata.c | 6 +- 2 files changed, 85 insertions(+), 49 deletions(-)
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c index 91a9ee0de22..2e344c3da2d 100644 --- a/dlls/windowscodecs/pngformat.c +++ b/dlls/windowscodecs/pngformat.c @@ -379,14 +379,18 @@ HRESULT PngHistReader_CreateInstance(REFIID iid, void** ppv) return MetadataReader_Create(&HistReader_Vtbl, iid, ppv); }
-static HRESULT LoadTimeMetadata(MetadataHandler *handler, IStream *stream, const GUID *preferred_vendor, - DWORD persist_options) +struct time_data +{ + USHORT year; + BYTE month; + BYTE day; + BYTE hour; + BYTE minute; + BYTE second; +}; + +static HRESULT create_time_items(const struct time_data *data, MetadataItem **ret) { - HRESULT hr; - BYTE type[4]; - BYTE *data; - ULONG data_size, i; - MetadataItem *result; static const WCHAR *names[6] = { L"Year", @@ -396,61 +400,96 @@ static HRESULT LoadTimeMetadata(MetadataHandler *handler, IStream *stream, const L"Minute", L"Second", }; - LPWSTR id_values[6] = {0}; + MetadataItem *items; + HRESULT hr = S_OK;
+ if (!(items = calloc(ARRAY_SIZE(names), sizeof(*items)))) + return E_OUTOFMEMORY;
- hr = read_png_chunk(stream, type, &data, &data_size); - if (FAILED(hr)) return hr; + for (int i = 0; i < ARRAY_SIZE(names); ++i) + { + if (FAILED(hr = init_propvar_from_string(names[i], &items[i].id))) + break; + }
- if (data_size != 7) + if (SUCCEEDED(hr)) { - free(data); - return E_FAIL; + items[0].value.vt = VT_UI2; + items[0].value.uiVal = data->year; + items[1].value.vt = VT_UI1; + items[1].value.bVal = data->month; + items[2].value.vt = VT_UI1; + items[2].value.bVal = data->day; + items[3].value.vt = VT_UI1; + items[3].value.bVal = data->hour; + items[4].value.vt = VT_UI1; + items[4].value.bVal = data->minute; + items[5].value.vt = VT_UI1; + items[5].value.bVal = data->second; }
- result = calloc(6, sizeof(MetadataItem)); - for (i = 0; i < 6; i++) + if (FAILED(hr)) { - SHStrDupW(names[i], &id_values[i]); - if (!id_values[i]) break; + for (int i = 0; i < ARRAY_SIZE(names); ++i) + clear_metadata_item(&items[i]); + free(items); + items = NULL; } - if (!result || i < 6) + + *ret = items; + + return hr; +} + +static HRESULT LoadTimeMetadata(MetadataHandler *handler, IStream *stream, const GUID *preferred_vendor, + DWORD persist_options) +{ + HRESULT hr; + BYTE type[4]; + BYTE *data; + ULONG data_size; + MetadataItem *result; + struct time_data time_data; + + hr = read_png_chunk(stream, type, &data, &data_size); + if (FAILED(hr)) return hr; + + if (data_size != 7) { - free(result); - for (i = 0; i < 6; i++) - CoTaskMemFree(id_values[i]); free(data); - return E_OUTOFMEMORY; + return E_FAIL; }
- for (i = 0; i < 6; i++) - { - PropVariantInit(&result[i].schema); - PropVariantInit(&result[i].id); - PropVariantInit(&result[i].value); + time_data.year = read_ushort_be(data); + time_data.month = data[2]; + time_data.day = data[3]; + time_data.hour = data[4]; + time_data.minute = data[5]; + time_data.second = data[6];
- result[i].id.vt = VT_LPWSTR; - result[i].id.pwszVal = id_values[i]; - } + free(data);
- result[0].value.vt = VT_UI2; - result[0].value.uiVal = read_ushort_be(data); - result[1].value.vt = VT_UI1; - result[1].value.bVal = data[2]; - result[2].value.vt = VT_UI1; - result[2].value.bVal = data[3]; - result[3].value.vt = VT_UI1; - result[3].value.bVal = data[4]; - result[4].value.vt = VT_UI1; - result[4].value.bVal = data[5]; - result[5].value.vt = VT_UI1; - result[5].value.bVal = data[6]; + if (FAILED(hr = create_time_items(&time_data, &result))) + return hr;
MetadataHandler_FreeItems(handler); handler->items = result; handler->item_count = 6;
- free(data); + return S_OK; +} + +static HRESULT CreateTimeHandler(MetadataHandler *handler) +{ + static const struct time_data time_data = { .month = 1, .day = 1 }; + MetadataItem *items; + HRESULT hr; + + if (FAILED(hr = create_time_items(&time_data, &items))) + return hr; + + handler->items = items; + handler->item_count = 6;
return S_OK; } @@ -458,7 +497,8 @@ static HRESULT LoadTimeMetadata(MetadataHandler *handler, IStream *stream, const static const MetadataHandlerVtbl TimeReader_Vtbl = { 0, &CLSID_WICPngTimeMetadataReader, - LoadTimeMetadata + LoadTimeMetadata, + CreateTimeHandler, };
HRESULT PngTimeReader_CreateInstance(REFIID iid, void** ppv) diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index f8f440ea658..793516312b1 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -1620,19 +1620,15 @@ static void test_metadata_tIME(void)
hr = IWICMetadataReader_GetCount(reader, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(count == ARRAY_SIZE(td), "unexpected count %i\n", count); compare_metadata(reader, default_data, count);
id.vt = VT_EMPTY; hr = IWICMetadataReader_GetValueByIndex(reader, 2, NULL, &id, NULL); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (hr == S_OK) - ok(!lstrcmpW(id.pwszVal, L"Day"), "Unexpected id %s.\n", debugstr_w(id.pwszVal)); + ok(!lstrcmpW(id.pwszVal, L"Day"), "Unexpected id %s.\n", debugstr_w(id.pwszVal));
hr = IWICMetadataReader_GetValue(reader, NULL, &id, NULL); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); PropVariantClear(&id);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/tests/metadata.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 793516312b1..478cbfaa2b3 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -3550,6 +3550,10 @@ static void test_metadata_IMD(void)
test_reader_container_format(reader, &GUID_ContainerFormatGif);
+ hr = IWICMetadataReader_GetCount(reader, &count); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!count, "Unexpected count %u.\n", count); + stream = create_stream(IMD_data, sizeof(IMD_data));
pos.QuadPart = 12; @@ -3676,6 +3680,13 @@ static void test_metadata_GCE(void)
test_reader_container_format(reader, &GUID_ContainerFormatGif);
+ hr = IWICMetadataReader_GetCount(reader, &count); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine + ok(count == 5, "Unexpected count %u.\n", count); + if (count == 5) + compare_metadata(reader, default_data, count); + stream = create_stream(GCE_data, sizeof(GCE_data));
pos.QuadPart = 12; @@ -3809,6 +3820,13 @@ static void test_metadata_APE(void)
test_reader_container_format(reader, &GUID_ContainerFormatGif);
+ hr = IWICMetadataReader_GetCount(reader, &count); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine + ok(count == 2, "Unexpected count %u.\n", count); + if (count == 2) + compare_metadata(reader, default_data, count); + stream = create_stream(APE_data, sizeof(APE_data));
hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist);
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/gifformat.c | 59 ++++++++++++++++++++++------- dlls/windowscodecs/tests/metadata.c | 11 ++---- 2 files changed, 49 insertions(+), 21 deletions(-)
diff --git a/dlls/windowscodecs/gifformat.c b/dlls/windowscodecs/gifformat.c index d3d8678e9f8..22be9e7deda 100644 --- a/dlls/windowscodecs/gifformat.c +++ b/dlls/windowscodecs/gifformat.c @@ -420,6 +420,26 @@ HRESULT APEReader_CreateInstance(REFIID iid, void **ppv) return MetadataReader_Create(&APEReader_Vtbl, iid, ppv); }
+static HRESULT create_gifcomment_item(char *data, MetadataItem **item) +{ + HRESULT hr; + + if (!(*item = calloc(1, sizeof(**item)))) + return E_OUTOFMEMORY; + + hr = init_propvar_from_string(L"TextEntry", &(*item)->id); + if (FAILED(hr)) + { + free(*item); + return hr; + } + + (*item)->value.vt = VT_LPSTR; + (*item)->value.pszVal = data; + + return S_OK; +} + static HRESULT load_GifComment_metadata(MetadataHandler *handler, IStream *stream, const GUID *vendor, DWORD options) { #include "pshpack1.h" @@ -477,22 +497,12 @@ static HRESULT load_GifComment_metadata(MetadataHandler *handler, IStream *strea
data[data_size] = 0;
- result = calloc(1, sizeof(MetadataItem)); - if (!result) + if (FAILED(hr = create_gifcomment_item(data, &result))) { CoTaskMemFree(data); - return E_OUTOFMEMORY; + return hr; }
- PropVariantInit(&result->schema); - PropVariantInit(&result->id); - PropVariantInit(&result->value); - - result->id.vt = VT_LPWSTR; - SHStrDupW(L"TextEntry", &result->id.pwszVal); - result->value.vt = VT_LPSTR; - result->value.pszVal = data; - MetadataHandler_FreeItems(handler); handler->items = result; handler->item_count = 1; @@ -500,10 +510,33 @@ static HRESULT load_GifComment_metadata(MetadataHandler *handler, IStream *strea return S_OK; }
+static HRESULT CreateGifCommentHandler(MetadataHandler *handler) +{ + MetadataItem *item; + char *data; + HRESULT hr; + + if (!(data = CoTaskMemAlloc(1))) + return E_OUTOFMEMORY; + *data = 0; + + if (FAILED(hr = create_gifcomment_item(data, &item))) + { + CoTaskMemFree(data); + return hr; + } + + handler->items = item; + handler->item_count = 1; + + return S_OK; +} + static const MetadataHandlerVtbl GifCommentReader_Vtbl = { 0, &CLSID_WICGifCommentMetadataReader, - load_GifComment_metadata + load_GifComment_metadata, + CreateGifCommentHandler, };
HRESULT GifCommentReader_CreateInstance(REFIID iid, void **ppv) diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 478cbfaa2b3..a7fb30bc8d3 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -3971,7 +3971,6 @@ static void test_metadata_GIF_comment(void)
hr = IWICMetadataReader_GetCount(reader, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(count == 1, "Unexpected count %u.\n", count);
for (i = 0; i < count; ++i) @@ -3993,14 +3992,10 @@ static void test_metadata_GIF_comment(void) id.pwszVal = (WCHAR *)L"TextEntry";
hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (hr == S_OK) - { - ok(value.vt == VT_LPSTR, "Unexpected vt %i.\n", value.vt); - ok(!strcmp(value.pszVal, ""), "Unexpected value: %s\n", value.pszVal); - PropVariantClear(&value); - } + ok(value.vt == VT_LPSTR, "Unexpected vt %i.\n", value.vt); + ok(!strcmp(value.pszVal, ""), "Unexpected value: %s\n", value.pszVal); + PropVariantClear(&value);
stream = create_stream(GIF_comment_data, sizeof(GIF_comment_data));
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),
Esme Povirk (@madewokherd) commented about dlls/windowscodecs/pngformat.c:
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);
I think if this fails, it doesn't take ownership of `value`, and `value` will need to be freed.