| Index: third_party/libwebp/dec/io.c
|
| diff --git a/third_party/libwebp/dec/io.c b/third_party/libwebp/dec/io.c
|
| index b2e72f0b2612d4a60d99c736cf3425a5b5fbeec7..13e469ab733ca7f15c6d7b851b6cd74235755fb9 100644
|
| --- a/third_party/libwebp/dec/io.c
|
| +++ b/third_party/libwebp/dec/io.c
|
| @@ -56,32 +56,6 @@ static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) {
|
| }
|
|
|
| //------------------------------------------------------------------------------
|
| -// YUV444 -> RGB conversion
|
| -
|
| -#if 0 // TODO(skal): this is for future rescaling.
|
| -static int EmitRGB(const VP8Io* const io, WebPDecParams* const p) {
|
| - WebPDecBuffer* output = p->output;
|
| - const WebPRGBABuffer* const buf = &output->u.RGBA;
|
| - uint8_t* dst = buf->rgba + io->mb_y * buf->stride;
|
| - const uint8_t* y_src = io->y;
|
| - const uint8_t* u_src = io->u;
|
| - const uint8_t* v_src = io->v;
|
| - const WebPYUV444Converter convert = WebPYUV444Converters[output->colorspace];
|
| - const int mb_w = io->mb_w;
|
| - const int last = io->mb_h;
|
| - int j;
|
| - for (j = 0; j < last; ++j) {
|
| - convert(y_src, u_src, v_src, dst, mb_w);
|
| - y_src += io->y_stride;
|
| - u_src += io->uv_stride;
|
| - v_src += io->uv_stride;
|
| - dst += buf->stride;
|
| - }
|
| - return io->mb_h;
|
| -}
|
| -#endif
|
| -
|
| -//------------------------------------------------------------------------------
|
| // Fancy upsampling
|
|
|
| #ifdef FANCY_UPSAMPLING
|
| @@ -145,14 +119,16 @@ static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) {
|
|
|
| //------------------------------------------------------------------------------
|
|
|
| -static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p) {
|
| +static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p,
|
| + int expected_num_lines_out) {
|
| const uint8_t* alpha = io->a;
|
| const WebPYUVABuffer* const buf = &p->output->u.YUVA;
|
| const int mb_w = io->mb_w;
|
| const int mb_h = io->mb_h;
|
| uint8_t* dst = buf->a + io->mb_y * buf->a_stride;
|
| int j;
|
| -
|
| + (void)expected_num_lines_out;
|
| + assert(expected_num_lines_out == mb_h);
|
| if (alpha != NULL) {
|
| for (j = 0; j < mb_h; ++j) {
|
| memcpy(dst, alpha, mb_w * sizeof(*dst));
|
| @@ -195,7 +171,8 @@ static int GetAlphaSourceRow(const VP8Io* const io,
|
| return start_y;
|
| }
|
|
|
| -static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
|
| +static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p,
|
| + int expected_num_lines_out) {
|
| const uint8_t* alpha = io->a;
|
| if (alpha != NULL) {
|
| const int mb_w = io->mb_w;
|
| @@ -206,21 +183,13 @@ static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
|
| int num_rows;
|
| const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
|
| uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
|
| - uint8_t* dst = base_rgba + (alpha_first ? 0 : 3);
|
| - uint32_t alpha_mask = 0xff;
|
| - int i, j;
|
| -
|
| - for (j = 0; j < num_rows; ++j) {
|
| - for (i = 0; i < mb_w; ++i) {
|
| - const uint32_t alpha_value = alpha[i];
|
| - dst[4 * i] = alpha_value;
|
| - alpha_mask &= alpha_value;
|
| - }
|
| - alpha += io->width;
|
| - dst += buf->stride;
|
| - }
|
| - // alpha_mask is < 0xff if there's non-trivial alpha to premultiply with.
|
| - if (alpha_mask != 0xff && WebPIsPremultipliedMode(colorspace)) {
|
| + uint8_t* const dst = base_rgba + (alpha_first ? 0 : 3);
|
| + const int has_alpha = WebPDispatchAlpha(alpha, io->width, mb_w,
|
| + num_rows, dst, buf->stride);
|
| + (void)expected_num_lines_out;
|
| + assert(expected_num_lines_out == num_rows);
|
| + // has_alpha is true if there's non-trivial alpha to premultiply with.
|
| + if (has_alpha && WebPIsPremultipliedMode(colorspace)) {
|
| WebPApplyAlphaMultiply(base_rgba, alpha_first,
|
| mb_w, num_rows, buf->stride);
|
| }
|
| @@ -228,7 +197,8 @@ static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
|
| return 0;
|
| }
|
|
|
| -static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p) {
|
| +static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p,
|
| + int expected_num_lines_out) {
|
| const uint8_t* alpha = io->a;
|
| if (alpha != NULL) {
|
| const int mb_w = io->mb_w;
|
| @@ -244,7 +214,6 @@ static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p) {
|
| #endif
|
| uint32_t alpha_mask = 0x0f;
|
| int i, j;
|
| -
|
| for (j = 0; j < num_rows; ++j) {
|
| for (i = 0; i < mb_w; ++i) {
|
| // Fill in the alpha value (converted to 4 bits).
|
| @@ -255,6 +224,8 @@ static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p) {
|
| alpha += io->width;
|
| alpha_dst += buf->stride;
|
| }
|
| + (void)expected_num_lines_out;
|
| + assert(expected_num_lines_out == num_rows);
|
| if (alpha_mask != 0x0f && WebPIsPremultipliedMode(colorspace)) {
|
| WebPApplyAlphaMultiply4444(base_rgba, mb_w, num_rows, buf->stride);
|
| }
|
| @@ -296,12 +267,15 @@ static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) {
|
| return num_lines_out;
|
| }
|
|
|
| -static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p) {
|
| +static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p,
|
| + int expected_num_lines_out) {
|
| if (io->a != NULL) {
|
| const WebPYUVABuffer* const buf = &p->output->u.YUVA;
|
| uint8_t* dst_y = buf->y + p->last_y * buf->y_stride;
|
| const uint8_t* src_a = buf->a + p->last_y * buf->a_stride;
|
| const int num_lines_out = Rescale(io->a, io->width, io->mb_h, &p->scaler_a);
|
| + (void)expected_num_lines_out;
|
| + assert(expected_num_lines_out == num_lines_out);
|
| if (num_lines_out > 0) { // unmultiply the Y
|
| WebPMultRows(dst_y, buf->y_stride, src_a, buf->a_stride,
|
| p->scaler_a.dst_width, num_lines_out, 1);
|
| @@ -361,13 +335,13 @@ static int ExportRGB(WebPDecParams* const p, int y_pos) {
|
| const WebPYUV444Converter convert =
|
| WebPYUV444Converters[p->output->colorspace];
|
| const WebPRGBABuffer* const buf = &p->output->u.RGBA;
|
| - uint8_t* dst = buf->rgba + (p->last_y + y_pos) * buf->stride;
|
| + uint8_t* dst = buf->rgba + y_pos * buf->stride;
|
| int num_lines_out = 0;
|
| // For RGB rescaling, because of the YUV420, current scan position
|
| // U/V can be +1/-1 line from the Y one. Hence the double test.
|
| while (WebPRescalerHasPendingOutput(&p->scaler_y) &&
|
| WebPRescalerHasPendingOutput(&p->scaler_u)) {
|
| - assert(p->last_y + y_pos + num_lines_out < p->output->height);
|
| + assert(y_pos + num_lines_out < p->output->height);
|
| assert(p->scaler_u.y_accum == p->scaler_v.y_accum);
|
| WebPRescalerExportRow(&p->scaler_y);
|
| WebPRescalerExportRow(&p->scaler_u);
|
| @@ -389,55 +363,54 @@ static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) {
|
| const int y_lines_in =
|
| WebPRescalerImport(&p->scaler_y, mb_h - j,
|
| io->y + j * io->y_stride, io->y_stride);
|
| - const int u_lines_in =
|
| - WebPRescalerImport(&p->scaler_u, uv_mb_h - uv_j,
|
| - io->u + uv_j * io->uv_stride, io->uv_stride);
|
| - const int v_lines_in =
|
| - WebPRescalerImport(&p->scaler_v, uv_mb_h - uv_j,
|
| - io->v + uv_j * io->uv_stride, io->uv_stride);
|
| - (void)v_lines_in; // remove a gcc warning
|
| - assert(u_lines_in == v_lines_in);
|
| j += y_lines_in;
|
| - uv_j += u_lines_in;
|
| - num_lines_out += ExportRGB(p, num_lines_out);
|
| + if (WebPRescaleNeededLines(&p->scaler_u, uv_mb_h - uv_j)) {
|
| + const int u_lines_in =
|
| + WebPRescalerImport(&p->scaler_u, uv_mb_h - uv_j,
|
| + io->u + uv_j * io->uv_stride, io->uv_stride);
|
| + const int v_lines_in =
|
| + WebPRescalerImport(&p->scaler_v, uv_mb_h - uv_j,
|
| + io->v + uv_j * io->uv_stride, io->uv_stride);
|
| + (void)v_lines_in; // remove a gcc warning
|
| + assert(u_lines_in == v_lines_in);
|
| + uv_j += u_lines_in;
|
| + }
|
| + num_lines_out += ExportRGB(p, p->last_y + num_lines_out);
|
| }
|
| return num_lines_out;
|
| }
|
|
|
| -static int ExportAlpha(WebPDecParams* const p, int y_pos) {
|
| +static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) {
|
| const WebPRGBABuffer* const buf = &p->output->u.RGBA;
|
| - uint8_t* const base_rgba = buf->rgba + (p->last_y + y_pos) * buf->stride;
|
| + uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride;
|
| const WEBP_CSP_MODE colorspace = p->output->colorspace;
|
| const int alpha_first =
|
| (colorspace == MODE_ARGB || colorspace == MODE_Argb);
|
| uint8_t* dst = base_rgba + (alpha_first ? 0 : 3);
|
| int num_lines_out = 0;
|
| const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
|
| - uint32_t alpha_mask = 0xff;
|
| + uint32_t non_opaque = 0;
|
| const int width = p->scaler_a.dst_width;
|
|
|
| - while (WebPRescalerHasPendingOutput(&p->scaler_a)) {
|
| - int i;
|
| - assert(p->last_y + y_pos + num_lines_out < p->output->height);
|
| + while (WebPRescalerHasPendingOutput(&p->scaler_a) &&
|
| + num_lines_out < max_lines_out) {
|
| + assert(y_pos + num_lines_out < p->output->height);
|
| WebPRescalerExportRow(&p->scaler_a);
|
| - for (i = 0; i < width; ++i) {
|
| - const uint32_t alpha_value = p->scaler_a.dst[i];
|
| - dst[4 * i] = alpha_value;
|
| - alpha_mask &= alpha_value;
|
| - }
|
| + non_opaque |= WebPDispatchAlpha(p->scaler_a.dst, 0, width, 1, dst, 0);
|
| dst += buf->stride;
|
| ++num_lines_out;
|
| }
|
| - if (is_premult_alpha && alpha_mask != 0xff) {
|
| + if (is_premult_alpha && non_opaque) {
|
| WebPApplyAlphaMultiply(base_rgba, alpha_first,
|
| width, num_lines_out, buf->stride);
|
| }
|
| return num_lines_out;
|
| }
|
|
|
| -static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos) {
|
| +static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos,
|
| + int max_lines_out) {
|
| const WebPRGBABuffer* const buf = &p->output->u.RGBA;
|
| - uint8_t* const base_rgba = buf->rgba + (p->last_y + y_pos) * buf->stride;
|
| + uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride;
|
| #ifdef WEBP_SWAP_16BIT_CSP
|
| uint8_t* alpha_dst = base_rgba;
|
| #else
|
| @@ -449,9 +422,10 @@ static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos) {
|
| const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
|
| uint32_t alpha_mask = 0x0f;
|
|
|
| - while (WebPRescalerHasPendingOutput(&p->scaler_a)) {
|
| + while (WebPRescalerHasPendingOutput(&p->scaler_a) &&
|
| + num_lines_out < max_lines_out) {
|
| int i;
|
| - assert(p->last_y + y_pos + num_lines_out < p->output->height);
|
| + assert(y_pos + num_lines_out < p->output->height);
|
| WebPRescalerExportRow(&p->scaler_a);
|
| for (i = 0; i < width; ++i) {
|
| // Fill in the alpha value (converted to 4 bits).
|
| @@ -468,15 +442,17 @@ static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos) {
|
| return num_lines_out;
|
| }
|
|
|
| -static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
|
| +static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p,
|
| + int expected_num_out_lines) {
|
| if (io->a != NULL) {
|
| WebPRescaler* const scaler = &p->scaler_a;
|
| - int j = 0;
|
| - int pos = 0;
|
| - while (j < io->mb_h) {
|
| - j += WebPRescalerImport(scaler, io->mb_h - j,
|
| - io->a + j * io->width, io->width);
|
| - pos += p->emit_alpha_row(p, pos);
|
| + int lines_left = expected_num_out_lines;
|
| + const int y_end = p->last_y + lines_left;
|
| + while (lines_left > 0) {
|
| + const int row_offset = scaler->src_y - io->mb_y;
|
| + WebPRescalerImport(scaler, io->mb_h + io->mb_y - scaler->src_y,
|
| + io->a + row_offset * io->width, io->width);
|
| + lines_left -= p->emit_alpha_row(p, y_end - lines_left, lines_left);
|
| }
|
| }
|
| return 0;
|
| @@ -516,6 +492,7 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
| tmp + 2 * out_width, out_width, out_height, 0, 1,
|
| work + 2 * work_size);
|
| p->emit = EmitRescaledRGB;
|
| + WebPInitYUV444Converters();
|
|
|
| if (has_alpha) {
|
| WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h,
|
| @@ -559,6 +536,7 @@ static int CustomSetup(VP8Io* io) {
|
| }
|
| } else {
|
| if (is_rgb) {
|
| + WebPInitSamplers();
|
| p->emit = EmitSampledRGB; // default
|
| if (io->fancy_upsampling) {
|
| #ifdef FANCY_UPSAMPLING
|
| @@ -573,8 +551,6 @@ static int CustomSetup(VP8Io* io) {
|
| p->emit = EmitFancyRGB;
|
| WebPInitUpsamplers();
|
| #endif
|
| - } else {
|
| - WebPInitSamplers();
|
| }
|
| } else {
|
| p->emit = EmitYUV;
|
| @@ -611,7 +587,7 @@ static int CustomPut(const VP8Io* io) {
|
| }
|
| num_lines_out = p->emit(io, p);
|
| if (p->emit_alpha != NULL) {
|
| - p->emit_alpha(io, p);
|
| + p->emit_alpha(io, p, num_lines_out);
|
| }
|
| p->last_y += num_lines_out;
|
| return 1;
|
|
|