mirror of
https://github.com/webmproject/libwebp.git
synced 2024-11-19 20:08:28 +01:00
Add WebPReplaceTransparentPixels() in dsp
with SSE2 implementation. (Extracted from side experiment) Change-Id: I62d457fb6643645291cffd6d2d205d4a5ffa4517
This commit is contained in:
parent
84739717d6
commit
55a080e50a
@ -359,6 +359,11 @@ static int HasAlpha32b_C(const uint8_t* src, int length) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void AlphaReplace_C(uint32_t* src, int length, uint32_t color) {
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < length; ++x) if ((src[x] >> 24) == 0) src[x] = color;
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Simple channel manipulations.
|
// Simple channel manipulations.
|
||||||
|
|
||||||
@ -400,6 +405,7 @@ void (*WebPPackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b,
|
|||||||
|
|
||||||
int (*WebPHasAlpha8b)(const uint8_t* src, int length);
|
int (*WebPHasAlpha8b)(const uint8_t* src, int length);
|
||||||
int (*WebPHasAlpha32b)(const uint8_t* src, int length);
|
int (*WebPHasAlpha32b)(const uint8_t* src, int length);
|
||||||
|
void (*WebPAlphaReplace)(uint32_t* src, int length, uint32_t color);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Init function
|
// Init function
|
||||||
@ -428,6 +434,7 @@ WEBP_DSP_INIT_FUNC(WebPInitAlphaProcessing) {
|
|||||||
|
|
||||||
WebPHasAlpha8b = HasAlpha8b_C;
|
WebPHasAlpha8b = HasAlpha8b_C;
|
||||||
WebPHasAlpha32b = HasAlpha32b_C;
|
WebPHasAlpha32b = HasAlpha32b_C;
|
||||||
|
WebPAlphaReplace = AlphaReplace_C;
|
||||||
|
|
||||||
// If defined, use CPUInfo() to overwrite some pointers with faster versions.
|
// If defined, use CPUInfo() to overwrite some pointers with faster versions.
|
||||||
if (VP8GetCPUInfo != NULL) {
|
if (VP8GetCPUInfo != NULL) {
|
||||||
@ -469,4 +476,5 @@ WEBP_DSP_INIT_FUNC(WebPInitAlphaProcessing) {
|
|||||||
assert(WebPPackRGB != NULL);
|
assert(WebPPackRGB != NULL);
|
||||||
assert(WebPHasAlpha8b != NULL);
|
assert(WebPHasAlpha8b != NULL);
|
||||||
assert(WebPHasAlpha32b != NULL);
|
assert(WebPHasAlpha32b != NULL);
|
||||||
|
assert(WebPAlphaReplace != NULL);
|
||||||
}
|
}
|
||||||
|
@ -265,6 +265,27 @@ static int HasAlpha32b_SSE2(const uint8_t* src, int length) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void AlphaReplace_SSE2(uint32_t* src, int length, uint32_t color) {
|
||||||
|
const __m128i m_color = _mm_set1_epi32(color);
|
||||||
|
const __m128i zero = _mm_setzero_si128();
|
||||||
|
int i = 0;
|
||||||
|
for (; i + 8 <= length; i += 8) {
|
||||||
|
const __m128i a0 = _mm_loadu_si128((const __m128i*)(src + i + 0));
|
||||||
|
const __m128i a1 = _mm_loadu_si128((const __m128i*)(src + i + 4));
|
||||||
|
const __m128i b0 = _mm_srai_epi32(a0, 24);
|
||||||
|
const __m128i b1 = _mm_srai_epi32(a1, 24);
|
||||||
|
const __m128i c0 = _mm_cmpeq_epi32(b0, zero);
|
||||||
|
const __m128i c1 = _mm_cmpeq_epi32(b1, zero);
|
||||||
|
const __m128i d0 = _mm_and_si128(c0, m_color);
|
||||||
|
const __m128i d1 = _mm_and_si128(c1, m_color);
|
||||||
|
const __m128i e0 = _mm_andnot_si128(c0, a0);
|
||||||
|
const __m128i e1 = _mm_andnot_si128(c1, a1);
|
||||||
|
_mm_storeu_si128((__m128i*)(src + i + 0), _mm_or_si128(d0, e0));
|
||||||
|
_mm_storeu_si128((__m128i*)(src + i + 4), _mm_or_si128(d1, e1));
|
||||||
|
}
|
||||||
|
for (; i < length; ++i) if ((src[i] >> 24) == 0) src[i] = color;
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Apply alpha value to rows
|
// Apply alpha value to rows
|
||||||
|
|
||||||
@ -334,6 +355,7 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE2(void) {
|
|||||||
|
|
||||||
WebPHasAlpha8b = HasAlpha8b_SSE2;
|
WebPHasAlpha8b = HasAlpha8b_SSE2;
|
||||||
WebPHasAlpha32b = HasAlpha32b_SSE2;
|
WebPHasAlpha32b = HasAlpha32b_SSE2;
|
||||||
|
WebPAlphaReplace = AlphaReplace_SSE2;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // !WEBP_USE_SSE2
|
#else // !WEBP_USE_SSE2
|
||||||
|
@ -638,6 +638,8 @@ extern void (*WebPPackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b,
|
|||||||
extern int (*WebPHasAlpha8b)(const uint8_t* src, int length);
|
extern int (*WebPHasAlpha8b)(const uint8_t* src, int length);
|
||||||
// This function returns true if src[4*i] contains a value different from 0xff.
|
// This function returns true if src[4*i] contains a value different from 0xff.
|
||||||
extern int (*WebPHasAlpha32b)(const uint8_t* src, int length);
|
extern int (*WebPHasAlpha32b)(const uint8_t* src, int length);
|
||||||
|
// replaces transparent values in src[] by 'color'.
|
||||||
|
extern void (*WebPAlphaReplace)(uint32_t* src, int length, uint32_t color);
|
||||||
|
|
||||||
// To be called first before using the above.
|
// To be called first before using the above.
|
||||||
void WebPInitAlphaProcessing(void);
|
void WebPInitAlphaProcessing(void);
|
||||||
|
@ -83,6 +83,19 @@ static int SmoothenBlock(const uint8_t* a_ptr, int a_stride, uint8_t* y_ptr,
|
|||||||
return (count == 0);
|
return (count == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebPReplaceTransparentPixels(WebPPicture* pic, uint32_t color) {
|
||||||
|
if (pic != NULL && pic->use_argb) {
|
||||||
|
int y = pic->height;
|
||||||
|
uint32_t* argb = pic->argb;
|
||||||
|
color &= 0xffffffu; // force alpha=0
|
||||||
|
WebPInitAlphaProcessing();
|
||||||
|
while (y-- > 0) {
|
||||||
|
WebPAlphaReplace(argb, pic->width, color);
|
||||||
|
argb += pic->argb_stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void WebPCleanupTransparentArea(WebPPicture* pic) {
|
void WebPCleanupTransparentArea(WebPPicture* pic) {
|
||||||
int x, y, w, h;
|
int x, y, w, h;
|
||||||
if (pic == NULL) return;
|
if (pic == NULL) return;
|
||||||
@ -165,24 +178,6 @@ void WebPCleanupTransparentArea(WebPPicture* pic) {
|
|||||||
#undef SIZE
|
#undef SIZE
|
||||||
#undef SIZE2
|
#undef SIZE2
|
||||||
|
|
||||||
void WebPCleanupTransparentAreaLossless(WebPPicture* const pic) {
|
|
||||||
int x, y, w, h;
|
|
||||||
uint32_t* argb;
|
|
||||||
assert(pic != NULL && pic->use_argb);
|
|
||||||
w = pic->width;
|
|
||||||
h = pic->height;
|
|
||||||
argb = pic->argb;
|
|
||||||
|
|
||||||
for (y = 0; y < h; ++y) {
|
|
||||||
for (x = 0; x < w; ++x) {
|
|
||||||
if ((argb[x] & 0xff000000) == 0) {
|
|
||||||
argb[x] = 0x00000000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
argb += pic->argb_stride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Blend color and remove transparency info
|
// Blend color and remove transparency info
|
||||||
|
|
||||||
|
@ -505,9 +505,9 @@ int WebPPictureAllocARGB(WebPPicture* const picture, int width, int height);
|
|||||||
// Returns false in case of error (invalid param, out-of-memory).
|
// Returns false in case of error (invalid param, out-of-memory).
|
||||||
int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height);
|
int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height);
|
||||||
|
|
||||||
// Clean-up the RGB samples under fully transparent area, to help lossless
|
// Replace samples that are fully transparent by 'color' to help compressibility
|
||||||
// compressibility (no guarantee, though). Assumes that pic->use_argb is true.
|
// (no guarantee, though). Assumes pic->use_argb is true.
|
||||||
void WebPCleanupTransparentAreaLossless(WebPPicture* const pic);
|
void WebPReplaceTransparentPixels(WebPPicture* const pic, uint32_t color);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -400,7 +400,7 @@ int WebPEncode(const WebPConfig* config, WebPPicture* pic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!config->exact) {
|
if (!config->exact) {
|
||||||
WebPCleanupTransparentAreaLossless(pic);
|
WebPReplaceTransparentPixels(pic, 0x000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem.
|
ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem.
|
||||||
|
Loading…
Reference in New Issue
Block a user