aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Leon Scroggins III <scroggo@google.com>2017-08-15 12:24:02 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-08-17 16:09:31 +0000
commit0741818e7ab4e9ea8505b8a8687412f0e3804c65 (patch)
treeac183b3107e97b0717319fd403f6d552fdbd840f /src
parentde44c2df9469e70f57f05d262cd1a245b2ff5e90 (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.cpp5
-rw-r--r--src/android/SkBitmapRegionCodec.h2
-rw-r--r--src/codec/SkAndroidCodec.cpp6
-rw-r--r--src/codec/SkBmpCodec.cpp4
-rw-r--r--src/codec/SkCodec.cpp66
-rw-r--r--src/codec/SkCodecPriv.h61
-rw-r--r--src/codec/SkGifCodec.cpp4
-rw-r--r--src/codec/SkIcoCodec.h6
-rw-r--r--src/codec/SkJpegCodec.h6
-rw-r--r--src/codec/SkPngCodec.cpp8
-rw-r--r--src/codec/SkRawCodec.cpp4
-rw-r--r--src/codec/SkWbmpCodec.cpp15
-rw-r--r--src/codec/SkWbmpCodec.h2
-rw-r--r--src/codec/SkWebpCodec.cpp17
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;