From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/windowscodecs/imgfactory.c | 89 +++++++++++++++++++++++++- dlls/windowscodecs/metadatahandler.c | 2 +- dlls/windowscodecs/tests/metadata.c | 37 ++++++++--- dlls/windowscodecs/wincodecs_private.h | 2 + 4 files changed, 116 insertions(+), 14 deletions(-)
diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c index e0b863f5cd4..9316beedb04 100644 --- a/dlls/windowscodecs/imgfactory.c +++ b/dlls/windowscodecs/imgfactory.c @@ -1623,10 +1623,93 @@ static HRESULT WINAPI ComponentFactory_CreateMetadataWriter(IWICComponentFactory }
static HRESULT WINAPI ComponentFactory_CreateMetadataWriterFromReader(IWICComponentFactory *iface, - IWICMetadataReader *reader, const GUID *vendor, IWICMetadataWriter **writer) + IWICMetadataReader *reader, const GUID *vendor, IWICMetadataWriter **out_writer) { - FIXME("%p,%p,%s,%p: stub\n", iface, reader, debugstr_guid(vendor), writer); - return E_NOTIMPL; + IWICStreamProvider *stream_provider = NULL; + IWICMetadataWriter *writer = NULL; + IStream *stream = NULL; + DWORD options = 0; + GUID format; + HRESULT hr; + + TRACE("%p,%p,%s,%p\n", iface, reader, debugstr_guid(vendor), out_writer); + + if (!reader || !out_writer) + return E_INVALIDARG; + + hr = IWICMetadataReader_GetMetadataFormat(reader, &format); + + if (SUCCEEDED(hr)) + hr = create_metadata_writer(&format, vendor, 0, &writer); + + if (SUCCEEDED(hr)) + hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICStreamProvider, (void **)&stream_provider); + + if (SUCCEEDED(hr)) + { + IStream *cached_stream = NULL; + + hr = IWICStreamProvider_GetStream(stream_provider, &cached_stream); + + /* Reader does not have to provide a stream. */ + if (hr == WINCODEC_ERR_STREAMNOTAVAILABLE) + { + hr = S_OK; + } + + if (cached_stream) + { + hr = create_stream_wrapper(cached_stream, 0, &stream); + IStream_Release(cached_stream); + } + } + + if (SUCCEEDED(hr)) + hr = IWICStreamProvider_GetPersistOptions(stream_provider, &options); + + if (SUCCEEDED(hr)) + { + if (stream) + { + IWICPersistStream *persist_stream; + + /* TODO: probably need to check for a dirty stream */ + + if (SUCCEEDED(hr = IWICMetadataWriter_QueryInterface(writer, &IID_IWICPersistStream, (void **)&persist_stream))) + { + hr = IWICPersistStream_LoadEx(persist_stream, stream, vendor, options); + IWICPersistStream_Release(persist_stream); + } + } + else + { + UINT count; + + hr = IWICMetadataReader_GetCount(reader, &count); + + if (SUCCEEDED(hr)) + { + if (count) + FIXME("Copy metadata items to the writer.\n"); + } + } + } + + if (stream_provider) + IWICStreamProvider_Release(stream_provider); + + if (SUCCEEDED(hr)) + { + *out_writer = writer; + IWICMetadataWriter_AddRef(*out_writer); + } + + if (writer) + IWICMetadataWriter_Release(writer); + if (stream) + IStream_Release(stream); + + return hr; }
static HRESULT WINAPI ComponentFactory_CreateQueryReaderFromBlockReader(IWICComponentFactory *iface, diff --git a/dlls/windowscodecs/metadatahandler.c b/dlls/windowscodecs/metadatahandler.c index 7e00f678e4e..71f81900395 100644 --- a/dlls/windowscodecs/metadatahandler.c +++ b/dlls/windowscodecs/metadatahandler.c @@ -847,7 +847,7 @@ static int tag_to_vt(SHORT tag) return (tag > 0 && tag <= 13) ? tag2vt[tag] : VT_BLOB; }
-static HRESULT create_stream_wrapper(IStream *input, ULONG offset, IStream **wrapper) +HRESULT create_stream_wrapper(IStream *input, ULONG offset, IStream **wrapper) { ULARGE_INTEGER start, maxsize; IWICStream *wic_stream = NULL; diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 9ad9e38372c..7904547114b 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -4111,6 +4111,7 @@ static void test_metadata_App1(void)
hr = get_persist_stream(ifd_reader, &stream2); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_interface(stream2, &IID_IWICStream, TRUE); ok(!!stream2 && app1_stream != stream2, "Unexpected stream.\n"); IStream_Release(stream2);
@@ -4158,6 +4159,7 @@ static void test_metadata_App1(void)
hr = get_persist_stream(exif_reader, &stream2); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_interface(stream2, &IID_IWICStream, TRUE); ok(!!stream2 && stream2 != app1_stream, "Unexpected stream.\n"); IStream_Release(stream2);
@@ -4195,6 +4197,7 @@ static void test_metadata_App1(void)
hr = get_persist_stream(gps_reader, &stream2); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_interface(stream2, &IID_IWICStream, TRUE); ok(!!stream2 && stream2 != app1_stream, "Unexpected stream.\n"); IStream_Release(stream2);
@@ -4256,14 +4259,7 @@ static void test_CreateMetadataWriterFromReader(void) check_persist_options(reader, 0);
hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, reader, NULL, &writer); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (FAILED(hr)) - { - IWICMetadataReader_Release(reader); - IWICComponentFactory_Release(factory); - return; - }
IWICMetadataReader_Release(reader);
@@ -4276,7 +4272,6 @@ static void test_CreateMetadataWriterFromReader(void) NULL, 0, stream, &reader); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); check_persist_options(reader, 0); - IStream_Release(stream);
hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, NULL, NULL, NULL); ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); @@ -4309,6 +4304,7 @@ static void test_CreateMetadataWriterFromReader(void)
hr = IWICMetadataWriter_GetMetadataFormat(writer, &format); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(IsEqualGUID(&format, &GUID_MetadataFormatChunktEXt), "Unexpected format %s.\n", wine_dbgstr_guid(&format));
hr = IWICMetadataWriter_GetCount(writer, &count); @@ -4319,15 +4315,26 @@ static void test_CreateMetadataWriterFromReader(void) PropVariantInit(&value); hr = IWICMetadataWriter_GetValueByIndex(writer, 0, NULL, &id, &value); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(id.vt == VT_LPSTR, "Unexpected id type %u.\n", id.vt); - ok(!strcmp(id.pszVal, "winetest"), "Unexpected id %s.\n", wine_dbgstr_a(id.pszVal)); + if (id.vt == VT_LPSTR) + ok(!strcmp(id.pszVal, "winetest"), "Unexpected id %s.\n", wine_dbgstr_a(id.pszVal)); + todo_wine ok(value.vt == VT_LPSTR, "Unexpected value type %u.\n", value.vt); - ok(!strcmp(value.pszVal, "value"), "Unexpected value %s.\n", wine_dbgstr_a(value.pszVal)); + if (value.vt == VT_LPSTR) + ok(!strcmp(value.pszVal, "value"), "Unexpected value %s.\n", wine_dbgstr_a(value.pszVal)); PropVariantClear(&id); PropVariantClear(&value);
+ hr = get_persist_stream(writer, &stream2); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(stream2 != stream, "Unexpected stream.\n"); + check_interface(stream2, &IID_IWICStream, TRUE); + IStream_Release(stream2); + IWICMetadataWriter_Release(writer); IWICMetadataReader_Release(reader); + IStream_Release(stream);
/* App1 reader */ stream = create_stream((const char *)&app1_data, sizeof(app1_data)); @@ -4378,6 +4385,7 @@ static void test_CreateMetadataWriterFromReader(void) hr = get_persist_stream(writer, &stream2); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(stream2 != stream, "Unexpected stream.\n"); + check_interface(stream2, &IID_IWICStream, TRUE); IStream_Release(stream2);
IWICMetadataWriter_Release(writer); @@ -4397,9 +4405,18 @@ static void test_CreateMetadataWriterFromReader(void) check_persist_options(reader, WICPersistOptionBigEndian); free(data);
+ hr = IWICMetadataReader_GetMetadataFormat(reader, &format); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(IsEqualGUID(&format, &GUID_MetadataFormatIfd), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); + hr = IWICComponentFactory_CreateMetadataWriterFromReader(factory, reader, NULL, &writer); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); check_persist_options(writer, WICPersistOptionBigEndian); + + hr = IWICMetadataWriter_GetMetadataFormat(writer, &format); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(IsEqualGUID(&format, &GUID_MetadataFormatIfd), "Unexpected format %s.\n", wine_dbgstr_guid(&format)); + IWICMetadataWriter_Release(writer);
IWICMetadataReader_Release(reader); diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index bbdb4c36f73..9858a1fdebb 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -164,6 +164,8 @@ extern HRESULT ColorContext_Create(IWICColorContext **context); extern HRESULT ColorTransform_Create(IWICColorTransform **transform); extern HRESULT BitmapClipper_Create(IWICBitmapClipper **clipper);
+extern HRESULT create_stream_wrapper(IStream *input, ULONG offset, IStream **wrapper); + extern HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer, UINT srcwidth, UINT srcheight, INT srcstride, const WICRect *rc, UINT dststride, UINT dstbuffersize, BYTE *dstbuffer);