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) { |