webp: decode directly to block storage when possible

This commit is contained in:
Benoit Pierre 2015-02-27 03:04:56 +01:00
parent 76c8dda681
commit bd369f78ae
3 changed files with 36 additions and 7 deletions

View File

@ -763,6 +763,7 @@ PyImaging_WebPDecoderNew(PyObject* self, PyObject* args)
context->has_alpha = has_alpha;
context->width = width;
context->height = height;
context->output = NULL;
context->decoder = NULL;
return (PyObject*) decoder;

View File

@ -25,6 +25,9 @@ typedef struct {
/* PRIVATE CONTEXT (set by decoder) */
WebPDecoderConfig config;
/* Non-NULL when a temporary output buffer is in use. */
WebPDecBuffer *output;
/* Non-NULL when an incremental decoder is in use. */
WebPIDecoder *decoder;
} WEBPSTATE;

View File

@ -39,13 +39,12 @@ static int _vp8_status_to_codec_status(VP8StatusCode code)
int ImagingWebPDecode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes)
{
WEBPSTATE *context = (WEBPSTATE *)state->context;
VP8StatusCode vp8_status_code;
WEBPSTATE *context = (WEBPSTATE *)state->context;
WebPDecoderConfig *config = &context->config;
VP8StatusCode vp8_status_code;
if (!state->state)
{
WebPDecoderConfig *config = &context->config;
if (!WebPInitDecoderConfig(config))
{
/* Mismatched version. */
@ -58,6 +57,23 @@ int ImagingWebPDecode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes
else
config->output.colorspace = MODE_RGB;
/* If block storage is used, and we're not stripping alpha, then directly decode to it. */
if (NULL != im->block && (MODE_RGBA == config->output.colorspace || !context->has_alpha))
{
assert(4 == im->pixelsize);
/* Force RGBA so RGB is correctly unpacked. */
config->output.colorspace = MODE_RGBA;
config->output.is_external_memory = 1;
config->output.u.RGBA.stride = im->linesize;
config->output.u.RGBA.size = config->output.u.RGBA.stride * state->ysize;
config->output.u.RGBA.rgba = (uint8_t *)im->block + state->xoff * 4 + state->yoff * im->linesize;
}
else
{
context->output = &config->output;
}
if (state->xsize != context->width || state->ysize != context->height)
{
config->options.scaled_width = state->xsize;
@ -102,10 +118,14 @@ int ImagingWebPDecode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes
assert(height == state->ysize);
assert(last_y <= state->ysize);
for (; state->y < last_y; ++state->y)
if (config->output.is_external_memory)
{
state->y = last_y;
}
else for (; state->y < last_y; ++state->y)
{
assert(state->y < state->ysize);
state->shuffle((UINT8*) im->image[state->y + state->yoff] +
state->shuffle((UINT8 *)im->image[state->y + state->yoff] +
state->xoff * im->pixelsize,
rgba + state->y * stride, state->xsize);
}
@ -131,9 +151,14 @@ int ImagingWebPDecodeCleanup(ImagingCodecState state)
{
WEBPSTATE* context = (WEBPSTATE*) state->context;
if (NULL != context->output)
{
WebPFreeDecBuffer(context->output);
context->output = NULL;
}
if (NULL != context->decoder)
{
WebPFreeDecBuffer(&context->config.output);
WebPIDelete(context->decoder);
context->decoder = NULL;
}