[PATCH 4/8] windowscodecs: Move PNG CopyPixels to unix lib.

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


Signed-off-by: Esme Povirk <esme at codeweavers.com>
---
 dlls/windowscodecs/libpng.c            | 54 ++++++++++++++++++++
 dlls/windowscodecs/main.c              | 65 -----------------------
 dlls/windowscodecs/pngformat.c         |  3 +-
 dlls/windowscodecs/unix_iface.c        |  8 +++
 dlls/windowscodecs/unix_lib.c          |  3 ++
 dlls/windowscodecs/wincodecs_common.h  | 71 ++++++++++++++++++++++++++
 dlls/windowscodecs/wincodecs_private.h |  6 +++
 7 files changed, 143 insertions(+), 67 deletions(-)

diff --git a/dlls/windowscodecs/libpng.c b/dlls/windowscodecs/libpng.c
index bed7ea72d65..397d2d371ef 100644
--- a/dlls/windowscodecs/libpng.c
+++ b/dlls/windowscodecs/libpng.c
@@ -60,6 +60,8 @@ MAKE_FUNCPTR(png_get_io_ptr);
 MAKE_FUNCPTR(png_get_pHYs);
 MAKE_FUNCPTR(png_get_PLTE);
 MAKE_FUNCPTR(png_get_tRNS);
+MAKE_FUNCPTR(png_read_end);
+MAKE_FUNCPTR(png_read_image);
 MAKE_FUNCPTR(png_read_info);
 MAKE_FUNCPTR(png_set_bgr);
 MAKE_FUNCPTR(png_set_crc_action);
@@ -107,6 +109,8 @@ static void *load_libpng(void)
         LOAD_FUNCPTR(png_get_pHYs);
         LOAD_FUNCPTR(png_get_PLTE);
         LOAD_FUNCPTR(png_get_tRNS);
+        LOAD_FUNCPTR(png_read_end);
+        LOAD_FUNCPTR(png_read_image);
         LOAD_FUNCPTR(png_read_info);
         LOAD_FUNCPTR(png_set_bgr);
         LOAD_FUNCPTR(png_set_crc_action);
@@ -130,6 +134,8 @@ struct png_decoder
 {
     struct decoder decoder;
     struct decoder_frame decoder_frame;
+    UINT stride;
+    BYTE *image_bits;
 };
 
 static inline struct png_decoder *impl_from_decoder(struct decoder* iface)
@@ -185,6 +191,8 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
     png_colorp png_palette;
     int num_palette;
     int i;
+    UINT image_size;
+    png_bytep *row_pointers=NULL;
 
     png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
     if (!png_ptr)
@@ -385,6 +393,33 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
         This->decoder_frame.num_colors = 0;
     }
 
+    This->stride = (This->decoder_frame.width * This->decoder_frame.bpp + 7) / 8;
+    image_size = This->stride * This->decoder_frame.height;
+
+    This->image_bits = malloc(image_size);
+    if (!This->image_bits)
+    {
+        hr = E_OUTOFMEMORY;
+        goto end;
+    }
+
+    row_pointers = malloc(sizeof(png_bytep)*This->decoder_frame.height);
+    if (!row_pointers)
+    {
+        hr = E_OUTOFMEMORY;
+        goto end;
+    }
+
+    for (i=0; i<This->decoder_frame.height; i++)
+        row_pointers[i] = This->image_bits + i * This->stride;
+
+    ppng_read_image(png_ptr, row_pointers);
+
+    free(row_pointers);
+    row_pointers = NULL;
+
+    ppng_read_end(png_ptr, end_info);
+
     st->flags = WICBitmapDecoderCapabilityCanDecodeAllImages |
                 WICBitmapDecoderCapabilityCanDecodeSomeImages |
                 WICBitmapDecoderCapabilityCanEnumerateMetadata;
@@ -394,6 +429,12 @@ HRESULT CDECL png_decoder_initialize(struct decoder *iface, IStream *stream, str
 
 end:
     ppng_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+    free(row_pointers);
+    if (FAILED(hr))
+    {
+        free(This->image_bits);
+        This->image_bits = NULL;
+    }
     return hr;
 }
 
