diff options
Diffstat (limited to 'third_party/libwebp/dec/webp.c')
-rw-r--r-- | third_party/libwebp/dec/webp.c | 129 |
1 files changed, 79 insertions, 50 deletions
diff --git a/third_party/libwebp/dec/webp.c b/third_party/libwebp/dec/webp.c index 823eafe641..3bf6f55 100644 --- a/third_party/libwebp/dec/webp.c +++ b/third_party/libwebp/dec/webp.c @@ -186,6 +186,7 @@ static int CustomPut(const VP8Io* io) { return 0; } + p->last_y = io->mb_y + io->mb_h; // a priori guess if (p->mode == MODE_YUV) { uint8_t* const y_dst = p->output + io->mb_y * p->stride; uint8_t* const u_dst = p->u + (io->mb_y >> 1) * p->u_stride; @@ -237,6 +238,9 @@ static int CustomPut(const VP8Io* io) { memcpy(p->top_y, cur_y, w * sizeof(*p->top_y)); memcpy(p->top_u, cur_u, uv_w * sizeof(*p->top_u)); memcpy(p->top_v, cur_v, uv_w * sizeof(*p->top_v)); + // The fancy upscaler leaves a row unfinished behind + // (except for the very last row) + p->last_y -= 1; } else { // Process the very last row of even-sized picture if (!(y_end & 1)) { @@ -315,12 +319,7 @@ void WebPInitCustomIo(VP8Io* const io) { int WebPInitDecParams(const uint8_t* data, uint32_t data_size, int* width, int* height, WebPDecParams* const params) { - int w, h, stride; - int uv_size = 0; - int uv_stride = 0; - int size; - uint8_t* output; - WEBP_CSP_MODE mode = params->mode; + int w, h; if (!WebPGetInfo(data, data_size, &w, &h)) { return 0; @@ -328,38 +327,49 @@ int WebPInitDecParams(const uint8_t* data, uint32_t data_size, int* width, if (width) *width = w; if (height) *height = h; - // initialize output buffer, now that dimensions are known. - stride = (mode == MODE_RGB || mode == MODE_BGR) ? 3 * w - : (mode == MODE_RGBA || mode == MODE_BGRA) ? 4 * w - : w; - size = stride * h; - - if (mode == MODE_YUV) { - uv_stride = (w + 1) / 2; - uv_size = uv_stride * ((h + 1) / 2); - } + if (!params->external_buffer) { + int stride; + int uv_stride = 0; + int size; + int uv_size = 0; + uint8_t* output; + WEBP_CSP_MODE mode = params->mode; + + // initialize output buffer, now that dimensions are known. + stride = (mode == MODE_RGB || mode == MODE_BGR) ? 3 * w + : (mode == MODE_RGBA || mode == MODE_BGRA) ? 4 * w + : w; + size = stride * h; + + if (mode == MODE_YUV) { + uv_stride = (w + 1) / 2; + uv_size = uv_stride * ((h + 1) / 2); + } - output = (uint8_t*)malloc(size + 2 * uv_size); - if (!output) { - return 0; - } + output = (uint8_t*)malloc(size + 2 * uv_size); + if (!output) { + return 0; + } - params->output = output; - params->stride = stride; - if (mode == MODE_YUV) { - params->u = output + size; - params->u_stride = uv_stride; - params->v = output + size + uv_size; - params->v_stride = uv_stride; + params->output = output; + params->stride = stride; + params->output_size = size; + if (mode == MODE_YUV) { + params->u = output + size; + params->u_stride = uv_stride; + params->output_u_size = uv_size; + params->v = output + size + uv_size; + params->v_stride = uv_stride; + params->output_v_size = uv_size; + } } return 1; } -int WebPCheckDecParams(const VP8Io* io, const WebPDecParams* params, - int output_size, int output_u_size, int output_v_size) { +int WebPCheckDecParams(const VP8Io* io, const WebPDecParams* params) { int ok = 1; WEBP_CSP_MODE mode = params->mode; - ok &= (params->stride * io->height <= output_size); + ok &= (params->stride * io->height <= params->output_size); if (mode == MODE_RGB || mode == MODE_BGR) { ok &= (params->stride >= io->width * 3); } else if (mode == MODE_RGBA || mode == MODE_BGRA) { @@ -371,13 +381,16 @@ int WebPCheckDecParams(const VP8Io* io, const WebPDecParams* params, ok &= (params->stride >= io->width); ok &= (params->u_stride >= (io->width + 1) / 2) && (params->v_stride >= (io->width + 1) / 2); - ok &= (u_size <= output_u_size && v_size <= output_v_size); + ok &= (u_size <= params->output_u_size && + v_size <= params->output_v_size); } return ok; } void WebPClearDecParams(WebPDecParams* params) { - free(params->output); + if (!params->external_buffer) { + free(params->output); + } memset(params, 0, sizeof(*params)); } @@ -386,8 +399,7 @@ void WebPClearDecParams(WebPDecParams* params) { static uint8_t* DecodeInto(WEBP_CSP_MODE mode, const uint8_t* data, uint32_t data_size, - WebPDecParams* params, int output_size, - int output_u_size, int output_v_size) { + WebPDecParams* params) { VP8Decoder* dec = VP8New(); VP8Io io; int ok = 1; @@ -410,8 +422,7 @@ static uint8_t* DecodeInto(WEBP_CSP_MODE mode, } // check output buffers - ok = WebPCheckDecParams(&io, params, output_size, - output_u_size, output_v_size); + ok = WebPCheckDecParams(&io, params); if (!ok) { VP8Delete(dec); return NULL; @@ -437,7 +448,10 @@ uint8_t* WebPDecodeRGBInto(const uint8_t* data, uint32_t data_size, params.output = output; params.stride = output_stride; - return DecodeInto(MODE_RGB, data, data_size, ¶ms, output_size, 0, 0); + params.output_size = output_size; + params.output_u_size = 0; + params.output_v_size = 0; + return DecodeInto(MODE_RGB, data, data_size, ¶ms); } uint8_t* WebPDecodeRGBAInto(const uint8_t* data, uint32_t data_size, @@ -451,7 +465,10 @@ uint8_t* WebPDecodeRGBAInto(const uint8_t* data, uint32_t data_size, params.output = output; params.stride = output_stride; - return DecodeInto(MODE_RGBA, data, data_size, ¶ms, output_size, 0, 0); + params.output_size = output_size; + params.output_u_size = 0; + params.output_v_size = 0; + return DecodeInto(MODE_RGBA, data, data_size, ¶ms); } uint8_t* WebPDecodeBGRInto(const uint8_t* data, uint32_t data_size, @@ -465,7 +482,10 @@ uint8_t* WebPDecodeBGRInto(const uint8_t* data, uint32_t data_size, params.output = output; params.stride = output_stride; - return DecodeInto(MODE_BGR, data, data_size, ¶ms, output_size, 0, 0); + params.output_size = output_size; + params.output_u_size = 0; + params.output_v_size = 0; + return DecodeInto(MODE_BGR, data, data_size, ¶ms); } uint8_t* WebPDecodeBGRAInto(const uint8_t* data, uint32_t data_size, @@ -479,7 +499,10 @@ uint8_t* WebPDecodeBGRAInto(const uint8_t* data, uint32_t data_size, params.output = output; params.stride = output_stride; - return DecodeInto(MODE_BGRA, data, data_size, ¶ms, output_size, 0, 0); + params.output_size = output_size; + params.output_u_size = 0; + params.output_v_size = 0; + return DecodeInto(MODE_BGRA, data, data_size, ¶ms); } uint8_t* WebPDecodeYUVInto(const uint8_t* data, uint32_t data_size, @@ -494,12 +517,14 @@ uint8_t* WebPDecodeYUVInto(const uint8_t* data, uint32_t data_size, params.output = luma; params.stride = luma_stride; + params.output_size = luma_size; params.u = u; params.u_stride = u_stride; + params.output_u_size = u_size; params.v = v; params.v_stride = v_stride; - return DecodeInto(MODE_YUV, data, data_size, ¶ms, - luma_size, u_size, v_size); + params.output_v_size = v_size; + return DecodeInto(MODE_YUV, data, data_size, ¶ms); } //----------------------------------------------------------------------------- @@ -507,22 +532,26 @@ uint8_t* WebPDecodeYUVInto(const uint8_t* data, uint32_t data_size, static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* data, uint32_t data_size, int* width, int* height, WebPDecParams* params_out) { - int size = 0; - int uv_size = 0; - WebPDecParams params = { 0 }; + uint8_t* output; + WebPDecParams params; + memset(¶ms, 0, sizeof(params)); params.mode = mode; if (!WebPInitDecParams(data, data_size, width, height, ¶ms)) { return NULL; } - size = params.stride * (*height); - uv_size = params.u_stride * ((*height + 1) / 2); - if (!DecodeInto(mode, data, data_size, ¶ms, size, uv_size, uv_size)) { + params.output_size = params.stride * (*height); + params.output_u_size = params.output_v_size = + params.u_stride * ((*height + 1) / 2); + output = DecodeInto(mode, data, data_size, ¶ms); + if (!output) { WebPClearDecParams(¶ms); } - if (params_out) *params_out = params; - return params.output; + if (params_out) { + *params_out = params; + } + return output; } uint8_t* WebPDecodeRGB(const uint8_t* data, uint32_t data_size, |