| Index: third_party/libwebp/dec/io.c
|
| diff --git a/third_party/libwebp/dec/io.c b/third_party/libwebp/dec/io.c
|
| index ee6f352bb1eea529d39fbc3a72f2953dbb3df11a..2c75f78256f5e02a6b4886a42841404a65ad911f 100644
|
| --- a/third_party/libwebp/dec/io.c
|
| +++ b/third_party/libwebp/dec/io.c
|
| @@ -1,4 +1,4 @@
|
| -// Copyright 2011 Google Inc.
|
| +// Copyright 2011 Google Inc. All Rights Reserved.
|
| //
|
| // This code is licensed under the same terms as WebM:
|
| // Software License Agreement: http://www.webmproject.org/license/software/
|
| @@ -32,11 +32,12 @@ static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) {
|
| const int mb_w = io->mb_w;
|
| const int mb_h = io->mb_h;
|
| const int uv_w = (mb_w + 1) / 2;
|
| + const int uv_h = (mb_h + 1) / 2;
|
| int j;
|
| for (j = 0; j < mb_h; ++j) {
|
| memcpy(y_dst + j * buf->y_stride, io->y + j * io->y_stride, mb_w);
|
| }
|
| - for (j = 0; j < (mb_h + 1) / 2; ++j) {
|
| + for (j = 0; j < uv_h; ++j) {
|
| memcpy(u_dst + j * buf->u_stride, io->u + j * io->uv_stride, uv_w);
|
| memcpy(v_dst + j * buf->v_stride, io->v + j * io->uv_stride, uv_w);
|
| }
|
| @@ -103,9 +104,7 @@ static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) {
|
| int num_lines_out = io->mb_h; // a priori guess
|
| const WebPRGBABuffer* const buf = &p->output->u.RGBA;
|
| uint8_t* dst = buf->rgba + io->mb_y * buf->stride;
|
| - const WebPUpsampleLinePairFunc upsample =
|
| - io->a ? WebPUpsamplersKeepAlpha[p->output->colorspace]
|
| - : WebPUpsamplers[p->output->colorspace];
|
| + WebPUpsampleLinePairFunc upsample = WebPUpsamplers[p->output->colorspace];
|
| const uint8_t* cur_y = io->y;
|
| const uint8_t* cur_u = io->u;
|
| const uint8_t* cur_v = io->v;
|
| @@ -121,11 +120,9 @@ static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) {
|
| upsample(NULL, cur_y, cur_u, cur_v, cur_u, cur_v, NULL, dst, mb_w);
|
| } else {
|
| // We can finish the left-over line from previous call.
|
| - // Warning! Don't overwrite the alpha values (if any), as they
|
| - // are not lagging one line behind but are already written.
|
| upsample(p->tmp_y, cur_y, top_u, top_v, cur_u, cur_v,
|
| dst - buf->stride, dst, mb_w);
|
| - num_lines_out++;
|
| + ++num_lines_out;
|
| }
|
| // Loop over each output pairs of row.
|
| for (; y + 2 < y_end; y += 2) {
|
| @@ -163,151 +160,114 @@ static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) {
|
|
|
| //------------------------------------------------------------------------------
|
|
|
| -#ifdef WEBP_EXPERIMENTAL_FEATURES
|
| static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p) {
|
| + 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;
|
| - int j;
|
| - const WebPYUVABuffer* const buf = &p->output->u.YUVA;
|
| uint8_t* dst = buf->a + io->mb_y * buf->a_stride;
|
| - const uint8_t* alpha = io->a;
|
| - if (alpha) {
|
| + int j;
|
| +
|
| + if (alpha != NULL) {
|
| for (j = 0; j < mb_h; ++j) {
|
| memcpy(dst, alpha, mb_w * sizeof(*dst));
|
| alpha += io->width;
|
| dst += buf->a_stride;
|
| }
|
| + } else if (buf->a != NULL) {
|
| + // the user requested alpha, but there is none, set it to opaque.
|
| + for (j = 0; j < mb_h; ++j) {
|
| + memset(dst, 0xff, mb_w * sizeof(*dst));
|
| + dst += buf->a_stride;
|
| + }
|
| }
|
| return 0;
|
| }
|
|
|
| static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
|
| - const int mb_w = io->mb_w;
|
| - const int mb_h = io->mb_h;
|
| - int i, j;
|
| - const WebPRGBABuffer* const buf = &p->output->u.RGBA;
|
| - uint8_t* dst = buf->rgba + io->mb_y * buf->stride;
|
| const uint8_t* alpha = io->a;
|
| - if (alpha) {
|
| - for (j = 0; j < mb_h; ++j) {
|
| - for (i = 0; i < mb_w; ++i) {
|
| - dst[4 * i + 3] = alpha[i];
|
| + if (alpha != NULL) {
|
| + const int mb_w = io->mb_w;
|
| + const int mb_h = io->mb_h;
|
| + int i, j;
|
| + const WEBP_CSP_MODE colorspace = p->output->colorspace;
|
| + const int alpha_first =
|
| + (colorspace == MODE_ARGB || colorspace == MODE_Argb);
|
| + const WebPRGBABuffer* const buf = &p->output->u.RGBA;
|
| + int start_y = io->mb_y;
|
| + int num_rows = mb_h;
|
| +
|
| + // We compensate for the 1-line delay of fancy upscaler.
|
| + // This is similar to EmitFancyRGB().
|
| + if (io->fancy_upsampling) {
|
| + if (start_y == 0) {
|
| + // We don't process the last row yet. It'll be done during next call.
|
| + --num_rows;
|
| + } else {
|
| + --start_y;
|
| + // Fortunately, *alpha data is persistent, so we can go back
|
| + // one row and finish alpha blending, now that the fancy upscaler
|
| + // completed the YUV->RGB interpolation.
|
| + alpha -= io->width;
|
| + }
|
| + if (io->crop_top + io->mb_y + mb_h == io->crop_bottom) {
|
| + // If it's the very last call, we process all the remaing rows!
|
| + num_rows = io->crop_bottom - io->crop_top - start_y;
|
| + }
|
| + }
|
| + {
|
| + uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
|
| + uint8_t* dst = base_rgba + (alpha_first ? 0 : 3);
|
| + for (j = 0; j < num_rows; ++j) {
|
| + for (i = 0; i < mb_w; ++i) dst[4 * i] = alpha[i];
|
| + alpha += io->width;
|
| + dst += buf->stride;
|
| + }
|
| + if (WebPIsPremultipliedMode(colorspace)) {
|
| + WebPApplyAlphaMultiply(base_rgba, alpha_first,
|
| + mb_w, num_rows, buf->stride);
|
| }
|
| - alpha += io->width;
|
| - dst += buf->stride;
|
| }
|
| }
|
| return 0;
|
| }
|
|
|
| -#endif /* WEBP_EXPERIMENTAL_FEATURES */
|
| -
|
| -//------------------------------------------------------------------------------
|
| -// Simple picture rescaler
|
| -
|
| -// TODO(skal): start a common library for encoder and decoder, and factorize
|
| -// this code in.
|
| -
|
| -#define RFIX 30
|
| -#define MULT(x,y) (((int64_t)(x) * (y) + (1 << (RFIX - 1))) >> RFIX)
|
| -
|
| -static void InitRescaler(WebPRescaler* const wrk,
|
| - int src_width, int src_height,
|
| - uint8_t* dst,
|
| - int dst_width, int dst_height, int dst_stride,
|
| - int x_add, int x_sub, int y_add, int y_sub,
|
| - int32_t* work) {
|
| - wrk->x_expand = (src_width < dst_width);
|
| - wrk->src_width = src_width;
|
| - wrk->src_height = src_height;
|
| - wrk->dst_width = dst_width;
|
| - wrk->dst_height = dst_height;
|
| - wrk->dst = dst;
|
| - wrk->dst_stride = dst_stride;
|
| - // for 'x_expand', we use bilinear interpolation
|
| - wrk->x_add = wrk->x_expand ? (x_sub - 1) : x_add - x_sub;
|
| - wrk->x_sub = wrk->x_expand ? (x_add - 1) : x_sub;
|
| - wrk->y_accum = y_add;
|
| - wrk->y_add = y_add;
|
| - wrk->y_sub = y_sub;
|
| - wrk->fx_scale = (1 << RFIX) / x_sub;
|
| - wrk->fy_scale = (1 << RFIX) / y_sub;
|
| - wrk->fxy_scale = wrk->x_expand ?
|
| - ((int64_t)dst_height << RFIX) / (x_sub * src_height) :
|
| - ((int64_t)dst_height << RFIX) / (x_add * src_height);
|
| - wrk->irow = work;
|
| - wrk->frow = work + dst_width;
|
| -}
|
| -
|
| -static inline void ImportRow(const uint8_t* const src,
|
| - WebPRescaler* const wrk) {
|
| - int x_in = 0;
|
| - int x_out;
|
| - int accum = 0;
|
| - if (!wrk->x_expand) {
|
| - int sum = 0;
|
| - for (x_out = 0; x_out < wrk->dst_width; ++x_out) {
|
| - accum += wrk->x_add;
|
| - for (; accum > 0; accum -= wrk->x_sub) {
|
| - sum += src[x_in++];
|
| - }
|
| - { // Emit next horizontal pixel.
|
| - const int32_t base = src[x_in++];
|
| - const int32_t frac = base * (-accum);
|
| - wrk->frow[x_out] = (sum + base) * wrk->x_sub - frac;
|
| - // fresh fractional start for next pixel
|
| - sum = (int)MULT(frac, wrk->fx_scale);
|
| +static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p) {
|
| + const uint8_t* alpha = io->a;
|
| + if (alpha != NULL) {
|
| + const int mb_w = io->mb_w;
|
| + const int mb_h = io->mb_h;
|
| + int i, j;
|
| + const WebPRGBABuffer* const buf = &p->output->u.RGBA;
|
| + uint8_t* const base_rgba = buf->rgba + io->mb_y * buf->stride;
|
| + uint8_t* alpha_dst = base_rgba + 1;
|
| + for (j = 0; j < mb_h; ++j) {
|
| + for (i = 0; i < mb_w; ++i) {
|
| + // Fill in the alpha value (converted to 4 bits).
|
| + const uint32_t alpha_val = VP8Clip4Bits(alpha[i]);
|
| + alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_val;
|
| }
|
| + alpha += io->width;
|
| + alpha_dst += buf->stride;
|
| }
|
| - } else { // simple bilinear interpolation
|
| - int left = src[0], right = src[0];
|
| - for (x_out = 0; x_out < wrk->dst_width; ++x_out) {
|
| - if (accum < 0) {
|
| - left = right;
|
| - right = src[++x_in];
|
| - accum += wrk->x_add;
|
| - }
|
| - wrk->frow[x_out] = right * wrk->x_add + (left - right) * accum;
|
| - accum -= wrk->x_sub;
|
| + if (p->output->colorspace == MODE_rgbA_4444) {
|
| + WebPApplyAlphaMultiply4444(base_rgba, mb_w, mb_h, buf->stride);
|
| }
|
| }
|
| - // Accumulate the new row's contribution
|
| - for (x_out = 0; x_out < wrk->dst_width; ++x_out) {
|
| - wrk->irow[x_out] += wrk->frow[x_out];
|
| - }
|
| -}
|
| -
|
| -static void ExportRow(WebPRescaler* const wrk) {
|
| - int x_out;
|
| - const int yscale = wrk->fy_scale * (-wrk->y_accum);
|
| - assert(wrk->y_accum <= 0);
|
| - for (x_out = 0; x_out < wrk->dst_width; ++x_out) {
|
| - const int frac = (int)MULT(wrk->frow[x_out], yscale);
|
| - const int v = (int)MULT(wrk->irow[x_out] - frac, wrk->fxy_scale);
|
| - wrk->dst[x_out] = (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255;
|
| - wrk->irow[x_out] = frac; // new fractional start
|
| - }
|
| - wrk->y_accum += wrk->y_add;
|
| - wrk->dst += wrk->dst_stride;
|
| + return 0;
|
| }
|
|
|
| -#undef MULT
|
| -#undef RFIX
|
| -
|
| //------------------------------------------------------------------------------
|
| // YUV rescaling (no final RGB conversion needed)
|
|
|
| static int Rescale(const uint8_t* src, int src_stride,
|
| int new_lines, WebPRescaler* const wrk) {
|
| int num_lines_out = 0;
|
| - while (new_lines-- > 0) { // import new contribution of one source row.
|
| - ImportRow(src, wrk);
|
| - src += src_stride;
|
| - wrk->y_accum -= wrk->y_sub;
|
| - while (wrk->y_accum <= 0) { // emit output row(s)
|
| - ExportRow(wrk);
|
| - num_lines_out++;
|
| - }
|
| + while (new_lines > 0) { // import new contributions of source rows.
|
| + const int lines_in = WebPRescalerImport(wrk, new_lines, src, src_stride);
|
| + src += lines_in * src_stride;
|
| + new_lines -= lines_in;
|
| + num_lines_out += WebPRescalerExport(wrk); // emit output row(s)
|
| }
|
| return num_lines_out;
|
| }
|
| @@ -322,19 +282,14 @@ static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) {
|
| }
|
|
|
| static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p) {
|
| - if (io->a) {
|
| + if (io->a != NULL) {
|
| Rescale(io->a, io->width, io->mb_h, &p->scaler_a);
|
| }
|
| return 0;
|
| }
|
|
|
| -static int IsAlphaMode(WEBP_CSP_MODE mode) {
|
| - return (mode == MODE_RGBA || mode == MODE_BGRA || mode == MODE_ARGB ||
|
| - mode == MODE_RGBA_4444 || mode == MODE_YUVA);
|
| -}
|
| -
|
| static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
| - const int has_alpha = IsAlphaMode(p->output->colorspace);
|
| + const int has_alpha = WebPIsAlphaMode(p->output->colorspace);
|
| const WebPYUVABuffer* const buf = &p->output->u.YUVA;
|
| const int out_width = io->scaled_width;
|
| const int out_height = io->scaled_height;
|
| @@ -356,26 +311,27 @@ static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
| return 0; // memory error
|
| }
|
| work = (int32_t*)p->memory;
|
| - InitRescaler(&p->scaler_y, io->mb_w, io->mb_h,
|
| - buf->y, out_width, out_height, buf->y_stride,
|
| - io->mb_w, out_width, io->mb_h, out_height,
|
| - work);
|
| - InitRescaler(&p->scaler_u, uv_in_width, uv_in_height,
|
| - buf->u, uv_out_width, uv_out_height, buf->u_stride,
|
| - uv_in_width, uv_out_width,
|
| - uv_in_height, uv_out_height,
|
| - work + work_size);
|
| - InitRescaler(&p->scaler_v, uv_in_width, uv_in_height,
|
| - buf->v, uv_out_width, uv_out_height, buf->v_stride,
|
| - uv_in_width, uv_out_width,
|
| - uv_in_height, uv_out_height,
|
| - work + work_size + uv_work_size);
|
| + WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h,
|
| + buf->y, out_width, out_height, buf->y_stride, 1,
|
| + io->mb_w, out_width, io->mb_h, out_height,
|
| + work);
|
| + WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height,
|
| + buf->u, uv_out_width, uv_out_height, buf->u_stride, 1,
|
| + uv_in_width, uv_out_width,
|
| + uv_in_height, uv_out_height,
|
| + work + work_size);
|
| + WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height,
|
| + buf->v, uv_out_width, uv_out_height, buf->v_stride, 1,
|
| + uv_in_width, uv_out_width,
|
| + uv_in_height, uv_out_height,
|
| + work + work_size + uv_work_size);
|
| p->emit = EmitRescaledYUV;
|
| +
|
| if (has_alpha) {
|
| - InitRescaler(&p->scaler_a, io->mb_w, io->mb_h,
|
| - buf->a, out_width, out_height, buf->a_stride,
|
| - io->mb_w, out_width, io->mb_h, out_height,
|
| - work + work_size + 2 * uv_work_size);
|
| + WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h,
|
| + buf->a, out_width, out_height, buf->a_stride, 1,
|
| + io->mb_w, out_width, io->mb_h, out_height,
|
| + work + work_size + 2 * uv_work_size);
|
| p->emit_alpha = EmitRescaledAlphaYUV;
|
| }
|
| return 1;
|
| @@ -384,20 +340,6 @@ static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
| //------------------------------------------------------------------------------
|
| // RGBA rescaling
|
|
|
| -// import new contributions until one row is ready to be output, or all input
|
| -// is consumed.
|
| -static int Import(const uint8_t* src, int src_stride,
|
| - int new_lines, WebPRescaler* const wrk) {
|
| - int num_lines_in = 0;
|
| - while (num_lines_in < new_lines && wrk->y_accum > 0) {
|
| - ImportRow(src, wrk);
|
| - src += src_stride;
|
| - ++num_lines_in;
|
| - wrk->y_accum -= wrk->y_sub;
|
| - }
|
| - return num_lines_in;
|
| -}
|
| -
|
| static int ExportRGB(WebPDecParams* const p, int y_pos) {
|
| const WebPYUV444Converter convert =
|
| WebPYUV444Converters[p->output->colorspace];
|
| @@ -406,16 +348,17 @@ static int ExportRGB(WebPDecParams* const p, int y_pos) {
|
| 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 (p->scaler_y.y_accum <= 0 && p->scaler_u.y_accum <= 0) {
|
| + while (WebPRescalerHasPendingOutput(&p->scaler_y) &&
|
| + WebPRescalerHasPendingOutput(&p->scaler_u)) {
|
| assert(p->last_y + y_pos + num_lines_out < p->output->height);
|
| assert(p->scaler_u.y_accum == p->scaler_v.y_accum);
|
| - ExportRow(&p->scaler_y);
|
| - ExportRow(&p->scaler_u);
|
| - ExportRow(&p->scaler_v);
|
| + WebPRescalerExportRow(&p->scaler_y);
|
| + WebPRescalerExportRow(&p->scaler_u);
|
| + WebPRescalerExportRow(&p->scaler_v);
|
| convert(p->scaler_y.dst, p->scaler_u.dst, p->scaler_v.dst,
|
| dst, p->scaler_y.dst_width);
|
| dst += buf->stride;
|
| - num_lines_out++;
|
| + ++num_lines_out;
|
| }
|
| return num_lines_out;
|
| }
|
| @@ -426,12 +369,15 @@ static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) {
|
| int j = 0, uv_j = 0;
|
| int num_lines_out = 0;
|
| while (j < mb_h) {
|
| - const int y_lines_in = Import(io->y + j * io->y_stride, io->y_stride,
|
| - mb_h - j, &p->scaler_y);
|
| - const int u_lines_in = Import(io->u + uv_j * io->uv_stride, io->uv_stride,
|
| - uv_mb_h - uv_j, &p->scaler_u);
|
| - const int v_lines_in = Import(io->v + uv_j * io->uv_stride, io->uv_stride,
|
| - uv_mb_h - uv_j, &p->scaler_v);
|
| + 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;
|
| @@ -443,34 +389,73 @@ static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) {
|
|
|
| static int ExportAlpha(WebPDecParams* const p, int y_pos) {
|
| const WebPRGBABuffer* const buf = &p->output->u.RGBA;
|
| - uint8_t* dst = buf->rgba + (p->last_y + y_pos) * buf->stride;
|
| + uint8_t* const base_rgba = buf->rgba + (p->last_y + 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;
|
| - while (p->scaler_a.y_accum <= 0) {
|
| + const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
|
| + 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);
|
| - ExportRow(&p->scaler_a);
|
| - for (i = 0; i < p->scaler_a.dst_width; ++i) {
|
| - dst[4 * i + 3] = p->scaler_a.dst[i];
|
| - }
|
| + WebPRescalerExportRow(&p->scaler_a);
|
| + for (i = 0; i < width; ++i) dst[4 * i] = p->scaler_a.dst[i];
|
| dst += buf->stride;
|
| - num_lines_out++;
|
| + ++num_lines_out;
|
| + }
|
| + if (is_premult_alpha) {
|
| + WebPApplyAlphaMultiply(base_rgba, alpha_first,
|
| + width, num_lines_out, buf->stride);
|
| + }
|
| + return num_lines_out;
|
| +}
|
| +
|
| +static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos) {
|
| + const WebPRGBABuffer* const buf = &p->output->u.RGBA;
|
| + uint8_t* const base_rgba = buf->rgba + (p->last_y + y_pos) * buf->stride;
|
| + uint8_t* alpha_dst = base_rgba + 1;
|
| + int num_lines_out = 0;
|
| + const WEBP_CSP_MODE colorspace = p->output->colorspace;
|
| + const int width = p->scaler_a.dst_width;
|
| + const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
|
| +
|
| + while (WebPRescalerHasPendingOutput(&p->scaler_a)) {
|
| + int i;
|
| + assert(p->last_y + 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).
|
| + const uint32_t alpha_val = VP8Clip4Bits(p->scaler_a.dst[i]);
|
| + alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_val;
|
| + }
|
| + alpha_dst += buf->stride;
|
| + ++num_lines_out;
|
| + }
|
| + if (is_premult_alpha) {
|
| + WebPApplyAlphaMultiply4444(base_rgba, width, num_lines_out, buf->stride);
|
| }
|
| return num_lines_out;
|
| }
|
|
|
| static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
|
| - if (io->a) {
|
| - int j = 0, pos = 0;
|
| + if (io->a != NULL) {
|
| + WebPRescaler* const scaler = &p->scaler_a;
|
| + int j = 0;
|
| + int pos = 0;
|
| while (j < io->mb_h) {
|
| - j += Import(io->a + j * io->width, io->width, io->mb_h - j, &p->scaler_a);
|
| - pos += ExportAlpha(p, pos);
|
| + j += WebPRescalerImport(scaler, io->mb_h - j,
|
| + io->a + j * io->width, io->width);
|
| + pos += p->emit_alpha_row(p, pos);
|
| }
|
| }
|
| return 0;
|
| }
|
|
|
| static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
| - const int has_alpha = IsAlphaMode(p->output->colorspace);
|
| + const int has_alpha = WebPIsAlphaMode(p->output->colorspace);
|
| const int out_width = io->scaled_width;
|
| const int out_height = io->scaled_height;
|
| const int uv_in_width = (io->mb_w + 1) >> 1;
|
| @@ -493,26 +478,32 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
| }
|
| work = (int32_t*)p->memory;
|
| tmp = (uint8_t*)(work + tmp_size1);
|
| - InitRescaler(&p->scaler_y, io->mb_w, io->mb_h,
|
| - tmp + 0 * out_width, out_width, out_height, 0,
|
| - io->mb_w, out_width, io->mb_h, out_height,
|
| - work + 0 * work_size);
|
| - InitRescaler(&p->scaler_u, uv_in_width, uv_in_height,
|
| - tmp + 1 * out_width, out_width, out_height, 0,
|
| - io->mb_w, 2 * out_width, io->mb_h, 2 * out_height,
|
| - work + 1 * work_size);
|
| - InitRescaler(&p->scaler_v, uv_in_width, uv_in_height,
|
| - tmp + 2 * out_width, out_width, out_height, 0,
|
| - io->mb_w, 2 * out_width, io->mb_h, 2 * out_height,
|
| - work + 2 * work_size);
|
| + WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h,
|
| + tmp + 0 * out_width, out_width, out_height, 0, 1,
|
| + io->mb_w, out_width, io->mb_h, out_height,
|
| + work + 0 * work_size);
|
| + WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height,
|
| + tmp + 1 * out_width, out_width, out_height, 0, 1,
|
| + io->mb_w, 2 * out_width, io->mb_h, 2 * out_height,
|
| + work + 1 * work_size);
|
| + WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height,
|
| + tmp + 2 * out_width, out_width, out_height, 0, 1,
|
| + io->mb_w, 2 * out_width, io->mb_h, 2 * out_height,
|
| + work + 2 * work_size);
|
| p->emit = EmitRescaledRGB;
|
|
|
| if (has_alpha) {
|
| - InitRescaler(&p->scaler_a, io->mb_w, io->mb_h,
|
| - tmp + 3 * out_width, out_width, out_height, 0,
|
| - io->mb_w, out_width, io->mb_h, out_height,
|
| - work + 3 * work_size);
|
| + WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h,
|
| + tmp + 3 * out_width, out_width, out_height, 0, 1,
|
| + io->mb_w, out_width, io->mb_h, out_height,
|
| + work + 3 * work_size);
|
| p->emit_alpha = EmitRescaledAlphaRGB;
|
| + if (p->output->colorspace == MODE_RGBA_4444 ||
|
| + p->output->colorspace == MODE_rgbA_4444) {
|
| + p->emit_alpha_row = ExportAlphaRGBA4444;
|
| + } else {
|
| + p->emit_alpha_row = ExportAlpha;
|
| + }
|
| }
|
| return 1;
|
| }
|
| @@ -520,67 +511,17 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
| //------------------------------------------------------------------------------
|
| // Default custom functions
|
|
|
| -// Setup crop_xxx fields, mb_w and mb_h
|
| -static int InitFromOptions(const WebPDecoderOptions* const options,
|
| - VP8Io* const io) {
|
| - const int W = io->width;
|
| - const int H = io->height;
|
| - int x = 0, y = 0, w = W, h = H;
|
| -
|
| - // Cropping
|
| - io->use_cropping = (options != NULL) && (options->use_cropping > 0);
|
| - if (io->use_cropping) {
|
| - w = options->crop_width;
|
| - h = options->crop_height;
|
| - // TODO(skal): take colorspace into account. Don't assume YUV420.
|
| - x = options->crop_left & ~1;
|
| - y = options->crop_top & ~1;
|
| - if (x < 0 || y < 0 || w <= 0 || h <= 0 || x + w > W || y + h > H) {
|
| - return 0; // out of frame boundary error
|
| - }
|
| - }
|
| - io->crop_left = x;
|
| - io->crop_top = y;
|
| - io->crop_right = x + w;
|
| - io->crop_bottom = y + h;
|
| - io->mb_w = w;
|
| - io->mb_h = h;
|
| -
|
| - // Scaling
|
| - io->use_scaling = (options != NULL) && (options->use_scaling > 0);
|
| - if (io->use_scaling) {
|
| - if (options->scaled_width <= 0 || options->scaled_height <= 0) {
|
| - return 0;
|
| - }
|
| - io->scaled_width = options->scaled_width;
|
| - io->scaled_height = options->scaled_height;
|
| - }
|
| -
|
| - // Filter
|
| - io->bypass_filtering = options && options->bypass_filtering;
|
| -
|
| - // Fancy upsampler
|
| -#ifdef FANCY_UPSAMPLING
|
| - io->fancy_upsampling = (options == NULL) || (!options->no_fancy_upsampling);
|
| -#endif
|
| -
|
| - if (io->use_scaling) {
|
| - // disable filter (only for large downscaling ratio).
|
| - io->bypass_filtering = (io->scaled_width < W * 3 / 4) &&
|
| - (io->scaled_height < H * 3 / 4);
|
| - io->fancy_upsampling = 0;
|
| - }
|
| - return 1;
|
| -}
|
| -
|
| static int CustomSetup(VP8Io* io) {
|
| WebPDecParams* const p = (WebPDecParams*)io->opaque;
|
| - const int is_rgb = (p->output->colorspace < MODE_YUV);
|
| + const WEBP_CSP_MODE colorspace = p->output->colorspace;
|
| + const int is_rgb = WebPIsRGBMode(colorspace);
|
| + const int is_alpha = WebPIsAlphaMode(colorspace);
|
|
|
| p->memory = NULL;
|
| p->emit = NULL;
|
| p->emit_alpha = NULL;
|
| - if (!InitFromOptions(p->options, io)) {
|
| + p->emit_alpha_row = NULL;
|
| + if (!WebPIoInitFromOptions(p->options, io, is_alpha ? MODE_YUV : MODE_YUVA)) {
|
| return 0;
|
| }
|
|
|
| @@ -609,12 +550,14 @@ static int CustomSetup(VP8Io* io) {
|
| } else {
|
| p->emit = EmitYUV;
|
| }
|
| -#ifdef WEBP_EXPERIMENTAL_FEATURES
|
| - if (IsAlphaMode(p->output->colorspace)) {
|
| - // We need transparency output
|
| - p->emit_alpha = is_rgb ? EmitAlphaRGB : EmitAlphaYUV;
|
| + if (is_alpha) { // need transparency output
|
| + if (WebPIsPremultipliedMode(colorspace)) WebPInitPremultiply();
|
| + p->emit_alpha =
|
| + (colorspace == MODE_RGBA_4444 || colorspace == MODE_rgbA_4444) ?
|
| + EmitAlphaRGBA4444
|
| + : is_rgb ? EmitAlphaRGB
|
| + : EmitAlphaYUV;
|
| }
|
| -#endif
|
| }
|
|
|
| if (is_rgb) {
|
|
|