diff options
author | Leon Scroggins III <scroggo@google.com> | 2017-08-15 12:24:02 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-08-17 16:09:31 +0000 |
commit | 0741818e7ab4e9ea8505b8a8687412f0e3804c65 (patch) | |
tree | ac183b3107e97b0717319fd403f6d552fdbd840f /src | |
parent | de44c2df9469e70f57f05d262cd1a245b2ff5e90 (diff) |
Move calls to conversion_possible to SkCodec
Move common code into the base class, so subclasses need not call
conversion_possible.
Use SkEncodedInfo rather than SkImageInfo, and use the proper frame.
API Changes:
- SkAndroidCodec:
- Add getEncodedInfo(), for SkBitmapRegionCodec
- SkEncodedInfo:
- Add opaque() helper
- SkBitmapRegionDecoder:
- Remove unused conversionSupported
(Split off from skia-review.googlesource.com/c/25746)
Bug: skia:5601
Change-Id: If4a40d4b98a3dd0afde2b6058f92315a393a5baf
Reviewed-on: https://skia-review.googlesource.com/34361
Reviewed-by: Mike Klein <mtklein@google.com>
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Commit-Queue: Leon Scroggins <scroggo@google.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/android/SkBitmapRegionCodec.cpp | 5 | ||||
-rw-r--r-- | src/android/SkBitmapRegionCodec.h | 2 | ||||
-rw-r--r-- | src/codec/SkAndroidCodec.cpp | 6 | ||||
-rw-r--r-- | src/codec/SkBmpCodec.cpp | 4 | ||||
-rw-r--r-- | src/codec/SkCodec.cpp | 66 | ||||
-rw-r--r-- | src/codec/SkCodecPriv.h | 61 | ||||
-rw-r--r-- | src/codec/SkGifCodec.cpp | 4 | ||||
-rw-r--r-- | src/codec/SkIcoCodec.h | 6 | ||||
-rw-r--r-- | src/codec/SkJpegCodec.h | 6 | ||||
-rw-r--r-- | src/codec/SkPngCodec.cpp | 8 | ||||
-rw-r--r-- | src/codec/SkRawCodec.cpp | 4 | ||||
-rw-r--r-- | src/codec/SkWbmpCodec.cpp | 15 | ||||
-rw-r--r-- | src/codec/SkWbmpCodec.h | 2 | ||||
-rw-r--r-- | src/codec/SkWebpCodec.cpp | 17 |
14 files changed, 97 insertions, 109 deletions
diff --git a/src/android/SkBitmapRegionCodec.cpp b/src/android/SkBitmapRegionCodec.cpp index e2ab423d27..f77c70264f 100644 --- a/src/android/SkBitmapRegionCodec.cpp +++ b/src/android/SkBitmapRegionCodec.cpp @@ -116,8 +116,3 @@ bool SkBitmapRegionCodec::decodeRegion(SkBitmap* bitmap, SkBRDAllocator* allocat return true; } - -bool SkBitmapRegionCodec::conversionSupported(SkColorType colorType) { - SkImageInfo dstInfo = fCodec->getInfo().makeColorType(colorType); - return conversion_possible(dstInfo, fCodec->getInfo()); -} diff --git a/src/android/SkBitmapRegionCodec.h b/src/android/SkBitmapRegionCodec.h index a7cfe33a91..94194c089f 100644 --- a/src/android/SkBitmapRegionCodec.h +++ b/src/android/SkBitmapRegionCodec.h @@ -28,8 +28,6 @@ public: SkColorType colorType, bool requireUnpremul, sk_sp<SkColorSpace> prefColorSpace) override; - bool conversionSupported(SkColorType colorType) override; - SkEncodedImageFormat getEncodedFormat() override { return fCodec->getEncodedFormat(); } SkColorType computeOutputColorType(SkColorType requestedColorType) override { diff --git a/src/codec/SkAndroidCodec.cpp b/src/codec/SkAndroidCodec.cpp index 3a57352113..d004eb8326 100644 --- a/src/codec/SkAndroidCodec.cpp +++ b/src/codec/SkAndroidCodec.cpp @@ -66,6 +66,12 @@ SkAndroidCodec::SkAndroidCodec(SkCodec* codec) , fCodec(codec) {} +SkAndroidCodec::~SkAndroidCodec() {} + +const SkEncodedInfo& SkAndroidCodec::getEncodedInfo() const { + return fCodec->getEncodedInfo(); +} + std::unique_ptr<SkAndroidCodec> SkAndroidCodec::MakeFromStream(std::unique_ptr<SkStream> stream, SkPngChunkReader* chunkReader) { auto codec = SkCodec::MakeFromStream(std::move(stream), nullptr, chunkReader); if (nullptr == codec) { diff --git a/src/codec/SkBmpCodec.cpp b/src/codec/SkBmpCodec.cpp index 18f8768e0d..d8167efa08 100644 --- a/src/codec/SkBmpCodec.cpp +++ b/src/codec/SkBmpCodec.cpp @@ -620,9 +620,7 @@ int32_t SkBmpCodec::getDstRow(int32_t y, int32_t height) const { SkCodec::Result SkBmpCodec::prepareToDecode(const SkImageInfo& dstInfo, const SkCodec::Options& options) { - if (!conversion_possible(dstInfo, this->getInfo()) || - !this->initializeColorXform(dstInfo, options.fPremulBehavior)) - { + if (!this->initializeColorXform(dstInfo, options.fPremulBehavior)) { return kInvalidConversion; } diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp index 2b6108250c..84af2271f7 100644 --- a/src/codec/SkCodec.cpp +++ b/src/codec/SkCodec.cpp @@ -155,6 +155,29 @@ SkCodec::SkCodec(const SkEncodedInfo& info, const SkImageInfo& imageInfo, SkCodec::~SkCodec() {} +bool SkCodec::conversionSupported(const SkImageInfo& dst, SkEncodedInfo::Color srcColor, + bool srcIsOpaque, const SkColorSpace* srcCS) const { + if (!valid_alpha(dst.alphaType(), srcIsOpaque)) { + return false; + } + + switch (dst.colorType()) { + case kRGBA_8888_SkColorType: + case kBGRA_8888_SkColorType: + return true; + case kRGBA_F16_SkColorType: + return dst.colorSpace() && dst.colorSpace()->gammaIsLinear(); + case kRGB_565_SkColorType: + return srcIsOpaque; + case kGray_8_SkColorType: + return SkEncodedInfo::kGray_Color == srcColor && srcIsOpaque && + !needs_color_xform(dst, srcCS, false); + default: + return false; + } + +} + bool SkCodec::rewindIfNeeded() { // Store the value of fNeedsRewind so we can update it. Next read will // require a rewind. @@ -194,6 +217,10 @@ SkCodec::Result SkCodec::handleFrameIndex(const SkImageInfo& info, void* pixels, const Options& options) { const int index = options.fFrameIndex; if (0 == index) { + if (!this->conversionSupported(info, fEncodedInfo.color(), fEncodedInfo.opaque(), + fSrcInfo.colorSpace())) { + return kInvalidConversion; + } return kSuccess; } @@ -213,6 +240,11 @@ SkCodec::Result SkCodec::handleFrameIndex(const SkImageInfo& info, void* pixels, const auto* frame = frameHolder->getFrame(index); SkASSERT(frame); + if (!this->conversionSupported(info, fEncodedInfo.color(), !frame->hasAlpha(), + fSrcInfo.colorSpace())) { + return kInvalidConversion; + } + const int requiredFrame = frame->getRequiredFrame(); if (requiredFrame == kNone) { return kSuccess; @@ -278,10 +310,6 @@ SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t if (nullptr == options) { options = &optsStorage; } else { - const Result frameIndexResult = this->handleFrameIndex(info, pixels, rowBytes, *options); - if (frameIndexResult != kSuccess) { - return frameIndexResult; - } if (options->fSubset) { SkIRect subset(*options->fSubset); if (!this->onGetValidSubset(&subset) || subset != *options->fSubset) { @@ -292,6 +320,12 @@ SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t } } + const Result frameIndexResult = this->handleFrameIndex(info, pixels, rowBytes, + *options); + if (frameIndexResult != kSuccess) { + return frameIndexResult; + } + // FIXME: Support subsets somehow? Note that this works for SkWebpCodec // because it supports arbitrary scaling/subset combinations. if (!this->dimensionsSupported(info.dimensions())) { @@ -350,10 +384,6 @@ SkCodec::Result SkCodec::startIncrementalDecode(const SkImageInfo& info, void* p if (nullptr == options) { options = &optsStorage; } else { - const Result frameIndexResult = this->handleFrameIndex(info, pixels, rowBytes, *options); - if (frameIndexResult != kSuccess) { - return frameIndexResult; - } if (options->fSubset) { SkIRect size = SkIRect::MakeSize(info.dimensions()); if (!size.contains(*options->fSubset)) { @@ -368,6 +398,12 @@ SkCodec::Result SkCodec::startIncrementalDecode(const SkImageInfo& info, void* p } } + const Result frameIndexResult = this->handleFrameIndex(info, pixels, rowBytes, + *options); + if (frameIndexResult != kSuccess) { + return frameIndexResult; + } + if (!this->dimensionsSupported(info.dimensions())) { return kInvalidScale; } @@ -418,6 +454,18 @@ SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& info, } } + // Scanline decoding only supports decoding the first frame. + if (options->fFrameIndex != 0) { + return kUnimplemented; + } + + // The void* dst and rowbytes in handleFrameIndex or only used for decoding prior + // frames, which is not supported here anyway, so it is safe to pass nullptr/0. + const Result frameIndexResult = this->handleFrameIndex(info, nullptr, 0, *options); + if (frameIndexResult != kSuccess) { + return frameIndexResult; + } + // FIXME: Support subsets somehow? if (!this->dimensionsSupported(info.dimensions())) { return kInvalidScale; @@ -567,7 +615,7 @@ bool SkCodec::initializeColorXform(const SkImageInfo& dstInfo, fXformOnDecode = false; bool needsColorCorrectPremul = needs_premul(dstInfo, fEncodedInfo) && SkTransferFunctionBehavior::kRespect == premulBehavior; - if (needs_color_xform(dstInfo, fSrcInfo, needsColorCorrectPremul)) { + if (needs_color_xform(dstInfo, fSrcInfo.colorSpace(), needsColorCorrectPremul)) { fColorXform = SkColorSpaceXform_Base::New(fSrcInfo.colorSpace(), dstInfo.colorSpace(), premulBehavior); if (!fColorXform) { diff --git a/src/codec/SkCodecPriv.h b/src/codec/SkCodecPriv.h index cb7cd94979..a737fb7511 100644 --- a/src/codec/SkCodecPriv.h +++ b/src/codec/SkCodecPriv.h @@ -82,31 +82,20 @@ static inline bool is_coord_necessary(int srcCoord, int sampleFactor, int scaled return ((srcCoord - startCoord) % sampleFactor) == 0; } -static inline bool valid_alpha(SkAlphaType dstAlpha, SkAlphaType srcAlpha) { +static inline bool valid_alpha(SkAlphaType dstAlpha, bool srcIsOpaque) { if (kUnknown_SkAlphaType == dstAlpha) { return false; } - if (srcAlpha != dstAlpha) { - if (kOpaque_SkAlphaType == srcAlpha) { - // If the source is opaque, we can support any. + if (srcIsOpaque) { + if (kOpaque_SkAlphaType != dstAlpha) { SkCodecPrintf("Warning: an opaque image should be decoded as opaque " "- it is being decoded as non-opaque, which will draw slower\n"); - return true; - } - - // The source is not opaque - switch (dstAlpha) { - case kPremul_SkAlphaType: - case kUnpremul_SkAlphaType: - // The source is not opaque, so either of these is okay - break; - default: - // We cannot decode a non-opaque image to opaque (or unknown) - return false; } + return true; } - return true; + + return dstAlpha != kOpaque_SkAlphaType; } /* @@ -287,7 +276,7 @@ static inline bool needs_premul(const SkImageInfo& dstInfo, const SkEncodedInfo& SkEncodedInfo::kUnpremul_Alpha == encodedInfo.alpha(); } -static inline bool needs_color_xform(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo, +static inline bool needs_color_xform(const SkImageInfo& dstInfo, const SkColorSpace* srcCS, bool needsColorCorrectPremul) { // We never perform a color xform in legacy mode. if (!dstInfo.colorSpace()) { @@ -298,7 +287,7 @@ static inline bool needs_color_xform(const SkImageInfo& dstInfo, const SkImageIn bool isF16 = kRGBA_F16_SkColorType == dstInfo.colorType(); // Need a color xform when dst space does not match the src. - bool srcDstNotEqual = !SkColorSpace::Equals(srcInfo.colorSpace(), dstInfo.colorSpace()); + bool srcDstNotEqual = !SkColorSpace::Equals(srcCS, dstInfo.colorSpace()); return needsColorCorrectPremul || isF16 || srcDstNotEqual; } @@ -307,38 +296,4 @@ static inline SkAlphaType select_xform_alpha(SkAlphaType dstAlphaType, SkAlphaTy return (kOpaque_SkAlphaType == srcAlphaType) ? kOpaque_SkAlphaType : dstAlphaType; } -/* - * Alpha Type Conversions - * - kOpaque to kOpaque, kUnpremul, kPremul is valid - * - kUnpremul to kUnpremul, kPremul is valid - * - * Color Type Conversions - * - Always support kRGBA_8888, kBGRA_8888 - * - Support kRGBA_F16 when there is a linear dst color space - * - Support k565 if kOpaque and color correction is not required - * - Support k565 if it matches the src, kOpaque, and color correction is not required - */ -static inline bool conversion_possible(const SkImageInfo& dst, const SkImageInfo& src) { - // Ensure the alpha type is valid. - if (!valid_alpha(dst.alphaType(), src.alphaType())) { - return false; - } - - // Check for supported color types. - switch (dst.colorType()) { - case kRGBA_8888_SkColorType: - case kBGRA_8888_SkColorType: - return true; - case kRGBA_F16_SkColorType: - return dst.colorSpace() && dst.colorSpace()->gammaIsLinear(); - case kRGB_565_SkColorType: - return kOpaque_SkAlphaType == src.alphaType(); - case kGray_8_SkColorType: - return kGray_8_SkColorType == src.colorType() && - kOpaque_SkAlphaType == src.alphaType() && !needs_color_xform(dst, src, false); - default: - return false; - } -} - #endif // SkCodecPriv_DEFINED diff --git a/src/codec/SkGifCodec.cpp b/src/codec/SkGifCodec.cpp index d54cbd558e..4bd0e17bd0 100644 --- a/src/codec/SkGifCodec.cpp +++ b/src/codec/SkGifCodec.cpp @@ -228,9 +228,7 @@ SkCodec::Result SkGifCodec::prepareToDecode(const SkImageInfo& dstInfo, const Op const auto at = frame->hasAlpha() ? kUnpremul_SkAlphaType : kOpaque_SkAlphaType; const auto srcInfo = this->getInfo().makeAlphaType(at); - if (!conversion_possible(dstInfo, srcInfo) || - !this->initializeColorXform(dstInfo, opts.fPremulBehavior)) - { + if (!this->initializeColorXform(dstInfo, opts.fPremulBehavior)) { return gif_error("Cannot convert input type to output type.\n", kInvalidConversion); } diff --git a/src/codec/SkIcoCodec.h b/src/codec/SkIcoCodec.h index aa19c9b935..62de20f9ff 100644 --- a/src/codec/SkIcoCodec.h +++ b/src/codec/SkIcoCodec.h @@ -48,6 +48,12 @@ protected: SkScanlineOrder onGetScanlineOrder() const override; + bool conversionSupported(const SkImageInfo&, SkEncodedInfo::Color, bool, + const SkColorSpace*) const override { + // This will be checked by the embedded codec. + return true; + } + private: Result onStartScanlineDecode(const SkImageInfo& dstInfo, diff --git a/src/codec/SkJpegCodec.h b/src/codec/SkJpegCodec.h index 1409182a97..fd8ee63d6c 100644 --- a/src/codec/SkJpegCodec.h +++ b/src/codec/SkJpegCodec.h @@ -58,6 +58,12 @@ protected: bool onDimensionsSupported(const SkISize&) override; + bool conversionSupported(const SkImageInfo&, SkEncodedInfo::Color, bool, + const SkColorSpace*) const override { + // This class checks for conversion after creating colorXform. + return true; + } + private: /* diff --git a/src/codec/SkPngCodec.cpp b/src/codec/SkPngCodec.cpp index 13e45ab609..c5dae3ed4a 100644 --- a/src/codec/SkPngCodec.cpp +++ b/src/codec/SkPngCodec.cpp @@ -1086,10 +1086,6 @@ bool SkPngCodec::onRewind() { SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, const Options& options, int* rowsDecoded) { - if (!conversion_possible(dstInfo, this->getInfo())) { - return kInvalidConversion; - } - Result result = this->initializeXforms(dstInfo, options); if (kSuccess != result) { return result; @@ -1106,10 +1102,6 @@ SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, SkCodec::Result SkPngCodec::onStartIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, const SkCodec::Options& options) { - if (!conversion_possible(dstInfo, this->getInfo())) { - return kInvalidConversion; - } - Result result = this->initializeXforms(dstInfo, options); if (kSuccess != result) { return result; diff --git a/src/codec/SkRawCodec.cpp b/src/codec/SkRawCodec.cpp index cf41d17e9b..93c6db56fb 100644 --- a/src/codec/SkRawCodec.cpp +++ b/src/codec/SkRawCodec.cpp @@ -696,9 +696,7 @@ std::unique_ptr<SkCodec> SkRawCodec::MakeFromStream(std::unique_ptr<SkStream> st SkCodec::Result SkRawCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options& options, int* rowsDecoded) { - if (!conversion_possible(dstInfo, this->getInfo()) || - !this->initializeColorXform(dstInfo, options.fPremulBehavior)) - { + if (!this->initializeColorXform(dstInfo, options.fPremulBehavior)) { SkCodecPrintf("Error: cannot convert input type to output type.\n"); return kInvalidConversion; } diff --git a/src/codec/SkWbmpCodec.cpp b/src/codec/SkWbmpCodec.cpp index 934d7d5b9a..bc796c4fcc 100644 --- a/src/codec/SkWbmpCodec.cpp +++ b/src/codec/SkWbmpCodec.cpp @@ -108,6 +108,11 @@ SkEncodedImageFormat SkWbmpCodec::onGetEncodedFormat() const { return SkEncodedImageFormat::kWBMP; } +bool SkWbmpCodec::conversionSupported(const SkImageInfo& dst, SkEncodedInfo::Color srcColor, + bool srcIsOpaque, const SkColorSpace* srcCS) const { + return valid_color_type(dst) && valid_alpha(dst.alphaType(), srcIsOpaque); +} + SkCodec::Result SkWbmpCodec::onGetPixels(const SkImageInfo& info, void* dst, size_t rowBytes, @@ -118,10 +123,6 @@ SkCodec::Result SkWbmpCodec::onGetPixels(const SkImageInfo& info, return kUnimplemented; } - if (!valid_color_type(info) || !valid_alpha(info.alphaType(), this->getInfo().alphaType())) { - return kInvalidConversion; - } - // Initialize the swizzler std::unique_ptr<SkSwizzler> swizzler(this->initializeSwizzler(info, options)); SkASSERT(swizzler); @@ -186,12 +187,6 @@ SkCodec::Result SkWbmpCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, return kUnimplemented; } - if (!valid_color_type(dstInfo) || - !valid_alpha(dstInfo.alphaType(), this->getInfo().alphaType())) - { - return kInvalidConversion; - } - // Initialize the swizzler fSwizzler.reset(this->initializeSwizzler(dstInfo, options)); SkASSERT(fSwizzler); diff --git a/src/codec/SkWbmpCodec.h b/src/codec/SkWbmpCodec.h index 03287710e0..f26967faa5 100644 --- a/src/codec/SkWbmpCodec.h +++ b/src/codec/SkWbmpCodec.h @@ -28,6 +28,8 @@ protected: Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&, int*) override; bool onRewind() override; + bool conversionSupported(const SkImageInfo& dst, SkEncodedInfo::Color srcColor, + bool srcIsOpaque, const SkColorSpace* srcCS) const override; private: /* * Returns a swizzler on success, nullptr on failure diff --git a/src/codec/SkWebpCodec.cpp b/src/codec/SkWebpCodec.cpp index 94fa175f82..38feb827e4 100644 --- a/src/codec/SkWebpCodec.cpp +++ b/src/codec/SkWebpCodec.cpp @@ -398,23 +398,14 @@ static void blend_line(SkColorType dstCT, void* dst, SkCodec::Result SkWebpCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, const Options& options, int* rowsDecodedPtr) { + if (!this->initializeColorXform(dstInfo, options.fPremulBehavior)) { + return kInvalidConversion; + } + const int index = options.fFrameIndex; SkASSERT(0 == index || index < fFrameHolder.size()); const auto& srcInfo = this->getInfo(); - { - auto info = srcInfo; - if (index > 0) { - auto alphaType = alpha_type(fFrameHolder.frame(index)->hasAlpha()); - info = info.makeAlphaType(alphaType); - } - if (!conversion_possible(dstInfo, info) || - !this->initializeColorXform(dstInfo, options.fPremulBehavior)) - { - return kInvalidConversion; - } - } - SkASSERT(0 == index || (!options.fSubset && dstInfo.dimensions() == srcInfo.dimensions())); WebPDecoderConfig config; |