@@ -404,16 +445,28 @@ HRESULT CDECL png_decoder_get_frame_info(struct decoder *iface, UINT frame, stru
     return S_OK;
 }
 
+HRESULT CDECL png_decoder_copy_pixels(struct decoder *iface, UINT frame,
+    const WICRect *prc, UINT stride, UINT buffersize, BYTE *buffer)
+{
+    struct png_decoder *This = impl_from_decoder(iface);
+
+    return copy_pixels(This->decoder_frame.bpp, This->image_bits,
+        This->decoder_frame.width, This->decoder_frame.height, This->stride,
+        prc, stride, buffersize, buffer);
+}
+
 void CDECL png_decoder_destroy(struct decoder* iface)
 {
     struct png_decoder *This = impl_from_decoder(iface);
 
+    free(This->image_bits);
     RtlFreeHeap(GetProcessHeap(), 0, This);
 }
 
 static const struct decoder_funcs png_decoder_vtable = {
     png_decoder_initialize,
     png_decoder_get_frame_info,
+    png_decoder_copy_pixels,
     png_decoder_destroy
 };
 
@@ -435,6 +488,7 @@ HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **res
     }
 
     This->decoder.vtable = &png_decoder_vtable;
+    This->image_bits = NULL;
     *result = &This->decoder;
 
     info->container_format = GUID_ContainerFormatPng;
diff --git a/dlls/windowscodecs/main.c b/dlls/windowscodecs/main.c
index 2d8b0336f3f..982c8ddfada 100644
--- a/dlls/windowscodecs/main.c
+++ b/dlls/windowscodecs/main.c
@@ -60,71 +60,6 @@ HRESULT WINAPI DllCanUnloadNow(void)
     return S_FALSE;
 }
 
-HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer,
-    UINT srcwidth, UINT srcheight, INT srcstride,
-    const WICRect *rc, UINT dststride, UINT dstbuffersize, BYTE *dstbuffer)
-{
-    UINT bytesperrow;
-    UINT row_offset; /* number of bits into the source rows where the data starts */
-    WICRect rect;
-
-    if (!rc)
-    {
-        rect.X = 0;
-        rect.Y = 0;
-        rect.Width = srcwidth;
-        rect.Height = srcheight;
-        rc = ▭
-    }
-    else
-    {
-        if (rc->X < 0 || rc->Y < 0 || rc->X+rc->Width > srcwidth || rc->Y+rc->Height > srcheight)
-            return E_INVALIDARG;
-    }
-
-    bytesperrow = ((bpp * rc->Width)+7)/8;
-
-    if (dststride < bytesperrow)
-        return E_INVALIDARG;
-
-    if ((dststride * (rc->Height-1)) + bytesperrow > dstbuffersize)
-        return E_INVALIDARG;
-
-    /* if the whole bitmap is copied and the buffer format matches then it's a matter of a single memcpy */
-    if (rc->X == 0 && rc->Y == 0 && rc->Width == srcwidth && rc->Height == srcheight &&
-        srcstride == dststride && srcstride == bytesperrow)
-    {
-        memcpy(dstbuffer, srcbuffer, srcstride * srcheight);
-        return S_OK;
-    }
-
-    row_offset = rc->X * bpp;
-
-    if (row_offset % 8 == 0)
-    {
-        /* everything lines up on a byte boundary */
-        INT row;
-        const BYTE *src;
-        BYTE *dst;
-
-        src = srcbuffer + (row_offset / 8) + srcstride * rc->Y;
-        dst = dstbuffer;
-        for (row=0; row < rc->Height; row++)
-        {
-            memcpy(dst, src, bytesperrow);
-            src += srcstride;
-            dst += dststride;
-        }
-        return S_OK;
-    }
-    else
-    {
-        /* we have to do a weird bitwise copy. eww. */
-        FIXME("cannot reliably copy bitmap data if bpp < 8\n");
-        return E_FAIL;
-    }
-}
-
 HRESULT configure_write_source(IWICBitmapFrameEncode *iface,
     IWICBitmapSource *source, const WICRect *prc,
     const WICPixelFormatGUID *format,
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c
index d10afcedbc3..834cc81d306 100644
--- a/dlls/windowscodecs/pngformat.c
+++ b/dlls/windowscodecs/pngformat.c
@@ -1051,8 +1051,7 @@ static HRESULT WINAPI PngDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface,
     PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
     TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer);
 
