diff options
author | Matt Sarett <msarett@google.com> | 2016-11-04 13:19:48 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2016-11-04 20:55:16 +0000 |
commit | 61eedebe4ce61215a56ced832e0df73c2cb19447 (patch) | |
tree | 869f208f74b8966e8f0153edd6fe323d37adfbf6 /src/codec/SkGifCodec.cpp | |
parent | 125b2aac5a38121b3c82545acd27e74366ca83aa (diff) |
Add F16, SkColorSpaceXform support to SkGifCodec
BUG=skia:4895
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4396
Change-Id: I7c521760891852daf4f3933ecf02dc08acec64c0
Reviewed-on: https://skia-review.googlesource.com/4396
Reviewed-by: Leon Scroggins <scroggo@google.com>
Commit-Queue: Matt Sarett <msarett@google.com>
Diffstat (limited to 'src/codec/SkGifCodec.cpp')
-rw-r--r-- | src/codec/SkGifCodec.cpp | 92 |
1 files changed, 60 insertions, 32 deletions
diff --git a/src/codec/SkGifCodec.cpp b/src/codec/SkGifCodec.cpp index 277da03191..e773ed71e9 100644 --- a/src/codec/SkGifCodec.cpp +++ b/src/codec/SkGifCodec.cpp @@ -145,12 +145,29 @@ int SkGifCodec::onGetRepetitionCount() { } void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, size_t frameIndex) { - fCurrColorTable = fReader->getColorTable(dstInfo.colorType(), frameIndex); - fCurrColorTableIsReal = fCurrColorTable; - if (!fCurrColorTable) { + SkColorType colorTableColorType = dstInfo.colorType(); + if (this->colorXform()) { + colorTableColorType = kRGBA_8888_SkColorType; + } + + sk_sp<SkColorTable> currColorTable = fReader->getColorTable(colorTableColorType, frameIndex); + fCurrColorTableIsReal = currColorTable; + if (!fCurrColorTableIsReal) { // This is possible for an empty frame. Create a dummy with one value (transparent). SkPMColor color = SK_ColorTRANSPARENT; fCurrColorTable.reset(new SkColorTable(&color, 1)); + } else if (this->colorXform() && !fXformOnDecode) { + SkPMColor dstColors[256]; + SkColorSpaceXform::ColorFormat dstFormat = select_xform_format(dstInfo.colorType()); + SkColorSpaceXform::ColorFormat srcFormat = SkColorSpaceXform::kRGBA_8888_ColorFormat; + SkAlphaType xformAlphaType = select_xform_alpha(dstInfo.alphaType(), + this->getInfo().alphaType()); + SkAssertResult(this->colorXform()->apply(dstFormat, dstColors, srcFormat, + currColorTable->readColors(), + currColorTable->count(), xformAlphaType)); + fCurrColorTable.reset(new SkColorTable(dstColors, currColorTable->count())); + } else { + fCurrColorTable = std::move(currColorTable); } } @@ -158,13 +175,17 @@ void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, size_t frameIn SkCodec::Result SkGifCodec::prepareToDecode(const SkImageInfo& dstInfo, SkPMColor* inputColorPtr, int* inputColorCount, const Options& opts) { // Check for valid input parameters - if (!conversion_possible_ignore_color_space(dstInfo, this->getInfo())) { + if (!conversion_possible(dstInfo, this->getInfo()) || !this->initializeColorXform(dstInfo)) { return gif_error("Cannot convert input type to output type.\n", kInvalidConversion); } - if (dstInfo.colorType() == kRGBA_F16_SkColorType) { - // FIXME: This should be supported. - return gif_error("GIF does not yet support F16.\n", kInvalidConversion); + fXformOnDecode = false; + if (this->colorXform()) { + fXformOnDecode = apply_xform_on_decode(dstInfo.colorType(), this->getEncodedInfo().color()); + if (fXformOnDecode) { + fXformBuffer.reset(new uint32_t[dstInfo.width()]); + sk_bzero(fXformBuffer.get(), dstInfo.width() * sizeof(uint32_t)); + } } if (opts.fSubset) { @@ -238,6 +259,14 @@ void SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo, size_t frameInde // frameRect, since it might extend beyond the edge of the frame. SkIRect swizzleRect = SkIRect::MakeLTRB(xBegin, 0, xEnd, 0); + SkImageInfo swizzlerInfo = dstInfo; + if (this->colorXform()) { + swizzlerInfo = swizzlerInfo.makeColorType(kRGBA_8888_SkColorType); + if (kPremul_SkAlphaType == dstInfo.alphaType()) { + swizzlerInfo = swizzlerInfo.makeAlphaType(kUnpremul_SkAlphaType); + } + } + // The default Options should be fine: // - we'll ignore if the memory is zero initialized - unless we're the first frame, this won't // matter anyway. @@ -246,7 +275,7 @@ void SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo, size_t frameInde // We may not be able to use the real Options anyway, since getPixels does not store it (due to // a bug). fSwizzler.reset(SkSwizzler::CreateSwizzler(this->getEncodedInfo(), - fCurrColorTable->readColors(), dstInfo, Options(), &swizzleRect)); + fCurrColorTable->readColors(), swizzlerInfo, Options(), &swizzleRect)); SkASSERT(fSwizzler.get()); } @@ -436,6 +465,22 @@ uint64_t SkGifCodec::onGetFillValue(const SkImageInfo& dstInfo) const { return SK_ColorTRANSPARENT; } +void SkGifCodec::applyXformRow(const SkImageInfo& dstInfo, void* dst, const uint8_t* src) const { + if (this->colorXform() && fXformOnDecode) { + fSwizzler->swizzle(fXformBuffer.get(), src); + + const SkColorSpaceXform::ColorFormat dstFormat = select_xform_format(dstInfo.colorType()); + const SkColorSpaceXform::ColorFormat srcFormat = SkColorSpaceXform::kRGBA_8888_ColorFormat; + const SkAlphaType xformAlphaType = select_xform_alpha(dstInfo.alphaType(), + this->getInfo().alphaType()); + const int xformWidth = get_scaled_dimension(dstInfo.width(), fSwizzler->sampleX()); + SkAssertResult(this->colorXform()->apply(dstFormat, dst, srcFormat, fXformBuffer.get(), + xformWidth, xformAlphaType)); + } else { + fSwizzler->swizzle(dst, src); + } +} + bool SkGifCodec::haveDecodedRow(size_t frameIndex, const unsigned char* rowBegin, size_t rowNumber, unsigned repeatCount, bool writeTransparentPixels) { @@ -524,27 +569,10 @@ bool SkGifCodec::haveDecodedRow(size_t frameIndex, const unsigned char* rowBegin // will "show through" the later ones. const auto dstInfo = this->dstInfo(); if (writeTransparentPixels) { - fSwizzler->swizzle(dstLine, rowBegin); + this->applyXformRow(dstInfo, dstLine, rowBegin); } else { - // We cannot swizzle directly into the dst, since that will write the transparent pixels. - // Instead, swizzle into a temporary buffer, and copy that into the dst. - { - void* const memsetDst = fTmpBuffer.get(); - // Although onGetFillValue returns a uint64_t, we only use the low eight bits. The - // return value is either an 8 bit index (for index8) or SK_ColorTRANSPARENT, which is - // all zeroes. - const int fillValue = (uint8_t) this->onGetFillValue(dstInfo); - const size_t rb = dstInfo.minRowBytes(); - if (fillValue == 0) { - // FIXME: This special case should be unnecessary, and in fact sk_bzero just calls - // memset. But without it, the compiler thinks this is trying to pass a zero length - // to memset, causing an error. - sk_bzero(memsetDst, rb); - } else { - memset(memsetDst, fillValue, rb); - } - } - fSwizzler->swizzle(fTmpBuffer.get(), rowBegin); + sk_bzero(fTmpBuffer.get(), dstInfo.minRowBytes()); + this->applyXformRow(dstInfo, fTmpBuffer.get(), rowBegin); const size_t offsetBytes = fSwizzler->swizzleOffsetBytes(); switch (dstInfo.colorType()) { @@ -564,11 +592,11 @@ bool SkGifCodec::haveDecodedRow(size_t frameIndex, const unsigned char* rowBegin } break; } - case kIndex_8_SkColorType: { - uint8_t* dstPixel = SkTAddOffset<uint8_t>(dstLine, offsetBytes); - uint8_t* srcPixel = SkTAddOffset<uint8_t>(fTmpBuffer.get(), offsetBytes); + case kRGBA_F16_SkColorType: { + uint64_t* dstPixel = SkTAddOffset<uint64_t>(dstLine, offsetBytes); + uint64_t* srcPixel = SkTAddOffset<uint64_t>(fTmpBuffer.get(), offsetBytes); for (int i = 0; i < fSwizzler->swizzleWidth(); i++) { - if (*srcPixel != frameContext->transparentPixel()) { + if (*srcPixel != 0) { *dstPixel = *srcPixel; } dstPixel++; |