aboutsummaryrefslogtreecommitdiffhomepage
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
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>
-rw-r--r--dm/DM.cpp174
-rw-r--r--dm/DMSrcSink.cpp4
-rw-r--r--include/android/SkBitmapRegionDecoder.h5
-rw-r--r--include/codec/SkAndroidCodec.h3
-rw-r--r--include/codec/SkCodec.h7
-rw-r--r--include/codec/SkEncodedInfo.h2
-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
-rw-r--r--tests/CodecTest.cpp6
21 files changed, 195 insertions, 212 deletions
diff --git a/dm/DM.cpp b/dm/DM.cpp
index afc853de90..37ff24d8d6 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -529,6 +529,65 @@ static void push_image_gen_src(Path path, ImageGenSrc::Mode mode, SkAlphaType al
push_src("image", folder, src);
}
+static void push_brd_src(Path path, CodecSrc::DstColorType dstColorType, BRDSrc::Mode mode,
+ uint32_t sampleSize) {
+ SkString folder("brd_android_codec");
+ switch (mode) {
+ case BRDSrc::kFullImage_Mode:
+ break;
+ case BRDSrc::kDivisor_Mode:
+ folder.append("_divisor");
+ break;
+ default:
+ SkASSERT(false);
+ return;
+ }
+
+ switch (dstColorType) {
+ case CodecSrc::kGetFromCanvas_DstColorType:
+ break;
+ case CodecSrc::kGrayscale_Always_DstColorType:
+ folder.append("_kGray");
+ break;
+ default:
+ SkASSERT(false);
+ return;
+ }
+
+ if (1 != sampleSize) {
+ folder.appendf("_%.3f", 1.0f / (float) sampleSize);
+ }
+
+ BRDSrc* src = new BRDSrc(path, mode, dstColorType, sampleSize);
+ push_src("image", folder, src);
+}
+
+static void push_brd_srcs(Path path, bool gray) {
+ if (gray) {
+ // Only run grayscale to one sampleSize and Mode. Though interesting
+ // to test grayscale, it should not reveal anything across various
+ // sampleSizes and Modes
+ // Arbitrarily choose Mode and sampleSize.
+ push_brd_src(path, CodecSrc::kGrayscale_Always_DstColorType,
+ BRDSrc::kFullImage_Mode, 2);
+ }
+
+ // Test on a variety of sampleSizes, making sure to include:
+ // - 2, 4, and 8, which are natively supported by jpeg
+ // - multiples of 2 which are not divisible by 4 (analogous for 4)
+ // - larger powers of two, since BRD clients generally use powers of 2
+ // We will only produce output for the larger sizes on large images.
+ const uint32_t sampleSizes[] = { 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 24, 32, 64 };
+
+ const BRDSrc::Mode modes[] = { BRDSrc::kFullImage_Mode, BRDSrc::kDivisor_Mode, };
+
+ for (uint32_t sampleSize : sampleSizes) {
+ for (BRDSrc::Mode mode : modes) {
+ push_brd_src(path, CodecSrc::kGetFromCanvas_DstColorType, mode, sampleSize);
+ }
+ }
+}
+
static void push_codec_srcs(Path path) {
sk_sp<SkData> encoded(SkData::MakeFromFileName(path.c_str()));
if (!encoded) {
@@ -641,16 +700,31 @@ static void push_codec_srcs(Path path) {
}
}
- static const char* const rawExts[] = {
- "arw", "cr2", "dng", "nef", "nrw", "orf", "raf", "rw2", "pef", "srw",
- "ARW", "CR2", "DNG", "NEF", "NRW", "ORF", "RAF", "RW2", "PEF", "SRW",
- };
+ const char* ext = strrchr(path.c_str(), '.');
+ if (ext) {
+ ext++;
- // There is not currently a reason to test RAW images on image generator.
- // If we want to enable these tests, we will need to fix skbug.com/5079.
- for (const char* ext : rawExts) {
- if (path.endsWith(ext)) {
- return;
+ static const char* const rawExts[] = {
+ "arw", "cr2", "dng", "nef", "nrw", "orf", "raf", "rw2", "pef", "srw",
+ "ARW", "CR2", "DNG", "NEF", "NRW", "ORF", "RAF", "RW2", "PEF", "SRW",
+ };
+ for (const char* rawExt : rawExts) {
+ if (0 == strcmp(rawExt, ext)) {
+ // RAW is not supported by image generator (skbug.com/5079) or BRD.
+ return;
+ }
+ }
+
+ static const char* const brdExts[] = {
+ "jpg", "jpeg", "png", "webp",
+ "JPG", "JPEG", "PNG", "WEBP",
+ };
+ for (const char* brdExt : brdExts) {
+ if (0 == strcmp(brdExt, ext)) {
+ bool gray = codec->getEncodedInfo().color() == SkEncodedInfo::kGray_Color;
+ push_brd_srcs(path, gray);
+ break;
+ }
}
}
@@ -678,80 +752,6 @@ static void push_codec_srcs(Path path) {
}
}
-static void push_brd_src(Path path, CodecSrc::DstColorType dstColorType, BRDSrc::Mode mode,
- uint32_t sampleSize) {
- SkString folder("brd_android_codec");
- switch (mode) {
- case BRDSrc::kFullImage_Mode:
- break;
- case BRDSrc::kDivisor_Mode:
- folder.append("_divisor");
- break;
- default:
- SkASSERT(false);
- return;
- }
-
- switch (dstColorType) {
- case CodecSrc::kGetFromCanvas_DstColorType:
- break;
- case CodecSrc::kGrayscale_Always_DstColorType:
- folder.append("_kGray");
- break;
- default:
- SkASSERT(false);
- return;
- }
-
- if (1 != sampleSize) {
- folder.appendf("_%.3f", 1.0f / (float) sampleSize);
- }
-
- BRDSrc* src = new BRDSrc(path, mode, dstColorType, sampleSize);
- push_src("image", folder, src);
-}
-
-static void push_brd_srcs(Path path) {
- // Only run grayscale to one sampleSize and Mode. Though interesting
- // to test grayscale, it should not reveal anything across various
- // sampleSizes and Modes
- // Arbitrarily choose Mode and sampleSize.
- push_brd_src(path, CodecSrc::kGrayscale_Always_DstColorType, BRDSrc::kFullImage_Mode, 2);
-
-
- // Test on a variety of sampleSizes, making sure to include:
- // - 2, 4, and 8, which are natively supported by jpeg
- // - multiples of 2 which are not divisible by 4 (analogous for 4)
- // - larger powers of two, since BRD clients generally use powers of 2
- // We will only produce output for the larger sizes on large images.
- const uint32_t sampleSizes[] = { 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 24, 32, 64 };
-
- const BRDSrc::Mode modes[] = {
- BRDSrc::kFullImage_Mode,
- BRDSrc::kDivisor_Mode,
- };
-
- for (uint32_t sampleSize : sampleSizes) {
- for (BRDSrc::Mode mode : modes) {
- push_brd_src(path, CodecSrc::kGetFromCanvas_DstColorType, mode, sampleSize);
- }
- }
-}
-
-static bool brd_supported(const char* ext) {
- static const char* const exts[] = {
- "jpg", "jpeg", "png", "webp",
- "JPG", "JPEG", "PNG", "WEBP",
- };
-
- for (uint32_t i = 0; i < SK_ARRAY_COUNT(exts); i++) {
- if (0 == strcmp(exts[i], ext)) {
- return true;
- }
- }
- return false;
-}
-
template <typename T>
void gather_file_srcs(const SkCommandLineFlags::StringArray& flags, const char* ext) {
for (int i = 0; i < flags.count(); i++) {
@@ -785,14 +785,6 @@ static bool gather_srcs() {
for (auto image : images) {
push_codec_srcs(image);
- if (FLAGS_simpleCodec) {
- continue;
- }
-
- const char* ext = strrchr(image.c_str(), '.');
- if (ext && brd_supported(ext+1)) {
- push_brd_srcs(image);
- }
}
SkTArray<SkString> colorImages;
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index e255dd3cdd..a862969e4a 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -152,10 +152,6 @@ Error BRDSrc::draw(SkCanvas* canvas) const {
return Error::Nonfatal(SkStringPrintf("Could not create brd for %s.", fPath.c_str()));
}
- if (!brd->conversionSupported(colorType)) {
- return Error::Nonfatal("Cannot convert to color type.");
- }
-
const uint32_t width = brd->width();
const uint32_t height = brd->height();
// Visually inspecting very small output images is not necessary.
diff --git a/include/android/SkBitmapRegionDecoder.h b/include/android/SkBitmapRegionDecoder.h
index df0c370338..c41d11247b 100644
--- a/include/android/SkBitmapRegionDecoder.h
+++ b/include/android/SkBitmapRegionDecoder.h
@@ -63,11 +63,6 @@ public:
const SkIRect& desiredSubset, int sampleSize,
SkColorType colorType, bool requireUnpremul,
sk_sp<SkColorSpace> prefColorSpace = nullptr) = 0;
- /*
- * @param Requested destination color type
- * @return true if we support the requested color type and false otherwise
- */
- virtual bool conversionSupported(SkColorType colorType) = 0;
virtual SkEncodedImageFormat getEncodedFormat() = 0;
diff --git a/include/codec/SkAndroidCodec.h b/include/codec/SkAndroidCodec.h
index 3571108edd..cc93bf18c4 100644
--- a/include/codec/SkAndroidCodec.h
+++ b/include/codec/SkAndroidCodec.h
@@ -41,8 +41,9 @@ public:
*/
static std::unique_ptr<SkAndroidCodec> MakeFromData(sk_sp<SkData>, SkPngChunkReader* = nullptr);
- virtual ~SkAndroidCodec() {}
+ virtual ~SkAndroidCodec();
+ const SkEncodedInfo& getEncodedInfo() const;
const SkImageInfo& getInfo() const { return fInfo; }
diff --git a/include/codec/SkCodec.h b/include/codec/SkCodec.h
index fb4f165dbf..8ec44c8539 100644
--- a/include/codec/SkCodec.h
+++ b/include/codec/SkCodec.h
@@ -846,6 +846,13 @@ private:
bool fStartedIncrementalDecode;
/**
+ * Return whether {srcColor, srcIsOpaque, srcCS} can convert to dst.
+ *
+ * Will be called for the appropriate frame, prior to initializing the colorXform.
+ */
+ virtual bool conversionSupported(const SkImageInfo& dst, SkEncodedInfo::Color srcColor,
+ bool srcIsOpaque, const SkColorSpace* srcCS) const;
+ /**
* Return whether these dimensions are supported as a scale.
*
* The codec may choose to cache the information about scale and subset.
diff --git a/include/codec/SkEncodedInfo.h b/include/codec/SkEncodedInfo.h
index 3b1ce48713..dce88cadc1 100644
--- a/include/codec/SkEncodedInfo.h
+++ b/include/codec/SkEncodedInfo.h
@@ -156,6 +156,8 @@ public:
Color color() const { return fColor; }
Alpha alpha() const { return fAlpha; }
+ bool opaque() const { return fAlpha == kOpaque_Alpha; }
+
uint8_t bitsPerComponent() const { return fBitsPerComponent; }
uint8_t bitsPerPixel() const {
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;
diff --git a/tests/CodecTest.cpp b/tests/CodecTest.cpp
index 4e68cd1ac6..6ffc44874c 100644
--- a/tests/CodecTest.cpp
+++ b/tests/CodecTest.cpp
@@ -1138,14 +1138,16 @@ static void test_conversion_possible(skiatest::Reporter* r, const char* path,
if (supportsScanlineDecoder) {
REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result);
} else {
- REPORTER_ASSERT(r, SkCodec::kUnimplemented == result);
+ REPORTER_ASSERT(r, SkCodec::kUnimplemented == result
+ || SkCodec::kInvalidConversion == result);
}
result = codec->startIncrementalDecode(infoF16, bm.getPixels(), bm.rowBytes());
if (supportsIncrementalDecoder) {
REPORTER_ASSERT(r, SkCodec::kInvalidConversion == result);
} else {
- REPORTER_ASSERT(r, SkCodec::kUnimplemented == result);
+ REPORTER_ASSERT(r, SkCodec::kUnimplemented == result
+ || SkCodec::kInvalidConversion == result);
}
SkASSERT(SkColorSpace_Base::Type::kXYZ == as_CSB(infoF16.colorSpace())->type());