-    return copy_pixels(This->bpp, This->image_bits,
-        This->width, This->height, This->stride,
+    return decoder_copy_pixels(This->png_decoder, 0,
         prc, cbStride, cbBufferSize, pbBuffer);
 }
 
diff --git a/dlls/windowscodecs/unix_iface.c b/dlls/windowscodecs/unix_iface.c
index cf66fbd964d..46bcacff941 100644
--- a/dlls/windowscodecs/unix_iface.c
+++ b/dlls/windowscodecs/unix_iface.c
@@ -78,6 +78,13 @@ HRESULT CDECL decoder_wrapper_get_frame_info(struct decoder* iface, UINT frame,
     return unix_funcs->decoder_get_frame_info(This->unix_decoder, frame, info);
 }
 
+HRESULT CDECL decoder_wrapper_copy_pixels(struct decoder* iface, UINT frame,
+    const WICRect *prc, UINT stride, UINT buffersize, BYTE *buffer)
+{
+    struct decoder_wrapper* This = impl_from_decoder(iface);
+    return unix_funcs->decoder_copy_pixels(This->unix_decoder, frame, prc, stride, buffersize, buffer);
+}
+
 void CDECL decoder_wrapper_destroy(struct decoder* iface)
 {
     struct decoder_wrapper* This = impl_from_decoder(iface);
@@ -88,6 +95,7 @@ void CDECL decoder_wrapper_destroy(struct decoder* iface)
 static const struct decoder_funcs decoder_wrapper_vtable = {
     decoder_wrapper_initialize,
     decoder_wrapper_get_frame_info,
+    decoder_wrapper_copy_pixels,
     decoder_wrapper_destroy
 };
 
diff --git a/dlls/windowscodecs/unix_lib.c b/dlls/windowscodecs/unix_lib.c
index 111a82dc637..5ab1cb342e6 100644
--- a/dlls/windowscodecs/unix_lib.c
+++ b/dlls/windowscodecs/unix_lib.c
@@ -41,6 +41,8 @@
 
 #include "wine/debug.h"
 
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
 #include "wincodecs_common.h"
 
 static const struct win32_funcs *win32_funcs;
@@ -67,6 +69,7 @@ static const struct unix_funcs unix_funcs = {
     decoder_create,
     decoder_initialize,
     decoder_get_frame_info,
+    decoder_copy_pixels,
     decoder_destroy
 };
 
diff --git a/dlls/windowscodecs/wincodecs_common.h b/dlls/windowscodecs/wincodecs_common.h
index ac8ae015c76..f116fb6fd8f 100644
--- a/dlls/windowscodecs/wincodecs_common.h
+++ b/dlls/windowscodecs/wincodecs_common.h
@@ -26,8 +26,79 @@ HRESULT CDECL decoder_get_frame_info(struct decoder *decoder, UINT frame, struct
     return decoder->vtable->get_frame_info(decoder, frame, info);
 }
 
+HRESULT CDECL decoder_copy_pixels(struct decoder *decoder, UINT frame,
+    const WICRect *prc, UINT stride, UINT buffersize, BYTE *buffer)
+{
+    return decoder->vtable->copy_pixels(decoder, frame, prc, stride, buffersize, buffer);
+}
+
 void CDECL decoder_destroy(struct decoder *decoder)
 {
     decoder->vtable->destroy(decoder);
 }
 
+HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer,
+    UINT srcwidth, UINT srcheight, INT srcstride,
+    const WICRect *rc, UINT dststride, UINT dstbuffersize, BYTE *dstbuffer)
+{
+    UINT bytesperrow;
+    UINT row_offset; /* number of bits into the source rows where the data starts */
+    WICRect rect;
+
+    if (!rc)
+    {
+        rect.X = 0;
+        rect.Y = 0;
+        rect.Width = srcwidth;
+        rect.Height = srcheight;
+        rc = ▭
+    }
+    else
+    {
+        if (rc->X < 0 || rc->Y < 0 || rc->X+rc->Width > srcwidth || rc->Y+rc->Height > srcheight)
+            return E_INVALIDARG;
+    }
+
+    bytesperrow = ((bpp * rc->Width)+7)/8;
+
+    if (dststride < bytesperrow)
+        return E_INVALIDARG;
+
+    if ((dststride * (rc->Height-1)) + bytesperrow > dstbuffersize)
+        return E_INVALIDARG;
+
+    /* if the whole bitmap is copied and the buffer format matches then it's a matter of a single memcpy */
+    if (rc->X == 0 && rc->Y == 0 && rc->Width == srcwidth && rc->Height == srcheight &&
+        srcstride == dststride && srcstride == bytesperrow)
+    {
+        memcpy(dstbuffer, srcbuffer, srcstride * srcheight);
+        return S_OK;
+    }
+
+    row_offset = rc->X * bpp;
+
+    if (row_offset % 8 == 0)
+    {
+        /* everything lines up on a byte boundary */
+        INT row;
+        const BYTE *src;
+        BYTE *dst;
+
+        src = srcbuffer + (row_offset / 8) + srcstride * rc->Y;
+        dst = dstbuffer;
+        for (row=0; row < rc->Height; row++)
+        {
+            memcpy(dst, src, bytesperrow);
+            src += srcstride;
+            dst += dststride;
+        }
+        return S_OK;
+    }
+    else
+    {
+        /* we have to do a weird bitwise copy. eww. */
+        FIXME("cannot reliably copy bitmap data if bpp < 8\n");
+        return E_FAIL;
+    }
+}
+
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index 6d12b98bfc4..24cae3652f4 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -286,6 +286,8 @@ struct decoder_funcs
 {
     HRESULT (CDECL *initialize)(struct decoder* This, IStream *stream, struct decoder_stat *st);
     HRESULT (CDECL *get_frame_info)(struct decoder* This, UINT frame, struct decoder_frame *info);
+    HRESULT (CDECL *copy_pixels)(struct decoder* This, UINT frame, const WICRect *prc,
+        UINT stride, UINT buffersize, BYTE *buffer);
     void (CDECL *destroy)(struct decoder* This);
 };
 
