Vincent Povirk : windowscodecs: Implement PngDecoder_Block_GetCount.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Mar 30 10:12:59 CDT 2015
Module: wine
Branch: master
Commit: 43c97b871f2e60983ed07025428effed62ec795d
URL: http://source.winehq.org/git/wine.git/?a=commit;h=43c97b871f2e60983ed07025428effed62ec795d
Author: Vincent Povirk <vincent at 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)
{
More information about the wine-cvs
mailing list