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