From 399b916d27fc569b8adb12ed029796edaf669726 Mon Sep 17 00:00:00 2001 From: skal Date: Mon, 26 May 2014 18:05:03 +0200 Subject: [PATCH] lossy decoding: correct alpha-rescaling for YUVA format The luminance needs to be pre- and post- multiplied by the alpha value in case of rescaling, for proper averaging. Also: - removed util/alpha_processing and moved it to dsp/ - removed WebPInitPremultiply() which was mostly useless and merged it with the new function WebPInitAlphaProcessing() Change-Id: If089cefd4ec53f6880a791c476fb1c7f7c5a8e60 --- Android.mk | 2 +- Makefile.vc | 2 +- makefile.unix | 3 +- src/dec/io.c | 36 +++++-- src/dec/vp8l.c | 4 +- src/dsp/Makefile.am | 1 + src/{utils => dsp}/alpha_processing.c | 134 +++++++++++++++++++++++--- src/dsp/dsp.h | 29 +++++- src/dsp/upsampling.c | 120 +---------------------- src/dsp/upsampling_neon.c | 8 +- src/dsp/upsampling_sse2.c | 8 +- src/enc/picture.c | 25 ++--- src/utils/Makefile.am | 2 - src/utils/alpha_processing.h | 46 --------- 14 files changed, 193 insertions(+), 227 deletions(-) rename src/{utils => dsp}/alpha_processing.c (72%) delete mode 100644 src/utils/alpha_processing.h diff --git a/Android.mk b/Android.mk index 36808db3..a4e323c0 100644 --- a/Android.mk +++ b/Android.mk @@ -32,6 +32,7 @@ LOCAL_SRC_FILES := \ src/dec/vp8.c \ src/dec/vp8l.c \ src/dec/webp.c \ + src/dsp/alpha_processing.c \ src/dsp/cpu.c \ src/dsp/dec.c \ src/dsp/dec_clip_tables.c \ @@ -68,7 +69,6 @@ LOCAL_SRC_FILES := \ src/enc/tree.c \ src/enc/vp8l.c \ src/enc/webpenc.c \ - src/utils/alpha_processing.c \ src/utils/bit_reader.c \ src/utils/bit_writer.c \ src/utils/color_cache.c \ diff --git a/Makefile.vc b/Makefile.vc index 43ff6019..017d720a 100644 --- a/Makefile.vc +++ b/Makefile.vc @@ -170,6 +170,7 @@ DEMUX_OBJS = \ $(DIROBJ)\demux\demux.obj \ DSP_DEC_OBJS = \ + $(DIROBJ)\dsp\alpha_processing.obj \ $(DIROBJ)\dsp\cpu.obj \ $(DIROBJ)\dsp\dec.obj \ $(DIROBJ)\dsp\dec_clip_tables.obj \ @@ -228,7 +229,6 @@ MUX_OBJS = \ $(DIROBJ)\mux\muxread.obj \ UTILS_DEC_OBJS = \ - $(DIROBJ)\utils\alpha_processing.obj \ $(DIROBJ)\utils\bit_reader.obj \ $(DIROBJ)\utils\color_cache.obj \ $(DIROBJ)\utils\filters.obj \ diff --git a/makefile.unix b/makefile.unix index b261ccb9..36892202 100644 --- a/makefile.unix +++ b/makefile.unix @@ -106,6 +106,7 @@ DEMUX_OBJS = \ src/demux/demux.o \ DSP_DEC_OBJS = \ + src/dsp/alpha_processing.o \ src/dsp/cpu.o \ src/dsp/dec.o \ src/dsp/dec_clip_tables.o \ @@ -166,7 +167,6 @@ MUX_OBJS = \ src/mux/muxread.o \ UTILS_DEC_OBJS = \ - src/utils/alpha_processing.o \ src/utils/bit_reader.o \ src/utils/color_cache.o \ src/utils/filters.o \ @@ -213,7 +213,6 @@ HDRS = \ src/enc/vp8enci.h \ src/enc/vp8li.h \ src/mux/muxi.h \ - src/utils/alpha_processing.h \ src/utils/bit_reader.h \ src/utils/bit_writer.h \ src/utils/color_cache.h \ diff --git a/src/dec/io.c b/src/dec/io.c index df6bc4e0..8094e44f 100644 --- a/src/dec/io.c +++ b/src/dec/io.c @@ -280,7 +280,17 @@ static int Rescale(const uint8_t* src, int src_stride, static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) { const int mb_h = io->mb_h; const int uv_mb_h = (mb_h + 1) >> 1; - const int num_lines_out = Rescale(io->y, io->y_stride, mb_h, &p->scaler_y); + WebPRescaler* const scaler = &p->scaler_y; + int num_lines_out = 0; + if (WebPIsAlphaMode(p->output->colorspace) && io->a != NULL) { + // Before rescaling, we premultiply the luma directly into the io->y + // internal buffer. This is OK since these samples are not used for + // intra-prediction (the top samples are saved in cache_y_/u_/v_). + // But we need to cast the const away, though. + WebPMultRows((uint8_t*)io->y, io->y_stride, + io->a, io->width, io->mb_w, mb_h, 0); + } + num_lines_out = Rescale(io->y, io->y_stride, mb_h, scaler); Rescale(io->u, io->uv_stride, uv_mb_h, &p->scaler_u); Rescale(io->v, io->uv_stride, uv_mb_h, &p->scaler_v); return num_lines_out; @@ -288,7 +298,14 @@ static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) { static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p) { if (io->a != NULL) { - Rescale(io->a, io->width, io->mb_h, &p->scaler_a); + 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); + 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); + } } return 0; } @@ -307,11 +324,11 @@ static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) { size_t tmp_size; int32_t* work; - tmp_size = work_size + 2 * uv_work_size; + tmp_size = (work_size + 2 * uv_work_size) * sizeof(*work); if (has_alpha) { - tmp_size += work_size; + tmp_size += work_size * sizeof(*work); } - p->memory = WebPSafeCalloc(1ULL, tmp_size * sizeof(*work)); + p->memory = WebPSafeCalloc(1ULL, tmp_size); if (p->memory == NULL) { return 0; // memory error } @@ -338,6 +355,7 @@ static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) { io->mb_w, out_width, io->mb_h, out_height, work + work_size + 2 * uv_work_size); p->emit_alpha = EmitRescaledAlphaYUV; + WebPInitAlphaProcessing(); } return 1; } @@ -520,6 +538,7 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) { } else { p->emit_alpha_row = ExportAlpha; } + WebPInitAlphaProcessing(); } return 1; } @@ -540,7 +559,9 @@ static int CustomSetup(VP8Io* io) { if (!WebPIoInitFromOptions(p->options, io, is_alpha ? MODE_YUV : MODE_YUVA)) { return 0; } - if (is_alpha && WebPIsPremultipliedMode(colorspace)) WebPInitPremultiply(); + if (is_alpha && WebPIsPremultipliedMode(colorspace)) { + WebPInitUpsamplers(); + } if (io->use_scaling) { const int ok = is_rgb ? InitRGBRescaler(io, p) : InitYUVRescaler(io, p); if (!ok) { @@ -574,6 +595,9 @@ static int CustomSetup(VP8Io* io) { EmitAlphaRGBA4444 : is_rgb ? EmitAlphaRGB : EmitAlphaYUV; + if (is_rgb) { + WebPInitAlphaProcessing(); + } } } diff --git a/src/dec/vp8l.c b/src/dec/vp8l.c index 270047e3..f08631bc 100644 --- a/src/dec/vp8l.c +++ b/src/dec/vp8l.c @@ -16,9 +16,9 @@ #include "./alphai.h" #include "./vp8li.h" +#include "../dsp/dsp.h" #include "../dsp/lossless.h" #include "../dsp/yuv.h" -#include "../utils/alpha_processing.h" #include "../utils/huffman.h" #include "../utils/utils.h" @@ -412,6 +412,7 @@ static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) { WebPRescalerInit(dec->rescaler, in_width, in_height, (uint8_t*)scaled_data, out_width, out_height, 0, num_channels, in_width, out_width, in_height, out_height, work); + WebPInitAlphaProcessing(); // needed for pre/post multiply with alpha return 1; } @@ -474,6 +475,7 @@ static int EmitRows(WEBP_CSP_MODE colorspace, //------------------------------------------------------------------------------ // Export to YUVA +// TODO(skal): should be in yuv.c static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos, const WebPDecBuffer* const output) { const WebPYUVABuffer* const buf = &output->u.YUVA; diff --git a/src/dsp/Makefile.am b/src/dsp/Makefile.am index 4f07606d..c6a833a2 100644 --- a/src/dsp/Makefile.am +++ b/src/dsp/Makefile.am @@ -9,6 +9,7 @@ common_HEADERS = ../webp/types.h commondir = $(includedir)/webp COMMON_SOURCES = +COMMON_SOURCES += alpha_processing.c COMMON_SOURCES += cpu.c COMMON_SOURCES += dec.c COMMON_SOURCES += dec_clip_tables.c diff --git a/src/utils/alpha_processing.c b/src/dsp/alpha_processing.c similarity index 72% rename from src/utils/alpha_processing.c rename to src/dsp/alpha_processing.c index 7362ff94..09deacfb 100644 --- a/src/utils/alpha_processing.c +++ b/src/dsp/alpha_processing.c @@ -12,7 +12,7 @@ // Author: Skal (pascal.massimino@gmail.com) #include -#include "./alpha_processing.h" +#include "./dsp.h" // Tables can be faster on some platform but incur some extra binary size (~2k). // #define USE_TABLES_FOR_ALPHA_MULT @@ -134,7 +134,7 @@ static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) { #endif // USE_TABLES_FOR_ALPHA_MULT -void WebPMultARGBRow(uint32_t* const ptr, int width, int inverse) { +static void MultARGBRow(uint32_t* const ptr, int width, int inverse) { int x; for (x = 0; x < width; ++x) { const uint32_t argb = ptr[x]; @@ -154,17 +154,8 @@ void WebPMultARGBRow(uint32_t* const ptr, int width, int inverse) { } } -void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows, - int inverse) { - int n; - for (n = 0; n < num_rows; ++n) { - WebPMultARGBRow((uint32_t*)ptr, width, inverse); - ptr += stride; - } -} - -void WebPMultRow(uint8_t* const ptr, const uint8_t* const alpha, - int width, int inverse) { +static void MultRow(uint8_t* const ptr, const uint8_t* const alpha, + int width, int inverse) { int x; for (x = 0; x < width; ++x) { const uint32_t a = alpha[x]; @@ -179,6 +170,26 @@ void WebPMultRow(uint8_t* const ptr, const uint8_t* const alpha, } } +#undef KINV_255 +#undef HALF +#undef MFIX + +void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse); +void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha, + int width, int inverse); + +//------------------------------------------------------------------------------ +// Generic per-plane calls + +void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows, + int inverse) { + int n; + for (n = 0; n < num_rows; ++n) { + WebPMultARGBRow((uint32_t*)ptr, width, inverse); + ptr += stride; + } +} + void WebPMultRows(uint8_t* ptr, int stride, const uint8_t* alpha, int alpha_stride, int width, int num_rows, int inverse) { @@ -190,7 +201,98 @@ void WebPMultRows(uint8_t* ptr, int stride, } } -#undef KINV_255 -#undef HALF -#undef MFIX +//------------------------------------------------------------------------------ +// Premultiplied modes +// non dithered-modes + +// (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.) +// for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5), +// one can use instead: (x * a * 65793 + (1 << 23)) >> 24 +#if 1 // (int)(x * a / 255.) +#define MULTIPLIER(a) ((a) * 32897U) +#define PREMULTIPLY(x, m) (((x) * (m)) >> 23) +#else // (int)(x * a / 255. + .5) +#define MULTIPLIER(a) ((a) * 65793U) +#define PREMULTIPLY(x, m) (((x) * (m) + (1U << 23)) >> 24) +#endif + +static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first, + int w, int h, int stride) { + while (h-- > 0) { + uint8_t* const rgb = rgba + (alpha_first ? 1 : 0); + const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3); + int i; + for (i = 0; i < w; ++i) { + const uint32_t a = alpha[4 * i]; + if (a != 0xff) { + const uint32_t mult = MULTIPLIER(a); + rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult); + rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult); + rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult); + } + } + rgba += stride; + } +} +#undef MULTIPLIER +#undef PREMULTIPLY + +// rgbA4444 + +#define MULTIPLIER(a) ((a) * 0x1111) // 0x1111 ~= (1 << 16) / 15 + +static WEBP_INLINE uint8_t dither_hi(uint8_t x) { + return (x & 0xf0) | (x >> 4); +} + +static WEBP_INLINE uint8_t dither_lo(uint8_t x) { + return (x & 0x0f) | (x << 4); +} + +static WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) { + return (x * m) >> 16; +} + +static WEBP_INLINE void ApplyAlphaMultiply4444(uint8_t* rgba4444, + int w, int h, int stride, + int rg_byte_pos /* 0 or 1 */) { + while (h-- > 0) { + int i; + for (i = 0; i < w; ++i) { + const uint32_t rg = rgba4444[2 * i + rg_byte_pos]; + const uint32_t ba = rgba4444[2 * i + (rg_byte_pos ^ 1)]; + const uint8_t a = ba & 0x0f; + const uint32_t mult = MULTIPLIER(a); + const uint8_t r = multiply(dither_hi(rg), mult); + const uint8_t g = multiply(dither_lo(rg), mult); + const uint8_t b = multiply(dither_hi(ba), mult); + rgba4444[2 * i + rg_byte_pos] = (r & 0xf0) | ((g >> 4) & 0x0f); + rgba4444[2 * i + (rg_byte_pos ^ 1)] = (b & 0xf0) | a; + } + rgba4444 += stride; + } +} +#undef MULTIPLIER + +static void ApplyAlphaMultiply_16b(uint8_t* rgba4444, + int w, int h, int stride) { +#ifdef WEBP_SWAP_16BIT_CSP + ApplyAlphaMultiply4444(rgba4444, w, h, stride, 1); +#else + ApplyAlphaMultiply4444(rgba4444, w, h, stride, 0); +#endif +} + +void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int); +void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int); + +//------------------------------------------------------------------------------ +// Init function + +void WebPInitAlphaProcessing(void) { + WebPMultARGBRow = MultARGBRow; + WebPMultRow = MultRow; + WebPApplyAlphaMultiply = ApplyAlphaMultiply; + WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b; +} diff --git a/src/dsp/dsp.h b/src/dsp/dsp.h index d69244ed..51c3bb8e 100644 --- a/src/dsp/dsp.h +++ b/src/dsp/dsp.h @@ -218,12 +218,14 @@ typedef void (*WebPYUV444Converter)(const uint8_t* y, extern const WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */]; -// Main functions to be called +// Must be called before using the WebPUpsamplers[] (and for premultiplied +// colorspaces like rgbA, rgbA4444, etc) void WebPInitUpsamplers(void); +// Must be called before using WebPSamplers[] void WebPInitSamplers(void); //------------------------------------------------------------------------------ -// Pre-multiply planes with alpha values +// Utilities for processing transparent channel. // Apply alpha pre-multiply on an rgba, bgra or argb plane of size w * h. // alpha_first should be 0 for argb, 1 for rgba or bgra (where alpha is last). @@ -234,10 +236,27 @@ extern void (*WebPApplyAlphaMultiply)( extern void (*WebPApplyAlphaMultiply4444)( uint8_t* rgba4444, int w, int h, int stride); -// To be called first before using the above. -void WebPInitPremultiply(void); +// Pre-Multiply operation transforms x into x * A / 255 (where x=Y,R,G or B). +// Un-Multiply operation transforms x into x * 255 / A. -//------------------------------------------------------------------------------ +// Pre-Multiply or Un-Multiply (if 'inverse' is true) argb values in a row. +extern void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse); + +// Same a WebPMultARGBRow(), but for several rows. +void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows, + int inverse); + +// Same for a row of single values, with side alpha values. +extern void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha, + int width, int inverse); + +// Same a WebPMultRow(), but for several 'num_rows' rows. +void WebPMultRows(uint8_t* ptr, int stride, + const uint8_t* alpha, int alpha_stride, + int width, int num_rows, int inverse); + +// To be called first before using the above. +void WebPInitAlphaProcessing(void); #ifdef __cplusplus } // extern "C" diff --git a/src/dsp/upsampling.c b/src/dsp/upsampling.c index 8712618b..2b1656bf 100644 --- a/src/dsp/upsampling.c +++ b/src/dsp/upsampling.c @@ -183,92 +183,6 @@ const WebPYUV444Converter WebPYUV444Converters[MODE_LAST] = { Yuv444ToRgba4444 // MODE_rgbA_4444 }; -//------------------------------------------------------------------------------ -// Premultiplied modes - -// non dithered-modes - -// (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.) -// for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5), -// one can use instead: (x * a * 65793 + (1 << 23)) >> 24 -#if 1 // (int)(x * a / 255.) -#define MULTIPLIER(a) ((a) * 32897UL) -#define PREMULTIPLY(x, m) (((x) * (m)) >> 23) -#else // (int)(x * a / 255. + .5) -#define MULTIPLIER(a) ((a) * 65793UL) -#define PREMULTIPLY(x, m) (((x) * (m) + (1UL << 23)) >> 24) -#endif - -static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first, - int w, int h, int stride) { - while (h-- > 0) { - uint8_t* const rgb = rgba + (alpha_first ? 1 : 0); - const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3); - int i; - for (i = 0; i < w; ++i) { - const uint32_t a = alpha[4 * i]; - if (a != 0xff) { - const uint32_t mult = MULTIPLIER(a); - rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult); - rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult); - rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult); - } - } - rgba += stride; - } -} -#undef MULTIPLIER -#undef PREMULTIPLY - -// rgbA4444 - -#define MULTIPLIER(a) ((a) * 0x1111) // 0x1111 ~= (1 << 16) / 15 - -static WEBP_INLINE uint8_t dither_hi(uint8_t x) { - return (x & 0xf0) | (x >> 4); -} - -static WEBP_INLINE uint8_t dither_lo(uint8_t x) { - return (x & 0x0f) | (x << 4); -} - -static WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) { - return (x * m) >> 16; -} - -static WEBP_INLINE void ApplyAlphaMultiply4444(uint8_t* rgba4444, - int w, int h, int stride, - int rg_byte_pos /* 0 or 1 */) { - while (h-- > 0) { - int i; - for (i = 0; i < w; ++i) { - const uint32_t rg = rgba4444[2 * i + rg_byte_pos]; - const uint32_t ba = rgba4444[2 * i + (rg_byte_pos ^ 1)]; - const uint8_t a = ba & 0x0f; - const uint32_t mult = MULTIPLIER(a); - const uint8_t r = multiply(dither_hi(rg), mult); - const uint8_t g = multiply(dither_lo(rg), mult); - const uint8_t b = multiply(dither_hi(ba), mult); - rgba4444[2 * i + rg_byte_pos] = (r & 0xf0) | ((g >> 4) & 0x0f); - rgba4444[2 * i + (rg_byte_pos ^ 1)] = (b & 0xf0) | a; - } - rgba4444 += stride; - } -} -#undef MULTIPLIER - -static void ApplyAlphaMultiply_16b(uint8_t* rgba4444, - int w, int h, int stride) { -#ifdef WEBP_SWAP_16BIT_CSP - ApplyAlphaMultiply4444(rgba4444, w, h, stride, 1); -#else - ApplyAlphaMultiply4444(rgba4444, w, h, stride, 0); -#endif -} - -void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int); -void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int); - //------------------------------------------------------------------------------ // Main calls @@ -284,6 +198,10 @@ void WebPInitUpsamplers(void) { WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; + WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; + WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; // If defined, use CPUInfo() to overwrite some pointers with faster versions. if (VP8GetCPUInfo != NULL) { @@ -302,33 +220,3 @@ void WebPInitUpsamplers(void) { } //------------------------------------------------------------------------------ - -extern void WebPInitPremultiplySSE2(void); -extern void WebPInitPremultiplyNEON(void); - -void WebPInitPremultiply(void) { - WebPApplyAlphaMultiply = ApplyAlphaMultiply; - WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b; - -#ifdef FANCY_UPSAMPLING - WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; - - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - WebPInitPremultiplySSE2(); - } -#endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - WebPInitPremultiplyNEON(); - } -#endif - } -#endif // FANCY_UPSAMPLING -} - -//------------------------------------------------------------------------------ diff --git a/src/dsp/upsampling_neon.c b/src/dsp/upsampling_neon.c index 59b03bc9..ce27f494 100644 --- a/src/dsp/upsampling_neon.c +++ b/src/dsp/upsampling_neon.c @@ -237,7 +237,6 @@ NEON_UPSAMPLE_FUNC(UpsampleBgraLinePair, Bgra, 4) //------------------------------------------------------------------------------ extern void WebPInitUpsamplersNEON(void); -extern void WebPInitPremultiplyNEON(void); #ifdef FANCY_UPSAMPLING @@ -249,11 +248,6 @@ void WebPInitUpsamplersNEON(void) { WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; -#endif // WEBP_USE_NEON -} - -void WebPInitPremultiplyNEON(void) { -#if defined(WEBP_USE_NEON) WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; #endif // WEBP_USE_NEON @@ -262,6 +256,6 @@ void WebPInitPremultiplyNEON(void) { #else // this empty function is to avoid an empty .o -void WebPInitPremultiplyNEON(void) {} +void WebPInitUpsamplersNEON(void) {} #endif // FANCY_UPSAMPLING diff --git a/src/dsp/upsampling_sse2.c b/src/dsp/upsampling_sse2.c index a327d197..45cf0906 100644 --- a/src/dsp/upsampling_sse2.c +++ b/src/dsp/upsampling_sse2.c @@ -189,7 +189,6 @@ SSE2_UPSAMPLE_FUNC(UpsampleBgraLinePair, VP8YuvToBgra, 4) //------------------------------------------------------------------------------ extern void WebPInitUpsamplersSSE2(void); -extern void WebPInitPremultiplySSE2(void); #ifdef FANCY_UPSAMPLING @@ -202,11 +201,6 @@ void WebPInitUpsamplersSSE2(void) { WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; -#endif // WEBP_USE_SSE2 -} - -void WebPInitPremultiplySSE2(void) { -#if defined(WEBP_USE_SSE2) WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; #endif // WEBP_USE_SSE2 @@ -215,6 +209,6 @@ void WebPInitPremultiplySSE2(void) { #else // this empty function is to avoid an empty .o -void WebPInitPremultiplySSE2(void) {} +void WebPInitUpsamplersSSE2(void) {} #endif // FANCY_UPSAMPLING diff --git a/src/enc/picture.c b/src/enc/picture.c index c45a7e27..c4777531 100644 --- a/src/enc/picture.c +++ b/src/enc/picture.c @@ -16,7 +16,6 @@ #include #include "./vp8enci.h" -#include "../utils/alpha_processing.h" #include "../utils/random.h" #include "../utils/rescaler.h" #include "../utils/utils.h" @@ -402,24 +401,15 @@ static void RescalePlane(const uint8_t* src, } static void AlphaMultiplyARGB(WebPPicture* const pic, int inverse) { - uint32_t* ptr = pic->argb; - int y; - for (y = 0; y < pic->height; ++y) { - WebPMultARGBRow(ptr, pic->width, inverse); - ptr += pic->argb_stride; - } + assert(pic->argb != NULL); + WebPMultARGBRows((uint8_t*)pic->argb, pic->argb_stride * sizeof(*pic->argb), + pic->width, pic->height, inverse); } static void AlphaMultiplyY(WebPPicture* const pic, int inverse) { - const uint8_t* ptr_a = pic->a; - if (ptr_a != NULL) { - uint8_t* ptr_y = pic->y; - int y; - for (y = 0; y < pic->height; ++y) { - WebPMultRow(ptr_y, ptr_a, pic->width, inverse); - ptr_y += pic->y_stride; - ptr_a += pic->a_stride; - } + if (pic->a != NULL) { + WebPMultRows(pic->y, pic->y_stride, pic->a, pic->a_stride, + pic->width, pic->height, inverse); } } @@ -455,6 +445,7 @@ int WebPPictureRescale(WebPPicture* pic, int width, int height) { } // If present, we need to rescale alpha first (for AlphaMultiplyY). if (pic->a != NULL) { + WebPInitAlphaProcessing(); RescalePlane(pic->a, prev_width, prev_height, pic->a_stride, tmp.a, width, height, tmp.a_stride, work, 1); } @@ -495,6 +486,7 @@ int WebPPictureRescale(WebPPicture* pic, int width, int height) { // In order to correctly interpolate colors, we need to apply the alpha // weighting first (black-matting), scale the RGB values, and remove // the premultiplication afterward (while preserving the alpha channel). + WebPInitAlphaProcessing(); AlphaMultiplyARGB(pic, 0); RescalePlane((const uint8_t*)pic->argb, prev_width, prev_height, pic->argb_stride * 4, @@ -1367,4 +1359,3 @@ LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGRA, WebPPictureImportBGRA) #undef LOSSLESS_ENCODE_FUNC //------------------------------------------------------------------------------ - diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am index 86dc6f30..ac2db270 100644 --- a/src/utils/Makefile.am +++ b/src/utils/Makefile.am @@ -9,8 +9,6 @@ common_HEADERS = ../webp/types.h commondir = $(includedir)/webp COMMON_SOURCES = -COMMON_SOURCES += alpha_processing.c -COMMON_SOURCES += alpha_processing.h COMMON_SOURCES += bit_reader.c COMMON_SOURCES += bit_reader.h COMMON_SOURCES += color_cache.c diff --git a/src/utils/alpha_processing.h b/src/utils/alpha_processing.h deleted file mode 100644 index 80e1ae45..00000000 --- a/src/utils/alpha_processing.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Utilities for processing transparent channel. -// -// Author: Skal (pascal.massimino@gmail.com) - -#ifndef WEBP_UTILS_ALPHA_PROCESSING_H_ -#define WEBP_UTILS_ALPHA_PROCESSING_H_ - -#include "../webp/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Pre-Multiply operation transforms x into x * A / 255 (where x=Y,R,G or B). -// Un-Multiply operation transforms x into x * 255 / A. - -// Pre-Multiply or Un-Multiply (if 'inverse' is true) argb values in a row. -void WebPMultARGBRow(uint32_t* const ptr, int width, int inverse); - -// Same a WebPMultARGBRow(), but for several rows. -void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows, - int inverse); - -// Same for a row of single values, with side alpha values. -void WebPMultRow(uint8_t* const ptr, const uint8_t* const alpha, - int width, int inverse); - -// Same a WebPMultRow(), but for several 'num_rows' rows. -void WebPMultRows(uint8_t* ptr, int stride, - const uint8_t* alpha, int alpha_stride, - int width, int num_rows, int inverse); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // WEBP_UTILS_ALPHA_PROCESSING_H_