windowscodecs: Implement PngDecoder_Block_GetCount.

This commit is contained in:
Vincent Povirk 2015-03-25 14:26:28 -05:00 committed by Alexandre Julliard
parent 292d7bdf0f
commit 43c97b871f
2 changed files with 79 additions and 7 deletions

View File

@ -291,6 +291,11 @@ static void user_warning_fn(png_structp png_ptr, png_const_charp warning_message
WARN("PNG warning: %s\n", debugstr_a(warning_message)); WARN("PNG warning: %s\n", debugstr_a(warning_message));
} }
typedef struct {
ULARGE_INTEGER ofs, len;
IWICMetadataReader* reader;
} metadata_block_info;
typedef struct { typedef struct {
IWICBitmapDecoder IWICBitmapDecoder_iface; IWICBitmapDecoder IWICBitmapDecoder_iface;
IWICBitmapFrameDecode IWICBitmapFrameDecode_iface; IWICBitmapFrameDecode IWICBitmapFrameDecode_iface;
@ -307,6 +312,8 @@ typedef struct {
const WICPixelFormatGUID *format; const WICPixelFormatGUID *format;
BYTE *image_bits; BYTE *image_bits;
CRITICAL_SECTION lock; /* must be held when png structures are accessed or initialized is set */ CRITICAL_SECTION lock; /* must be held when png structures are accessed or initialized is set */
ULONG metadata_count;
metadata_block_info* metadata_blocks;
} PngDecoder; } PngDecoder;
static inline PngDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface) 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); PngDecoder *This = impl_from_IWICBitmapDecoder(iface);
ULONG ref = InterlockedDecrement(&This->ref); ULONG ref = InterlockedDecrement(&This->ref);
ULONG i;
TRACE("(%p) refcount=%u\n", iface, ref); TRACE("(%p) refcount=%u\n", iface, ref);
@ -373,6 +381,12 @@ static ULONG WINAPI PngDecoder_Release(IWICBitmapDecoder *iface)
This->lock.DebugInfo->Spare[0] = 0; This->lock.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->lock); DeleteCriticalSection(&This->lock);
HeapFree(GetProcessHeap(), 0, This->image_bits); 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); HeapFree(GetProcessHeap(), 0, This);
} }
@ -425,6 +439,10 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
png_uint_32 transparency; png_uint_32 transparency;
png_color_16p trans_values; png_color_16p trans_values;
jmp_buf jmpbuf; 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); 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); 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; This->stream = pIStream;
IStream_AddRef(This->stream); IStream_AddRef(This->stream);
This->initialized = TRUE; This->initialized = TRUE;
end: end:
LeaveCriticalSection(&This->lock); LeaveCriticalSection(&This->lock);
return hr; return hr;
@ -983,10 +1048,15 @@ static HRESULT WINAPI PngDecoder_Block_GetContainerFormat(IWICMetadataBlockReade
static HRESULT WINAPI PngDecoder_Block_GetCount(IWICMetadataBlockReader *iface, static HRESULT WINAPI PngDecoder_Block_GetCount(IWICMetadataBlockReader *iface,
UINT *pcCount) UINT *pcCount)
{ {
static int once; PngDecoder *This = impl_from_IWICMetadataBlockReader(iface);
TRACE("%p,%p\n", iface, pcCount); 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, static HRESULT WINAPI PngDecoder_Block_GetReaderByIndex(IWICMetadataBlockReader *iface,
@ -1042,6 +1112,8 @@ HRESULT PngDecoder_CreateInstance(REFIID iid, void** ppv)
This->image_bits = NULL; This->image_bits = NULL;
InitializeCriticalSection(&This->lock); InitializeCriticalSection(&This->lock);
This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PngDecoder.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); ret = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv);
IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface); IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);

View File

@ -946,11 +946,11 @@ static void test_metadata_png(void)
ok(IsEqualGUID(&containerformat, &GUID_ContainerFormatPng), "unexpected container format\n"); ok(IsEqualGUID(&containerformat, &GUID_ContainerFormatPng), "unexpected container format\n");
hr = IWICMetadataBlockReader_GetCount(blockreader, NULL); 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); hr = IWICMetadataBlockReader_GetCount(blockreader, &count);
todo_wine ok(hr == S_OK, "GetCount failed, hr=%x\n", hr); ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
todo_wine ok(count == 1, "unexpected count %d\n", count); ok(count == 1, "unexpected count %d\n", count);
if (0) if (0)
{ {