windowscodecs: Move PNG CopyPixels to unix lib.

Signed-off-by: Esme Povirk <esme@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Esme Povirk 2020-10-09 14:56:19 -05:00 committed by Alexandre Julliard
parent 8b849e814b
commit 53ce545e69
7 changed files with 143 additions and 67 deletions

View File

@ -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;

View File

@ -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 = &rect;
}
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,

View File

@ -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);
}

View File

@ -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
};

View File

@ -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
};

View File

@ -26,7 +26,78 @@ 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 = &rect;
}
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;
}
}

View File

@ -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);
};