| Index: src/codec/SkPngCodec.cpp
|
| diff --git a/src/codec/SkPngCodec.cpp b/src/codec/SkPngCodec.cpp
|
| index 2b52ab72d75d6faa9b72047aa24df93699686778..8f7ab79bf1f099df265e4c3796425cfa5ea22d6c 100644
|
| --- a/src/codec/SkPngCodec.cpp
|
| +++ b/src/codec/SkPngCodec.cpp
|
| @@ -92,8 +92,12 @@ private:
|
| };
|
| #define AutoCleanPng(...) SK_REQUIRE_LOCAL_VAR(AutoCleanPng)
|
|
|
| +static inline SkAlphaType xform_alpha_type(SkAlphaType dstAlphaType, SkAlphaType srcAlphaType) {
|
| + return (kOpaque_SkAlphaType == srcAlphaType) ? kOpaque_SkAlphaType : dstAlphaType;
|
| +}
|
| +
|
| // Note: SkColorTable claims to store SkPMColors, which is not necessarily the case here.
|
| -bool SkPngCodec::createColorTable(SkColorType dstColorType, bool premultiply, int* ctableCount) {
|
| +bool SkPngCodec::createColorTable(const SkImageInfo& dstInfo, int* ctableCount) {
|
|
|
| int numColors;
|
| png_color* palette;
|
| @@ -101,21 +105,27 @@ bool SkPngCodec::createColorTable(SkColorType dstColorType, bool premultiply, in
|
| return false;
|
| }
|
|
|
| - // Note: These are not necessarily SkPMColors.
|
| - SkPMColor colorPtr[256];
|
| + // Contents depend on tableColorType and our choice of if/when to premultiply:
|
| + // { kPremul, kUnpremul, kOpaque } x { RGBA, BGRA }
|
| + SkPMColor colorTable[256];
|
| + SkColorType tableColorType = fColorXform ? kRGBA_8888_SkColorType : dstInfo.colorType();
|
|
|
| png_bytep alphas;
|
| int numColorsWithAlpha = 0;
|
| if (png_get_tRNS(fPng_ptr, fInfo_ptr, &alphas, &numColorsWithAlpha, nullptr)) {
|
| + // If we are performing a color xform, it will handle the premultiply. Otherwise,
|
| + // we'll do it here.
|
| + bool premultiply = !fColorXform && needs_premul(dstInfo, this->getInfo());
|
| +
|
| // Choose which function to use to create the color table. If the final destination's
|
| // colortype is unpremultiplied, the color table will store unpremultiplied colors.
|
| - PackColorProc proc = choose_pack_color_proc(premultiply, dstColorType);
|
| + PackColorProc proc = choose_pack_color_proc(premultiply, tableColorType);
|
|
|
| for (int i = 0; i < numColorsWithAlpha; i++) {
|
| // We don't have a function in SkOpts that combines a set of alphas with a set
|
| // of RGBs. We could write one, but it's hardly worth it, given that this
|
| // is such a small fraction of the total decode time.
|
| - colorPtr[i] = proc(alphas[i], palette->red, palette->green, palette->blue);
|
| + colorTable[i] = proc(alphas[i], palette->red, palette->green, palette->blue);
|
| palette++;
|
| }
|
| }
|
| @@ -129,21 +139,31 @@ bool SkPngCodec::createColorTable(SkColorType dstColorType, bool premultiply, in
|
| SkASSERT(&palette->green < &palette->blue);
|
| #endif
|
|
|
| - if (is_rgba(dstColorType)) {
|
| - SkOpts::RGB_to_RGB1(colorPtr + numColorsWithAlpha, palette,
|
| + if (is_rgba(tableColorType)) {
|
| + SkOpts::RGB_to_RGB1(colorTable + numColorsWithAlpha, palette,
|
| numColors - numColorsWithAlpha);
|
| } else {
|
| - SkOpts::RGB_to_BGR1(colorPtr + numColorsWithAlpha, palette,
|
| + SkOpts::RGB_to_BGR1(colorTable + numColorsWithAlpha, palette,
|
| numColors - numColorsWithAlpha);
|
| }
|
| }
|
|
|
| + // If we are not decoding to F16, we can color xform now and store the results
|
| + // in the color table.
|
| + if (fColorXform && kRGBA_F16_SkColorType != dstInfo.colorType()) {
|
| + SkColorType xformColorType = is_rgba(dstInfo.colorType()) ?
|
| + kRGBA_8888_SkColorType : kBGRA_8888_SkColorType;
|
| + SkAlphaType xformAlphaType = xform_alpha_type(dstInfo.alphaType(),
|
| + this->getInfo().alphaType());
|
| + fColorXform->apply(colorTable, colorTable, numColors, xformColorType, xformAlphaType);
|
| + }
|
| +
|
| // Pad the color table with the last color in the table (or black) in the case that
|
| // invalid pixel indices exceed the number of colors in the table.
|
| const int maxColors = 1 << fBitDepth;
|
| if (numColors < maxColors) {
|
| - SkPMColor lastColor = numColors > 0 ? colorPtr[numColors - 1] : SK_ColorBLACK;
|
| - sk_memset32(colorPtr + numColors, lastColor, maxColors - numColors);
|
| + SkPMColor lastColor = numColors > 0 ? colorTable[numColors - 1] : SK_ColorBLACK;
|
| + sk_memset32(colorTable + numColors, lastColor, maxColors - numColors);
|
| }
|
|
|
| // Set the new color count.
|
| @@ -151,7 +171,7 @@ bool SkPngCodec::createColorTable(SkColorType dstColorType, bool premultiply, in
|
| *ctableCount = maxColors;
|
| }
|
|
|
| - fColorTable.reset(new SkColorTable(colorPtr, maxColors));
|
| + fColorTable.reset(new SkColorTable(colorTable, maxColors));
|
| return true;
|
| }
|
|
|
| @@ -367,6 +387,11 @@ void SkPngCodec::allocateStorage() {
|
| fColorXform ? SkTAddOffset<uint32_t>(fSwizzlerSrcRow, SkAlign4(fSrcRowBytes)) : 0;
|
| }
|
|
|
| +static inline bool apply_xform_on_decode(SkColorType dstColorType, SkEncodedInfo::Color srcColor) {
|
| + // We will apply the color xform when reading the color table, unless F16 is requested.
|
| + return SkEncodedInfo::kPalette_Color != srcColor || kRGBA_F16_SkColorType == dstColorType;
|
| +}
|
| +
|
| class SkPngNormalCodec : public SkPngCodec {
|
| public:
|
| SkPngNormalCodec(const SkEncodedInfo& encodedInfo, const SkImageInfo& imageInfo,
|
| @@ -400,18 +425,21 @@ public:
|
|
|
| void* swizzlerDstRow = dst;
|
| size_t swizzlerDstRowBytes = rowBytes;
|
| - if (fColorXform) {
|
| +
|
| + bool colorXform = fColorXform &&
|
| + apply_xform_on_decode(dstInfo.colorType(), this->getEncodedInfo().color());
|
| + if (colorXform) {
|
| swizzlerDstRow = fColorXformSrcRow;
|
| swizzlerDstRowBytes = 0;
|
| }
|
|
|
| - SkAlphaType xformAlphaType = (kOpaque_SkAlphaType == this->getInfo().alphaType()) ?
|
| - kOpaque_SkAlphaType : dstInfo.alphaType();
|
| + SkAlphaType xformAlphaType = xform_alpha_type(dstInfo.alphaType(),
|
| + this->getInfo().alphaType());
|
| for (; y < count; y++) {
|
| png_read_row(fPng_ptr, fSwizzlerSrcRow, nullptr);
|
| fSwizzler->swizzle(swizzlerDstRow, fSwizzlerSrcRow);
|
|
|
| - if (fColorXform) {
|
| + if (colorXform) {
|
| fColorXform->apply(dst, (const uint32_t*) swizzlerDstRow, fSwizzler->swizzleWidth(),
|
| dstInfo.colorType(), xformAlphaType);
|
| dst = SkTAddOffset<void>(dst, rowBytes);
|
| @@ -442,7 +470,6 @@ public:
|
| typedef SkPngCodec INHERITED;
|
| };
|
|
|
| -
|
| class SkPngInterlacedCodec : public SkPngCodec {
|
| public:
|
| SkPngInterlacedCodec(const SkEncodedInfo& encodedInfo, const SkImageInfo& imageInfo,
|
| @@ -500,25 +527,25 @@ public:
|
| // Swizzle and xform the rows we care about
|
| void* swizzlerDstRow = dst;
|
| size_t swizzlerDstRowBytes = rowBytes;
|
| - if (fColorXform) {
|
| +
|
| + bool colorXform = fColorXform &&
|
| + apply_xform_on_decode(dstInfo.colorType(), this->getEncodedInfo().color());
|
| + if (colorXform) {
|
| swizzlerDstRow = fColorXformSrcRow;
|
| swizzlerDstRowBytes = 0;
|
| }
|
|
|
| - SkAlphaType xformAlphaType = (kOpaque_SkAlphaType == this->getInfo().alphaType()) ?
|
| - kOpaque_SkAlphaType : dstInfo.alphaType();
|
| + SkAlphaType xformAlphaType = xform_alpha_type(dstInfo.alphaType(),
|
| + this->getInfo().alphaType());
|
| srcRow = storage.get();
|
| for (int y = 0; y < count; y++) {
|
| fSwizzler->swizzle(swizzlerDstRow, srcRow);
|
| srcRow = SkTAddOffset<uint8_t>(srcRow, fSrcRowBytes);
|
|
|
| - if (fColorXform) {
|
| - if (fColorXform) {
|
| - fColorXform->apply(dst, (const uint32_t*) swizzlerDstRow,
|
| - fSwizzler->swizzleWidth(), dstInfo.colorType(),
|
| - xformAlphaType);
|
| - dst = SkTAddOffset<void>(dst, rowBytes);
|
| - }
|
| + if (colorXform) {
|
| + fColorXform->apply(dst, (const uint32_t*) swizzlerDstRow, fSwizzler->swizzleWidth(),
|
| + dstInfo.colorType(), xformAlphaType);
|
| + dst = SkTAddOffset<void>(dst, rowBytes);
|
| }
|
|
|
| swizzlerDstRow = SkTAddOffset<void>(swizzlerDstRow, swizzlerDstRowBytes);
|
| @@ -802,6 +829,8 @@ bool SkPngCodec::initializeXforms(const SkImageInfo& dstInfo, const Options& opt
|
| swizzlerInfo = swizzlerInfo.makeAlphaType(kUnpremul_SkAlphaType);
|
| }
|
| break;
|
| + case kIndex_8_SkColorType:
|
| + break;
|
| default:
|
| return false;
|
| }
|
| @@ -815,8 +844,7 @@ bool SkPngCodec::initializeXforms(const SkImageInfo& dstInfo, const Options& opt
|
| }
|
|
|
| if (SkEncodedInfo::kPalette_Color == this->getEncodedInfo().color()) {
|
| - if (!this->createColorTable(swizzlerInfo.colorType(),
|
| - kPremul_SkAlphaType == swizzlerInfo.alphaType(), ctableCount)) {
|
| + if (!this->createColorTable(dstInfo, ctableCount)) {
|
| return false;
|
| }
|
| }
|
|
|