windowscodecs: Implement PngDecoder_Block_GetCount.
This commit is contained in:
parent
292d7bdf0f
commit
43c97b871f
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue