Index: src/images/SkImageDecoder_libwebp.cpp |
diff --git a/src/images/SkImageDecoder_libwebp.cpp b/src/images/SkImageDecoder_libwebp.cpp |
index 05925d03a26686c1207644fa4ad991d87644e1f8..49d5bd1cca079653a3d7f014d300bb2638671b3c 100644 |
--- a/src/images/SkImageDecoder_libwebp.cpp |
+++ b/src/images/SkImageDecoder_libwebp.cpp |
@@ -444,6 +444,8 @@ bool SkWEBPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap, |
/////////////////////////////////////////////////////////////////////////////// |
+#include "SkUnPreMultiply.h" |
+ |
typedef void (*ScanlineImporter)(const uint8_t* in, uint8_t* out, int width, |
const SkPMColor* SK_RESTRICT ctable); |
@@ -459,6 +461,31 @@ static void ARGB_8888_To_RGB(const uint8_t* in, uint8_t* rgb, int width, |
} |
} |
+static void ARGB_8888_To_RGBA(const uint8_t* in, uint8_t* rgb, int width, |
+ const SkPMColor*) { |
+ const uint32_t* SK_RESTRICT src = (const uint32_t*)in; |
+ const SkUnPreMultiply::Scale* SK_RESTRICT table = |
+ SkUnPreMultiply::GetScaleTable(); |
+ for (int i = 0; i < width; ++i) { |
+ const uint32_t c = *src++; |
+ uint8_t a = SkGetPackedA32(c); |
+ uint8_t r = SkGetPackedR32(c); |
+ uint8_t g = SkGetPackedG32(c); |
+ uint8_t b = SkGetPackedB32(c); |
+ if (0 != a && 255 != a) { |
+ SkUnPreMultiply::Scale scale = table[a]; |
+ r = SkUnPreMultiply::ApplyScale(scale, r); |
+ g = SkUnPreMultiply::ApplyScale(scale, g); |
+ b = SkUnPreMultiply::ApplyScale(scale, b); |
+ } |
+ rgb[0] = r; |
+ rgb[1] = g; |
+ rgb[2] = b; |
+ rgb[3] = a; |
+ rgb += 4; |
+ } |
+} |
+ |
static void RGB_565_To_RGB(const uint8_t* in, uint8_t* rgb, int width, |
const SkPMColor*) { |
const uint16_t* SK_RESTRICT src = (const uint16_t*)in; |
@@ -483,6 +510,31 @@ static void ARGB_4444_To_RGB(const uint8_t* in, uint8_t* rgb, int width, |
} |
} |
+static void ARGB_4444_To_RGBA(const uint8_t* in, uint8_t* rgb, int width, |
+ const SkPMColor*) { |
+ const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)in; |
+ const SkUnPreMultiply::Scale* SK_RESTRICT table = |
+ SkUnPreMultiply::GetScaleTable(); |
+ for (int i = 0; i < width; ++i) { |
+ const SkPMColor16 c = *src++; |
+ uint8_t a = SkPacked4444ToA32(c); |
+ uint8_t r = SkPacked4444ToR32(c); |
+ uint8_t g = SkPacked4444ToG32(c); |
+ uint8_t b = SkPacked4444ToB32(c); |
+ if (0 != a && 255 != a) { |
+ SkUnPreMultiply::Scale scale = table[a]; |
+ r = SkUnPreMultiply::ApplyScale(scale, r); |
+ g = SkUnPreMultiply::ApplyScale(scale, g); |
+ b = SkUnPreMultiply::ApplyScale(scale, b); |
+ } |
+ rgb[0] = r; |
+ rgb[1] = g; |
+ rgb[2] = b; |
+ rgb[3] = a; |
+ rgb += 4; |
+ } |
+} |
+ |
static void Index8_To_RGB(const uint8_t* in, uint8_t* rgb, int width, |
const SkPMColor* SK_RESTRICT ctable) { |
const uint8_t* SK_RESTRICT src = (const uint8_t*)in; |
@@ -495,15 +547,31 @@ static void Index8_To_RGB(const uint8_t* in, uint8_t* rgb, int width, |
} |
} |
-static ScanlineImporter ChooseImporter(const SkBitmap::Config& config) { |
+static ScanlineImporter ChooseImporter(const SkBitmap::Config& config, |
+ bool hasAlpha, |
+ int* bpp) { |
switch (config) { |
case SkBitmap::kARGB_8888_Config: |
- return ARGB_8888_To_RGB; |
+ if (hasAlpha) { |
+ *bpp = 4; |
+ return ARGB_8888_To_RGBA; |
+ } else { |
+ *bpp = 3; |
+ return ARGB_8888_To_RGB; |
+ } |
+ case SkBitmap::kARGB_4444_Config: |
+ if (hasAlpha) { |
+ *bpp = 4; |
+ return ARGB_4444_To_RGBA; |
+ } else { |
+ *bpp = 3; |
+ return ARGB_4444_To_RGB; |
+ } |
case SkBitmap::kRGB_565_Config: |
+ *bpp = 3; |
return RGB_565_To_RGB; |
- case SkBitmap::kARGB_4444_Config: |
- return ARGB_4444_To_RGB; |
case SkBitmap::kIndex8_Config: |
+ *bpp = 3; |
return Index8_To_RGB; |
default: |
return NULL; |
@@ -527,10 +595,16 @@ private: |
bool SkWEBPImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bm, |
int quality) { |
const SkBitmap::Config config = bm.config(); |
- const ScanlineImporter scanline_import = ChooseImporter(config); |
+ const bool hasAlpha = !bm.isOpaque(); |
+ int bpp = -1; |
+ const ScanlineImporter scanline_import = ChooseImporter(config, hasAlpha, |
+ &bpp); |
if (NULL == scanline_import) { |
return false; |
} |
+ if (-1 == bpp) { |
+ return false; |
+ } |
SkAutoLockPixels alp(bm); |
SkAutoLockColors ctLocker; |
@@ -552,7 +626,7 @@ bool SkWEBPImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bm, |
const SkPMColor* colors = ctLocker.lockColors(bm); |
const uint8_t* src = (uint8_t*)bm.getPixels(); |
- const int rgbStride = pic.width * 3; |
+ const int rgbStride = pic.width * bpp; |
// Import (for each scanline) the bit-map image (in appropriate color-space) |
// to RGB color space. |
@@ -562,7 +636,12 @@ bool SkWEBPImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bm, |
pic.width, colors); |
} |
- bool ok = SkToBool(WebPPictureImportRGB(&pic, rgb, rgbStride)); |
+ bool ok; |
+ if (bpp == 3) { |
+ ok = SkToBool(WebPPictureImportRGB(&pic, rgb, rgbStride)); |
+ } else { |
+ ok = SkToBool(WebPPictureImportRGBA(&pic, rgb, rgbStride)); |
+ } |
delete[] rgb; |
ok = ok && WebPEncode(&webp_config, &pic); |