Signed-off-by: Esme Povirk esme@codeweavers.com --- dlls/windowscodecs/libpng.c | 45 ++++++++++++++++++++++++++ dlls/windowscodecs/pngformat.c | 35 +++++++++----------- dlls/windowscodecs/unix_iface.c | 8 +++++ dlls/windowscodecs/unix_lib.c | 1 + dlls/windowscodecs/wincodecs_common.h | 6 ++++ dlls/windowscodecs/wincodecs_private.h | 7 ++++ 6 files changed, 83 insertions(+), 19 deletions(-)
diff --git a/dlls/windowscodecs/libpng.c b/dlls/windowscodecs/libpng.c index 8a4db91f2a9..36151e94f1b 100644 --- a/dlls/windowscodecs/libpng.c +++ b/dlls/windowscodecs/libpng.c @@ -54,6 +54,7 @@ MAKE_FUNCPTR(png_error); MAKE_FUNCPTR(png_get_bit_depth); MAKE_FUNCPTR(png_get_color_type); MAKE_FUNCPTR(png_get_error_ptr); +MAKE_FUNCPTR(png_get_iCCP); MAKE_FUNCPTR(png_get_image_height); MAKE_FUNCPTR(png_get_image_width); MAKE_FUNCPTR(png_get_io_ptr); @@ -105,6 +106,7 @@ static void *load_libpng(void) LOAD_FUNCPTR(png_get_error_ptr); LOAD_FUNCPTR(png_get_image_height); LOAD_FUNCPTR(png_get_image_width); + LOAD_FUNCPTR(png_get_iCCP); LOAD_FUNCPTR(png_get_io_ptr); LOAD_FUNCPTR(png_get_pHYs); LOAD_FUNCPTR(png_get_PLTE); @@ -137,6 +139,8 @@ struct png_decoder struct decoder_frame decoder_frame; UINT stride; BYTE *image_bits; + BYTE *color_profile; + DWORD color_profile_len; };
static inline struct png_decoder *impl_from_decoder(struct decoder* iface) @@ -194,6 +198,10 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str int i; UINT image_size; png_bytep *row_pointers=NULL; + png_charp cp_name; + png_bytep cp_profile; + png_uint_32 cp_len; + int cp_compression;
png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) @@ -351,6 +359,22 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str This->decoder_frame.dpix = This->decoder_frame.dpiy = 96.0; }
+ ret = ppng_get_iCCP(png_ptr, info_ptr, &cp_name, &cp_compression, &cp_profile, &cp_len); + if (ret) + { + This->decoder_frame.num_color_contexts = 1; + This->color_profile_len = cp_len; + This->color_profile = malloc(cp_len); + if (!This->color_profile) + { + hr = E_OUTOFMEMORY; + goto end; + } + memcpy(This->color_profile, cp_profile, cp_len); + } + else + This->decoder_frame.num_color_contexts = 0; + if (color_type == PNG_COLOR_TYPE_PALETTE) { ret = ppng_get_PLTE(png_ptr, info_ptr, &png_palette, &num_palette); @@ -437,6 +461,8 @@ end: { free(This->image_bits); This->image_bits = NULL; + free(This->color_profile); + This->color_profile = NULL; } return hr; } @@ -531,11 +557,28 @@ end: return hr; }
+HRESULT CDECL png_decoder_get_color_context(struct decoder* iface, UINT frame, UINT num, + BYTE **data, DWORD *datasize) +{ + struct png_decoder *This = impl_from_decoder(iface); + + *data = RtlAllocateHeap(GetProcessHeap(), 0, This->color_profile_len); + *datasize = This->color_profile_len; + + if (!*data) + return E_OUTOFMEMORY; + + memcpy(*data, This->color_profile, This->color_profile_len); + + return S_OK; +} + void CDECL png_decoder_destroy(struct decoder* iface) { struct png_decoder *This = impl_from_decoder(iface);
free(This->image_bits); + free(This->color_profile); RtlFreeHeap(GetProcessHeap(), 0, This); }
@@ -544,6 +587,7 @@ static const struct decoder_funcs png_decoder_vtable = { png_decoder_get_frame_info, png_decoder_copy_pixels, png_decoder_get_metadata_blocks, + png_decoder_get_color_context, png_decoder_destroy };
@@ -566,6 +610,7 @@ HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **res
This->decoder.vtable = &png_decoder_vtable; This->image_bits = NULL; + This->color_profile = NULL; *result = &This->decoder;
info->container_format = GUID_ContainerFormatPng; diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c index 1d696a4fe01..efd5f6ab2c1 100644 --- a/dlls/windowscodecs/pngformat.c +++ b/dlls/windowscodecs/pngformat.c @@ -976,37 +976,34 @@ static HRESULT WINAPI PngDecoder_Frame_GetColorContexts(IWICBitmapFrameDecode *i UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount) { PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface); - png_charp name; + HRESULT hr=S_OK; BYTE *profile; - png_uint_32 len; - int compression_type; - HRESULT hr; + DWORD profile_len;
TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
if (!pcActualCount) return E_INVALIDARG;
- EnterCriticalSection(&This->lock); + *pcActualCount = This->decoder_frame.num_color_contexts;
- if (ppng_get_iCCP(This->png_ptr, This->info_ptr, &name, &compression_type, (void *)&profile, &len)) + if (This->decoder_frame.num_color_contexts && cCount && ppIColorContexts) { - if (cCount && ppIColorContexts) + EnterCriticalSection(&This->lock); + + hr = decoder_get_color_context(This->png_decoder, 0, 0, + &profile, &profile_len); + + LeaveCriticalSection(&This->lock); + + if (SUCCEEDED(hr)) { - hr = IWICColorContext_InitializeFromMemory(*ppIColorContexts, profile, len); - if (FAILED(hr)) - { - LeaveCriticalSection(&This->lock); - return hr; - } + hr = IWICColorContext_InitializeFromMemory(*ppIColorContexts, profile, profile_len); + + HeapFree(GetProcessHeap(), 0, profile); } - *pcActualCount = 1; } - else - *pcActualCount = 0;
- LeaveCriticalSection(&This->lock); - - return S_OK; + return hr; }
static HRESULT WINAPI PngDecoder_Frame_GetThumbnail(IWICBitmapFrameDecode *iface, diff --git a/dlls/windowscodecs/unix_iface.c b/dlls/windowscodecs/unix_iface.c index 8d22b49ba22..cdc92a7d160 100644 --- a/dlls/windowscodecs/unix_iface.c +++ b/dlls/windowscodecs/unix_iface.c @@ -92,6 +92,13 @@ HRESULT CDECL decoder_wrapper_get_metadata_blocks(struct decoder* iface, return unix_funcs->decoder_get_metadata_blocks(This->unix_decoder, frame, count, blocks); }
+HRESULT CDECL decoder_wrapper_get_color_context(struct decoder* iface, + UINT frame, UINT num, BYTE **data, DWORD *datasize) +{ + struct decoder_wrapper* This = impl_from_decoder(iface); + return unix_funcs->decoder_get_color_context(This->unix_decoder, frame, num, data, datasize); +} + void CDECL decoder_wrapper_destroy(struct decoder* iface) { struct decoder_wrapper* This = impl_from_decoder(iface); @@ -104,6 +111,7 @@ static const struct decoder_funcs decoder_wrapper_vtable = { decoder_wrapper_get_frame_info, decoder_wrapper_copy_pixels, decoder_wrapper_get_metadata_blocks, + decoder_wrapper_get_color_context, decoder_wrapper_destroy };
diff --git a/dlls/windowscodecs/unix_lib.c b/dlls/windowscodecs/unix_lib.c index 58c68018430..217a5a2e63a 100644 --- a/dlls/windowscodecs/unix_lib.c +++ b/dlls/windowscodecs/unix_lib.c @@ -71,6 +71,7 @@ static const struct unix_funcs unix_funcs = { decoder_get_frame_info, decoder_copy_pixels, decoder_get_metadata_blocks, + decoder_get_color_context, decoder_destroy };
diff --git a/dlls/windowscodecs/wincodecs_common.h b/dlls/windowscodecs/wincodecs_common.h index 5489a055a27..b5d7b645638 100644 --- a/dlls/windowscodecs/wincodecs_common.h +++ b/dlls/windowscodecs/wincodecs_common.h @@ -37,6 +37,12 @@ HRESULT CDECL decoder_get_metadata_blocks(struct decoder *decoder, UINT frame, U return decoder->vtable->get_metadata_blocks(decoder, frame, count, blocks); }
+HRESULT CDECL decoder_get_color_context(struct decoder *decoder, UINT frame, + UINT num, BYTE **data, DWORD *datasize) +{ + return decoder->vtable->get_color_context(decoder, frame, num, data, datasize); +} + void CDECL decoder_destroy(struct decoder *decoder) { decoder->vtable->destroy(decoder); diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index 3c0b73e893f..e5294b8cf1a 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -275,6 +275,7 @@ struct decoder_frame UINT width, height; UINT bpp; double dpix, dpiy; + DWORD num_color_contexts; DWORD num_colors; WICColor palette[256]; }; @@ -299,6 +300,8 @@ struct decoder_funcs UINT stride, UINT buffersize, BYTE *buffer); HRESULT (CDECL *get_metadata_blocks)(struct decoder* This, UINT frame, UINT *count, struct decoder_block **blocks); + HRESULT (CDECL *get_color_context)(struct decoder* This, UINT frame, UINT num, + BYTE **data, DWORD *datasize); void (CDECL *destroy)(struct decoder* This); };
@@ -318,6 +321,8 @@ HRESULT CDECL decoder_copy_pixels(struct decoder* This, UINT frame, const WICRec UINT stride, UINT buffersize, BYTE *buffer); HRESULT CDECL decoder_get_metadata_blocks(struct decoder* This, UINT frame, UINT *count, struct decoder_block **blocks); +HRESULT CDECL decoder_get_color_context(struct decoder* This, UINT frame, UINT num, + BYTE **data, DWORD *datasize); void CDECL decoder_destroy(struct decoder *This);
HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result); @@ -331,6 +336,8 @@ struct unix_funcs UINT stride, UINT buffersize, BYTE *buffer); HRESULT (CDECL *decoder_get_metadata_blocks)(struct decoder* This, UINT frame, UINT *count, struct decoder_block **blocks); + HRESULT (CDECL *decoder_get_color_context)(struct decoder* This, UINT frame, UINT num, + BYTE **data, DWORD *datasize); void (CDECL *decoder_destroy)(struct decoder* This); };