Index: third_party/libwebp/dsp/upsampling.c |
diff --git a/third_party/libwebp/dsp/upsampling.c b/third_party/libwebp/dsp/upsampling.c |
index c88a17ad9bebd99c3ce613705e6e05f36e323a9b..9ca04927b9b639c5e31acd6360647179afe5b52c 100644 |
--- a/third_party/libwebp/dsp/upsampling.c |
+++ b/third_party/libwebp/dsp/upsampling.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/ |
@@ -11,7 +11,6 @@ |
#include "./dsp.h" |
#include "./yuv.h" |
-#include "../dec/webpi.h" |
#if defined(__cplusplus) || defined(c_plusplus) |
extern "C" { |
@@ -24,7 +23,6 @@ extern "C" { |
// Fancy upsampling functions to convert YUV to RGB |
WebPUpsampleLinePairFunc WebPUpsamplers[MODE_LAST]; |
-WebPUpsampleLinePairFunc WebPUpsamplersKeepAlpha[MODE_LAST]; |
// Given samples laid out in a square as: |
// [a b] |
@@ -101,11 +99,6 @@ UPSAMPLE_FUNC(UpsampleBgraLinePair, VP8YuvToBgra, 4) |
UPSAMPLE_FUNC(UpsampleArgbLinePair, VP8YuvToArgb, 4) |
UPSAMPLE_FUNC(UpsampleRgba4444LinePair, VP8YuvToRgba4444, 2) |
UPSAMPLE_FUNC(UpsampleRgb565LinePair, VP8YuvToRgb565, 2) |
-// These two don't erase the alpha value |
-UPSAMPLE_FUNC(UpsampleRgbKeepAlphaLinePair, VP8YuvToRgb, 4) |
-UPSAMPLE_FUNC(UpsampleBgrKeepAlphaLinePair, VP8YuvToBgr, 4) |
-UPSAMPLE_FUNC(UpsampleArgbKeepAlphaLinePair, VP8YuvToArgbKeepA, 4) |
-UPSAMPLE_FUNC(UpsampleRgba4444KeepAlphaLinePair, VP8YuvToRgba4444KeepA, 2) |
#undef LOAD_UV |
#undef UPSAMPLE_FUNC |
@@ -156,10 +149,56 @@ const WebPSampleLinePairFunc WebPSamplers[MODE_LAST] = { |
SampleBgraLinePair, // MODE_BGRA |
SampleArgbLinePair, // MODE_ARGB |
SampleRgba4444LinePair, // MODE_RGBA_4444 |
- SampleRgb565LinePair // MODE_RGB_565 |
+ SampleRgb565LinePair, // MODE_RGB_565 |
+ SampleRgbaLinePair, // MODE_rgbA |
+ SampleBgraLinePair, // MODE_bgrA |
+ SampleArgbLinePair, // MODE_Argb |
+ SampleRgba4444LinePair // MODE_rgbA_4444 |
}; |
//------------------------------------------------------------------------------ |
+ |
+#if !defined(FANCY_UPSAMPLING) |
+#define DUAL_SAMPLE_FUNC(FUNC_NAME, FUNC) \ |
+static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \ |
+ const uint8_t* top_u, const uint8_t* top_v, \ |
+ const uint8_t* bot_u, const uint8_t* bot_v, \ |
+ uint8_t* top_dst, uint8_t* bot_dst, int len) { \ |
+ const int half_len = len >> 1; \ |
+ int x; \ |
+ if (top_dst != NULL) { \ |
+ for (x = 0; x < half_len; ++x) { \ |
+ FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x + 0); \ |
+ FUNC(top_y[2 * x + 1], top_u[x], top_v[x], top_dst + 8 * x + 4); \ |
+ } \ |
+ if (len & 1) FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x); \ |
+ } \ |
+ if (bot_dst != NULL) { \ |
+ for (x = 0; x < half_len; ++x) { \ |
+ FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x + 0); \ |
+ FUNC(bot_y[2 * x + 1], bot_u[x], bot_v[x], bot_dst + 8 * x + 4); \ |
+ } \ |
+ if (len & 1) FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x); \ |
+ } \ |
+} |
+ |
+DUAL_SAMPLE_FUNC(DualLineSamplerBGRA, VP8YuvToBgra) |
+DUAL_SAMPLE_FUNC(DualLineSamplerARGB, VP8YuvToArgb) |
+#undef DUAL_SAMPLE_FUNC |
+ |
+#endif // !FANCY_UPSAMPLING |
+ |
+WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last) { |
+ WebPInitUpsamplers(); |
+ VP8YUVInit(); |
+#ifdef FANCY_UPSAMPLING |
+ return WebPUpsamplers[alpha_is_last ? MODE_BGRA : MODE_ARGB]; |
+#else |
+ return (alpha_is_last ? DualLineSamplerBGRA : DualLineSamplerARGB); |
+#endif |
+} |
+ |
+//------------------------------------------------------------------------------ |
// YUV444 converter |
#define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \ |
@@ -186,10 +225,88 @@ const WebPYUV444Converter WebPYUV444Converters[MODE_LAST] = { |
Yuv444ToBgra, // MODE_BGRA |
Yuv444ToArgb, // MODE_ARGB |
Yuv444ToRgba4444, // MODE_RGBA_4444 |
- Yuv444ToRgb565 // MODE_RGB_565 |
+ Yuv444ToRgb565, // MODE_RGB_565 |
+ Yuv444ToRgba, // MODE_rgbA |
+ Yuv444ToBgra, // MODE_bgrA |
+ Yuv444ToArgb, // MODE_Argb |
+ 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) * 0x11) |
+#define PREMULTIPLY(x, m) (((x) * (m)) >> 12) |
+ |
+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 void ApplyAlphaMultiply4444(uint8_t* rgba4444, |
+ int w, int h, int stride) { |
+ while (h-- > 0) { |
+ int i; |
+ for (i = 0; i < w; ++i) { |
+ const uint8_t a = dither_lo(rgba4444[2 * i + 1]); |
+ const uint32_t mult = MULTIPLIER(a); |
+ const uint8_t r = PREMULTIPLY(dither_hi(rgba4444[2 * i + 0]), mult); |
+ const uint8_t g = PREMULTIPLY(dither_lo(rgba4444[2 * i + 0]), mult); |
+ const uint8_t b = PREMULTIPLY(dither_hi(rgba4444[2 * i + 1]), mult); |
+ rgba4444[2 * i + 0] = (r & 0xf0) | (g & 0x0f); |
+ rgba4444[2 * i + 1] = (b & 0xf0) | a; |
+ } |
+ rgba4444 += stride; |
+ } |
+} |
+#undef MULTIPLIER |
+#undef PREMULTIPLY |
+ |
+void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int) |
+ = ApplyAlphaMultiply; |
+void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int) |
+ = ApplyAlphaMultiply4444; |
+ |
+//------------------------------------------------------------------------------ |
// Main call |
void WebPInitUpsamplers(void) { |
@@ -202,17 +319,9 @@ void WebPInitUpsamplers(void) { |
WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; |
WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; |
- WebPUpsamplersKeepAlpha[MODE_RGB] = UpsampleRgbLinePair; |
- WebPUpsamplersKeepAlpha[MODE_RGBA] = UpsampleRgbKeepAlphaLinePair; |
- WebPUpsamplersKeepAlpha[MODE_BGR] = UpsampleBgrLinePair; |
- WebPUpsamplersKeepAlpha[MODE_BGRA] = UpsampleBgrKeepAlphaLinePair; |
- WebPUpsamplersKeepAlpha[MODE_ARGB] = UpsampleArgbKeepAlphaLinePair; |
- WebPUpsamplersKeepAlpha[MODE_RGBA_4444] = UpsampleRgba4444KeepAlphaLinePair; |
- WebPUpsamplersKeepAlpha[MODE_RGB_565] = UpsampleRgb565LinePair; |
- |
// If defined, use CPUInfo() to overwrite some pointers with faster versions. |
- if (VP8GetCPUInfo) { |
-#if defined(__SSE2__) || defined(_MSC_VER) |
+ if (VP8GetCPUInfo != NULL) { |
+#if defined(WEBP_USE_SSE2) |
if (VP8GetCPUInfo(kSSE2)) { |
WebPInitUpsamplersSSE2(); |
} |
@@ -221,6 +330,26 @@ void WebPInitUpsamplers(void) { |
#endif // FANCY_UPSAMPLING |
} |
+void WebPInitPremultiply(void) { |
+ WebPApplyAlphaMultiply = ApplyAlphaMultiply; |
+ WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply4444; |
+ |
+#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 |
+ } |
+#endif // FANCY_UPSAMPLING |
+} |
+ |
#if defined(__cplusplus) || defined(c_plusplus) |
} // extern "C" |
#endif |