Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(636)

Unified Diff: third_party/libwebp/dec/io.c

Issue 10832153: libwebp: update snapshot to v0.2.0-rc1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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) {

Powered by Google App Engine
This is Rietveld 408576698