diff --git a/PIL/WebPImagePlugin.py b/PIL/WebPImagePlugin.py index cdf5fe48e..afddb0a0d 100644 --- a/PIL/WebPImagePlugin.py +++ b/PIL/WebPImagePlugin.py @@ -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): diff --git a/decode.c b/decode.c index 2aab01157..782966ac4 100644 --- a/decode.c +++ b/decode.c @@ -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; diff --git a/libImaging/WebP.h b/libImaging/WebP.h index 7da292e6f..6eb9b51bb 100644 --- a/libImaging/WebP.h +++ b/libImaging/WebP.h @@ -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; diff --git a/libImaging/WebPDecode.c b/libImaging/WebPDecode.c index c886ffc94..9b19b764e 100644 --- a/libImaging/WebPDecode.c +++ b/libImaging/WebPDecode.c @@ -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);