Index: src/images/SkPNGImageEncoder.cpp |
diff --git a/src/images/SkPNGImageEncoder.cpp b/src/images/SkPNGImageEncoder.cpp |
index a9c8b3d7857e2dd604fe9a531e3d676b04158c0e..b30cd2509a6b6aa0a856b1ea2e67f0e106e108fc 100644 |
--- a/src/images/SkPNGImageEncoder.cpp |
+++ b/src/images/SkPNGImageEncoder.cpp |
@@ -58,30 +58,30 @@ static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { |
} |
} |
-static transform_scanline_proc choose_proc(SkColorType ct, bool hasAlpha) { |
- // we don't care about search on alpha if we're kIndex8, since only the |
- // colortable packing cares about that distinction, not the pixels |
- if (kIndex_8_SkColorType == ct) { |
- hasAlpha = false; // we store false in the table entries for kIndex8 |
- } |
- |
+static transform_scanline_proc choose_proc(SkColorType ct, SkAlphaType alphaType) { |
static const struct { |
SkColorType fColorType; |
- bool fHasAlpha; |
+ SkAlphaType fAlphaType; |
transform_scanline_proc fProc; |
} gMap[] = { |
- { kRGB_565_SkColorType, false, transform_scanline_565 }, |
- { kN32_SkColorType, false, transform_scanline_888 }, |
- { kN32_SkColorType, true, transform_scanline_8888 }, |
- { kARGB_4444_SkColorType, false, transform_scanline_444 }, |
- { kARGB_4444_SkColorType, true, transform_scanline_4444 }, |
- { kIndex_8_SkColorType, false, transform_scanline_memcpy }, |
- { kGray_8_SkColorType, false, transform_scanline_memcpy }, |
+ { kRGB_565_SkColorType, kOpaque_SkAlphaType, transform_scanline_565 }, |
+ { kRGBA_8888_SkColorType, kOpaque_SkAlphaType, transform_scanline_RGBX }, |
+ { kBGRA_8888_SkColorType, kOpaque_SkAlphaType, transform_scanline_BGRX }, |
+ { kRGBA_8888_SkColorType, kPremul_SkAlphaType, transform_scanline_rgbA }, |
+ { kBGRA_8888_SkColorType, kPremul_SkAlphaType, transform_scanline_bgrA }, |
+ { kRGBA_8888_SkColorType, kUnpremul_SkAlphaType, transform_scanline_memcpy }, |
+ { kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, transform_scanline_BGRA }, |
+ { kARGB_4444_SkColorType, kOpaque_SkAlphaType, transform_scanline_444 }, |
+ { kARGB_4444_SkColorType, kPremul_SkAlphaType, transform_scanline_4444 }, |
+ { kIndex_8_SkColorType, kOpaque_SkAlphaType, transform_scanline_memcpy }, |
+ { kIndex_8_SkColorType, kPremul_SkAlphaType, transform_scanline_memcpy }, |
+ { kIndex_8_SkColorType, kUnpremul_SkAlphaType, transform_scanline_memcpy }, |
+ { kGray_8_SkColorType, kOpaque_SkAlphaType, transform_scanline_memcpy }, |
}; |
- for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) { |
- if (gMap[i].fColorType == ct && gMap[i].fHasAlpha == hasAlpha) { |
- return gMap[i].fProc; |
+ for (auto entry : gMap) { |
+ if (entry.fColorType == ct && entry.fAlphaType == alphaType) { |
+ return entry.fProc; |
} |
} |
sk_throw(); |
@@ -112,12 +112,12 @@ static int computeBitDepth(int colorCount) { |
*/ |
static inline int pack_palette(SkColorTable* ctable, |
png_color* SK_RESTRICT palette, |
- png_byte* SK_RESTRICT trans, bool hasAlpha) { |
+ png_byte* SK_RESTRICT trans, SkAlphaType alphaType) { |
const SkPMColor* SK_RESTRICT colors = ctable ? ctable->readColors() : nullptr; |
const int ctCount = ctable->count(); |
int i, num_trans = 0; |
- if (hasAlpha) { |
+ if (kOpaque_SkAlphaType != alphaType) { |
/* first see if we have some number of fully opaque at the end of the |
ctable. PNG allows num_trans < num_palette, but all of the trans |
entries must come first in the palette. If I was smarter, I'd |
@@ -134,18 +134,27 @@ static inline int pack_palette(SkColorTable* ctable, |
num_trans -= 1; |
} |
- const SkUnPreMultiply::Scale* SK_RESTRICT table = |
- SkUnPreMultiply::GetScaleTable(); |
- |
- for (i = 0; i < num_trans; i++) { |
- const SkPMColor c = *colors++; |
- const unsigned a = SkGetPackedA32(c); |
- const SkUnPreMultiply::Scale s = table[a]; |
- trans[i] = a; |
- palette[i].red = SkUnPreMultiply::ApplyScale(s, SkGetPackedR32(c)); |
- palette[i].green = SkUnPreMultiply::ApplyScale(s,SkGetPackedG32(c)); |
- palette[i].blue = SkUnPreMultiply::ApplyScale(s, SkGetPackedB32(c)); |
+ if (kPremul_SkAlphaType == alphaType) { |
+ const SkUnPreMultiply::Scale* SK_RESTRICT table = SkUnPreMultiply::GetScaleTable(); |
+ for (i = 0; i < num_trans; i++) { |
+ const SkPMColor c = *colors++; |
+ const unsigned a = SkGetPackedA32(c); |
+ const SkUnPreMultiply::Scale s = table[a]; |
+ trans[i] = a; |
+ palette[i].red = SkUnPreMultiply::ApplyScale(s, SkGetPackedR32(c)); |
+ palette[i].green = SkUnPreMultiply::ApplyScale(s,SkGetPackedG32(c)); |
+ palette[i].blue = SkUnPreMultiply::ApplyScale(s, SkGetPackedB32(c)); |
+ } |
+ } else { |
+ for (i = 0; i < num_trans; i++) { |
+ const SkPMColor c = *colors++; |
+ trans[i] = SkGetPackedA32(c); |
+ palette[i].red = SkGetPackedR32(c); |
+ palette[i].green = SkGetPackedG32(c); |
+ palette[i].blue = SkGetPackedB32(c); |
+ } |
} |
+ |
// now fall out of this if-block to use common code for the trailing |
// opaque entries |
} |
@@ -165,7 +174,7 @@ protected: |
bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) override; |
private: |
bool doEncode(SkWStream* stream, const SkBitmap& bm, |
- const bool& hasAlpha, int colorType, |
+ SkAlphaType alphaType, int colorType, |
int bitDepth, SkColorType ct, |
png_color_8& sig_bit); |
@@ -180,12 +189,12 @@ bool SkPNGImageEncoder::onEncode(SkWStream* stream, |
switch (originalBitmap.colorType()) { |
case kIndex_8_SkColorType: |
case kGray_8_SkColorType: |
- case kN32_SkColorType: |
+ case kRGBA_8888_SkColorType: |
+ case kBGRA_8888_SkColorType: |
case kARGB_4444_SkColorType: |
case kRGB_565_SkColorType: |
break; |
default: |
- // TODO(scroggo): support 8888-but-not-N32 natively. |
// TODO(scroggo): support Alpha_8 as Grayscale(black)+Alpha |
if (originalBitmap.copyTo(©, kN32_SkColorType)) { |
bitmap = © |
@@ -193,7 +202,22 @@ bool SkPNGImageEncoder::onEncode(SkWStream* stream, |
} |
SkColorType ct = bitmap->colorType(); |
- const bool hasAlpha = !bitmap->isOpaque(); |
+ const SkAlphaType alphaType = bitmap->alphaType(); |
+ switch (alphaType) { |
+ case kUnpremul_SkAlphaType: |
+ if (kARGB_4444_SkColorType == ct) { |
+ return false; |
+ } |
+ |
+ break; |
+ case kOpaque_SkAlphaType: |
+ case kPremul_SkAlphaType: |
+ break; |
+ default: |
+ return false; |
+ } |
+ |
+ const bool isOpaque = (kOpaque_SkAlphaType == alphaType); |
int bitDepth = 8; // default for color |
png_color_8 sig_bit; |
sk_bzero(&sig_bit, sizeof(png_color_8)); |
@@ -210,28 +234,29 @@ bool SkPNGImageEncoder::onEncode(SkWStream* stream, |
case kGray_8_SkColorType: |
sig_bit.gray = 8; |
colorType = PNG_COLOR_TYPE_GRAY; |
- SkASSERT(!hasAlpha); |
+ SkASSERT(isOpaque); |
break; |
- case kN32_SkColorType: |
+ case kRGBA_8888_SkColorType: |
+ case kBGRA_8888_SkColorType: |
sig_bit.red = 8; |
sig_bit.green = 8; |
sig_bit.blue = 8; |
sig_bit.alpha = 8; |
- colorType = hasAlpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB; |
+ colorType = isOpaque ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA; |
break; |
case kARGB_4444_SkColorType: |
sig_bit.red = 4; |
sig_bit.green = 4; |
sig_bit.blue = 4; |
sig_bit.alpha = 4; |
- colorType = hasAlpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB; |
+ colorType = isOpaque ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA; |
break; |
case kRGB_565_SkColorType: |
sig_bit.red = 5; |
sig_bit.green = 6; |
sig_bit.blue = 5; |
colorType = PNG_COLOR_TYPE_RGB; |
- SkASSERT(!hasAlpha); |
+ SkASSERT(isOpaque); |
break; |
default: |
return false; |
@@ -253,11 +278,11 @@ bool SkPNGImageEncoder::onEncode(SkWStream* stream, |
bitDepth = computeBitDepth(ctable->count()); |
} |
- return doEncode(stream, *bitmap, hasAlpha, colorType, bitDepth, ct, sig_bit); |
+ return doEncode(stream, *bitmap, alphaType, colorType, bitDepth, ct, sig_bit); |
} |
bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap, |
- const bool& hasAlpha, int colorType, |
+ SkAlphaType alphaType, int colorType, |
int bitDepth, SkColorType ct, |
png_color_8& sig_bit) { |
@@ -304,9 +329,9 @@ bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap, |
png_color paletteColors[256]; |
png_byte trans[256]; |
if (kIndex_8_SkColorType == ct) { |
- SkColorTable* ct = bitmap.getColorTable(); |
- int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha); |
- png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); |
+ SkColorTable* colorTable = bitmap.getColorTable(); |
+ int numTrans = pack_palette(colorTable, paletteColors, trans, alphaType); |
+ png_set_PLTE(png_ptr, info_ptr, paletteColors, colorTable->count()); |
if (numTrans > 0) { |
png_set_tRNS(png_ptr, info_ptr, trans, numTrans, nullptr); |
} |
@@ -318,11 +343,11 @@ bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap, |
const char* srcImage = (const char*)bitmap.getPixels(); |
SkAutoSTMalloc<1024, char> rowStorage(bitmap.width() << 2); |
char* storage = rowStorage.get(); |
- transform_scanline_proc proc = choose_proc(ct, hasAlpha); |
+ transform_scanline_proc proc = choose_proc(ct, alphaType); |
for (int y = 0; y < bitmap.height(); y++) { |
png_bytep row_ptr = (png_bytep)storage; |
- proc(srcImage, bitmap.width(), storage); |
+ proc(storage, srcImage, bitmap.width(), SkColorTypeBytesPerPixel(ct)); |
png_write_rows(png_ptr, &row_ptr, 1); |
srcImage += bitmap.rowBytes(); |
} |