[PATCH 6/8] windowscodecs: Use unix lib to get PNG color contexts.

Esme Povirk esme at codeweavers.com
Fri Oct 9 14:56:21 CDT 2020


Signed-off-by: Esme Povirk <esme at 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);
 };
 
-- 
2.17.1




More information about the wine-devel mailing list