Module: wine Branch: master Commit: 43c97b871f2e60983ed07025428effed62ec795d URL: http://source.winehq.org/git/wine.git/?a=commit;h=43c97b871f2e60983ed0702542...
Author: Vincent Povirk vincent@codeweavers.com Date: Wed Mar 25 14:26:28 2015 -0500
windowscodecs: Implement PngDecoder_Block_GetCount.
---
dlls/windowscodecs/pngformat.c | 80 +++++++++++++++++++++++++++++++++++-- dlls/windowscodecs/tests/metadata.c | 6 +-- 2 files changed, 79 insertions(+), 7 deletions(-)
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c index 260330f..53a2122 100644 --- a/dlls/windowscodecs/pngformat.c +++ b/dlls/windowscodecs/pngformat.c @@ -292,6 +292,11 @@ static void user_warning_fn(png_structp png_ptr, png_const_charp warning_message }
typedef struct { + ULARGE_INTEGER ofs, len; + IWICMetadataReader* reader; +} metadata_block_info; + +typedef struct { IWICBitmapDecoder IWICBitmapDecoder_iface; IWICBitmapFrameDecode IWICBitmapFrameDecode_iface; IWICMetadataBlockReader IWICMetadataBlockReader_iface; @@ -307,6 +312,8 @@ typedef struct { const WICPixelFormatGUID *format; BYTE *image_bits; CRITICAL_SECTION lock; /* must be held when png structures are accessed or initialized is set */ + ULONG metadata_count; + metadata_block_info* metadata_blocks; } PngDecoder;
static inline PngDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface) @@ -362,6 +369,7 @@ static ULONG WINAPI PngDecoder_Release(IWICBitmapDecoder *iface) { PngDecoder *This = impl_from_IWICBitmapDecoder(iface); ULONG ref = InterlockedDecrement(&This->ref); + ULONG i;
TRACE("(%p) refcount=%u\n", iface, ref);
@@ -373,6 +381,12 @@ static ULONG WINAPI PngDecoder_Release(IWICBitmapDecoder *iface) This->lock.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->lock); HeapFree(GetProcessHeap(), 0, This->image_bits); + for (i=0; i<This->metadata_count; i++) + { + if (This->metadata_blocks[i].reader) + IWICMetadataReader_Release(This->metadata_blocks[i].reader); + } + HeapFree(GetProcessHeap(), 0, This->metadata_blocks); HeapFree(GetProcessHeap(), 0, This); }
@@ -425,6 +439,10 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p png_uint_32 transparency; png_color_16p trans_values; jmp_buf jmpbuf; + BYTE chunk_type[4]; + ULONG chunk_size; + ULARGE_INTEGER chunk_start; + ULONG metadata_blocks_size = 0;
TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
@@ -607,13 +625,60 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
ppng_read_end(This->png_ptr, This->end_info);
+ /* Find the metadata chunks in the file. */ + seek.QuadPart = 8; + hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, &chunk_start); + if (FAILED(hr)) goto end; + + do + { + hr = read_png_chunk(pIStream, chunk_type, NULL, &chunk_size); + if (FAILED(hr)) goto end; + + if (chunk_type[0] >= 'a' && chunk_type[0] <= 'z' && + memcmp(chunk_type, "tRNS", 4) && memcmp(chunk_type, "pHYs", 4)) + { + /* This chunk is considered metadata. */ + if (This->metadata_count == metadata_blocks_size) + { + metadata_block_info* new_metadata_blocks; + ULONG new_metadata_blocks_size; + + new_metadata_blocks_size = 4 + metadata_blocks_size * 2; + new_metadata_blocks = HeapAlloc(GetProcessHeap(), 0, + new_metadata_blocks_size * sizeof(*new_metadata_blocks)); + + if (!new_metadata_blocks) + { + hr = E_OUTOFMEMORY; + goto end; + } + + memcpy(new_metadata_blocks, This->metadata_blocks, + This->metadata_count * sizeof(*new_metadata_blocks)); + + HeapFree(GetProcessHeap(), 0, This->metadata_blocks); + This->metadata_blocks = new_metadata_blocks; + metadata_blocks_size = new_metadata_blocks_size; + } + + This->metadata_blocks[This->metadata_count].ofs = chunk_start; + This->metadata_blocks[This->metadata_count].len.QuadPart = chunk_size + 12; + This->metadata_blocks[This->metadata_count].reader = NULL; + This->metadata_count++; + } + + seek.QuadPart = chunk_start.QuadPart + chunk_size + 12; /* skip data and CRC */ + hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, &chunk_start); + if (FAILED(hr)) goto end; + } while (memcmp(chunk_type, "IEND", 4)); + This->stream = pIStream; IStream_AddRef(This->stream);
This->initialized = TRUE;
end: - LeaveCriticalSection(&This->lock);
return hr; @@ -983,10 +1048,15 @@ static HRESULT WINAPI PngDecoder_Block_GetContainerFormat(IWICMetadataBlockReade static HRESULT WINAPI PngDecoder_Block_GetCount(IWICMetadataBlockReader *iface, UINT *pcCount) { - static int once; + PngDecoder *This = impl_from_IWICMetadataBlockReader(iface); + TRACE("%p,%p\n", iface, pcCount); - if (!once++) FIXME("stub\n"); - return E_NOTIMPL; + + if (!pcCount) return E_INVALIDARG; + + *pcCount = This->metadata_count; + + return S_OK; }
static HRESULT WINAPI PngDecoder_Block_GetReaderByIndex(IWICMetadataBlockReader *iface, @@ -1042,6 +1112,8 @@ HRESULT PngDecoder_CreateInstance(REFIID iid, void** ppv) This->image_bits = NULL; InitializeCriticalSection(&This->lock); This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PngDecoder.lock"); + This->metadata_count = 0; + This->metadata_blocks = NULL;
ret = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv); IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface); diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c index 20fe54c..1a7587f 100644 --- a/dlls/windowscodecs/tests/metadata.c +++ b/dlls/windowscodecs/tests/metadata.c @@ -946,11 +946,11 @@ static void test_metadata_png(void) ok(IsEqualGUID(&containerformat, &GUID_ContainerFormatPng), "unexpected container format\n");
hr = IWICMetadataBlockReader_GetCount(blockreader, NULL); - todo_wine ok(hr == E_INVALIDARG, "GetCount failed, hr=%x\n", hr); + ok(hr == E_INVALIDARG, "GetCount failed, hr=%x\n", hr);
hr = IWICMetadataBlockReader_GetCount(blockreader, &count); - todo_wine ok(hr == S_OK, "GetCount failed, hr=%x\n", hr); - todo_wine ok(count == 1, "unexpected count %d\n", count); + ok(hr == S_OK, "GetCount failed, hr=%x\n", hr); + ok(count == 1, "unexpected count %d\n", count);
if (0) {