webp: disable incremental decoding on lossless content

Two reasons:
- it's *really* slow on lossless content
- it's not incremental on lossless content: decoding will only be done
  at the end, after the whole data has been pushed to the decoder
This commit is contained in:
Benoit Pierre 2015-02-27 12:50:45 +01:00
parent 2a7fde6c81
commit ea2ceab377
4 changed files with 52 additions and 14 deletions

View File

@ -157,6 +157,11 @@ class WebPImageFile(ImageFile.ImageFile):
# Decoder params: rawmode, has_alpha, width, height. # Decoder params: rawmode, has_alpha, width, height.
(mode, 1 if 'RGBA' == mode else 0, size[0], size[1]))] (mode, 1 if 'RGBA' == mode else 0, size[0], size[1]))]
if not lossy:
# Incremental decoding on lossless is *really* slow, disable it.
self.decodermaxblock = 12 + i32le(header[4:8])
self.decoderconfig = (1,)
def draft(self, mode, size): def draft(self, mode, size):
if 1 != len(self.tile): if 1 != len(self.tile):

View File

@ -740,10 +740,12 @@ PyImaging_WebPDecoderNew(PyObject* self, PyObject* args)
char* rawmode; /* what we wan't from the decoder */ char* rawmode; /* what we wan't from the decoder */
int has_alpha; int has_alpha;
int width, height; int width, height;
int onepass = 0;
if (!PyArg_ParseTuple(args, "ssiii", if (!PyArg_ParseTuple(args, "ssiii|i",
&mode, &rawmode, &mode, &rawmode,
&has_alpha, &width, &height)) &has_alpha, &width, &height,
&onepass))
return NULL; return NULL;
decoder = PyImaging_DecoderNew(sizeof(WEBPSTATE)); decoder = PyImaging_DecoderNew(sizeof(WEBPSTATE));
@ -763,6 +765,7 @@ PyImaging_WebPDecoderNew(PyObject* self, PyObject* args)
context->has_alpha = has_alpha; context->has_alpha = has_alpha;
context->width = width; context->width = width;
context->height = height; context->height = height;
context->onepass = onepass;
context->output = NULL; context->output = NULL;
context->decoder = NULL; context->decoder = NULL;

View File

@ -22,6 +22,9 @@ typedef struct {
int has_alpha; int has_alpha;
int width, height; int width, height;
/* Decoder will receive and decode the data in one pass. */
int onepass;
/* PRIVATE CONTEXT (set by decoder) */ /* PRIVATE CONTEXT (set by decoder) */
WebPDecoderConfig config; WebPDecoderConfig config;

View File

@ -81,24 +81,39 @@ int ImagingWebPDecode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes
config->options.use_scaling = 1; config->options.use_scaling = 1;
} }
context->decoder = WebPIDecode(NULL, 0, config); if (!context->onepass)
if (NULL == context->decoder)
{ {
state->errcode = _vp8_status_to_codec_status(vp8_status_code); context->decoder = WebPIDecode(NULL, 0, config);
return -1; if (NULL == context->decoder)
{
state->errcode = _vp8_status_to_codec_status(vp8_status_code);
return -1;
}
} }
state->state = 1; state->state = 1;
} }
/* Consume the buffer, decoding as much as possible. */ if (context->onepass)
vp8_status_code = WebPIAppend(context->decoder, buf, bytes);
if (VP8_STATUS_NOT_ENOUGH_DATA != vp8_status_code &&
VP8_STATUS_SUSPENDED != vp8_status_code &&
VP8_STATUS_OK != vp8_status_code)
{ {
state->errcode = _vp8_status_to_codec_status(vp8_status_code); vp8_status_code = WebPDecode(buf, bytes, config);
return -1; if (VP8_STATUS_OK != vp8_status_code)
{
state->errcode = _vp8_status_to_codec_status(vp8_status_code);
return -1;
}
}
else
{
/* Consume the buffer, decoding as much as possible. */
vp8_status_code = WebPIAppend(context->decoder, buf, bytes);
if (VP8_STATUS_NOT_ENOUGH_DATA != vp8_status_code &&
VP8_STATUS_SUSPENDED != vp8_status_code &&
VP8_STATUS_OK != vp8_status_code)
{
state->errcode = _vp8_status_to_codec_status(vp8_status_code);
return -1;
}
} }
if (VP8_STATUS_NOT_ENOUGH_DATA != vp8_status_code) if (VP8_STATUS_NOT_ENOUGH_DATA != vp8_status_code)
@ -111,7 +126,19 @@ int ImagingWebPDecode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes
int height; int height;
int stride; int stride;
rgba = WebPIDecGetRGB(context->decoder, &last_y, &width, &height, &stride); if (context->onepass)
{
rgba = config->output.u.RGBA.rgba;
last_y = state->ysize;
width = state->xsize;
height = state->ysize;
stride = config->output.u.RGBA.stride;
}
else
{
rgba = WebPIDecGetRGB(context->decoder, &last_y, &width, &height, &stride);
}
if (NULL != rgba) if (NULL != rgba)
{ {
assert(width == state->xsize); assert(width == state->xsize);