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.
(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):
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 */
int has_alpha;
int width, height;
int onepass = 0;
if (!PyArg_ParseTuple(args, "ssiii",
if (!PyArg_ParseTuple(args, "ssiii|i",
&mode, &rawmode,
&has_alpha, &width, &height))
&has_alpha, &width, &height,
&onepass))
return NULL;
decoder = PyImaging_DecoderNew(sizeof(WEBPSTATE));
@ -763,6 +765,7 @@ PyImaging_WebPDecoderNew(PyObject* self, PyObject* args)
context->has_alpha = has_alpha;
context->width = width;
context->height = height;
context->onepass = onepass;
context->output = NULL;
context->decoder = NULL;

View File

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

View File

@ -81,24 +81,39 @@ int ImagingWebPDecode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes
config->options.use_scaling = 1;
}
context->decoder = WebPIDecode(NULL, 0, config);
if (NULL == context->decoder)
if (!context->onepass)
{
state->errcode = _vp8_status_to_codec_status(vp8_status_code);
return -1;
context->decoder = WebPIDecode(NULL, 0, config);
if (NULL == context->decoder)
{
state->errcode = _vp8_status_to_codec_status(vp8_status_code);
return -1;
}
}
state->state = 1;
}
/* 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)
if (context->onepass)
{
state->errcode = _vp8_status_to_codec_status(vp8_status_code);
return -1;
vp8_status_code = WebPDecode(buf, bytes, config);
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)
@ -111,7 +126,19 @@ int ImagingWebPDecode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes
int height;
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)
{
assert(width == state->xsize);