From 44a0ee3fa711be899da9f55ce857627d7d6e8dda Mon Sep 17 00:00:00 2001 From: Pascal Massimino Date: Thu, 16 Nov 2017 06:59:52 -0800 Subject: [PATCH] introduce WebPHasAlpha8b and WebPHasAlpha32b Rewrote WebPPictureHasTransparency() to use them (even for argb). This is 10% faster, for some reasons. SSE2 version should be straightforward. Removes a TODO. Change-Id: I7ad5848fc5e355e2df505dbcd5a0f42fb6cbab41 --- src/dsp/alpha_processing.c | 21 +++++++++++++++++++++ src/dsp/dsp.h | 5 +++++ src/enc/picture_csp_enc.c | 27 ++++++++++++--------------- 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/dsp/alpha_processing.c b/src/dsp/alpha_processing.c index dfead26d..590e3bc3 100644 --- a/src/dsp/alpha_processing.c +++ b/src/dsp/alpha_processing.c @@ -346,6 +346,19 @@ static void ExtractGreen_C(const uint32_t* argb, uint8_t* alpha, int size) { } #endif // !WEBP_NEON_OMIT_C_CODE +//------------------------------------------------------------------------------ + +static int HasAlpha8b_C(const uint8_t* src, int length) { + while (length-- > 0) if (*src++ != 0xff) return 1; + return 0; +} + +static int HasAlpha32b_C(const uint8_t* src, int length) { + int x; + for (x = 0; length-- > 0; x += 4) if (src[x] != 0xff) return 1; + return 0; +} + //------------------------------------------------------------------------------ // Simple channel manipulations. @@ -371,6 +384,9 @@ void (*WebPExtractGreen)(const uint32_t* argb, uint8_t* alpha, int size); void (*WebPPackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b, int len, int step, uint32_t* out); +int (*WebPHasAlpha8b)(const uint8_t* src, int length); +int (*WebPHasAlpha32b)(const uint8_t* src, int length); + //------------------------------------------------------------------------------ // Init function @@ -398,6 +414,9 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessing(void) { WebPExtractGreen = ExtractGreen_C; #endif + WebPHasAlpha8b = HasAlpha8b_C; + WebPHasAlpha32b = HasAlpha32b_C; + // If defined, use CPUInfo() to overwrite some pointers with faster versions. if (VP8GetCPUInfo != NULL) { #if defined(WEBP_USE_SSE2) @@ -433,6 +452,8 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessing(void) { assert(WebPExtractAlpha != NULL); assert(WebPExtractGreen != NULL); assert(WebPPackRGB != NULL); + assert(WebPHasAlpha8b != NULL); + assert(WebPHasAlpha32b != NULL); alpha_processing_last_cpuinfo_used = VP8GetCPUInfo; } diff --git a/src/dsp/dsp.h b/src/dsp/dsp.h index d2001121..7a87595c 100644 --- a/src/dsp/dsp.h +++ b/src/dsp/dsp.h @@ -578,6 +578,11 @@ void WebPMultARGBRow_C(uint32_t* const ptr, int width, int inverse); extern void (*WebPPackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b, int len, int step, uint32_t* out); +// This function returns true if src[i] contains a value different from 0xff. +extern int (*WebPHasAlpha8b)(const uint8_t* src, int length); +// This function returns true if src[4*i] contains a value different from 0xff. +extern int (*WebPHasAlpha32b)(const uint8_t* src, int length); + // To be called first before using the above. void WebPInitAlphaProcessing(void); diff --git a/src/enc/picture_csp_enc.c b/src/enc/picture_csp_enc.c index 62be097b..cf5170b3 100644 --- a/src/enc/picture_csp_enc.c +++ b/src/enc/picture_csp_enc.c @@ -41,12 +41,15 @@ static const union { static int CheckNonOpaque(const uint8_t* alpha, int width, int height, int x_step, int y_step) { if (alpha == NULL) return 0; - while (height-- > 0) { - int x; - for (x = 0; x < width * x_step; x += x_step) { - if (alpha[x] != 0xff) return 1; // TODO(skal): check 4/8 bytes at a time. + WebPInitAlphaProcessing(); + if (x_step == 1) { + for (; height-- > 0; alpha += y_step) { + if (WebPHasAlpha8b(alpha, width)) return 1; + } + } else { + for (; height-- > 0; alpha += y_step) { + if (WebPHasAlpha32b(alpha, width)) return 1; } - alpha += y_step; } return 0; } @@ -58,15 +61,10 @@ int WebPPictureHasTransparency(const WebPPicture* picture) { return CheckNonOpaque(picture->a, picture->width, picture->height, 1, picture->a_stride); } else { - int x, y; - const uint32_t* argb = picture->argb; - if (argb == NULL) return 0; - for (y = 0; y < picture->height; ++y) { - for (x = 0; x < picture->width; ++x) { - if (argb[x] < 0xff000000u) return 1; // test any alpha values != 0xff - } - argb += picture->argb_stride; - } + const int alpha_offset = ALPHA_IS_LAST ? 3 : 0; + return CheckNonOpaque((const uint8_t*)picture->argb + alpha_offset, + picture->width, picture->height, + 4, picture->argb_stride * sizeof(*picture->argb)); } return 0; } @@ -858,7 +856,6 @@ static int ImportYUVAFromRGBA(const uint8_t* r_ptr, return 0; } if (has_alpha) { - WebPInitAlphaProcessing(); assert(step == 4); #if defined(USE_GAMMA_COMPRESSION) && defined(USE_INVERSE_ALPHA_TABLE) assert(kAlphaFix + kGammaFix <= 31);