@@ -301,6 +303,8 @@ struct win32_funcs
 HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result);
 HRESULT CDECL decoder_initialize(struct decoder *This, IStream *stream, struct decoder_stat *st);
 HRESULT CDECL decoder_get_frame_info(struct decoder* This, UINT frame, struct decoder_frame *info);
+HRESULT CDECL decoder_copy_pixels(struct decoder* This, UINT frame, const WICRect *prc,
+    UINT stride, UINT buffersize, BYTE *buffer);
 void CDECL decoder_destroy(struct decoder *This);
 
 HRESULT CDECL png_decoder_create(struct decoder_info *info, struct decoder **result);
@@ -310,6 +314,8 @@ struct unix_funcs
     HRESULT (CDECL *decoder_create)(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result); 
     HRESULT (CDECL *decoder_initialize)(struct decoder *This, IStream *stream, struct decoder_stat *st); 
     HRESULT (CDECL *decoder_get_frame_info)(struct decoder* This, UINT frame, struct decoder_frame *info);
+    HRESULT (CDECL *decoder_copy_pixels)(struct decoder* This, UINT frame, const WICRect *prc,
+        UINT stride, UINT buffersize, BYTE *buffer);
     void (CDECL *decoder_destroy)(struct decoder* This);
 };
 
-- 
2.17.1




More information about the wine-devel mailing list