Reland "Switch SkCodec to use skcms plus fixes""
This reverts commit 83988edfd3256dc822b961362aad7fbc3e0cdabc.
The CTS failure was actually due to another CL.
TBR=brianosman@google.com
TBR=djsollen@google.com
Bug: skia:6839
Bug: skia:8052
Bug: skia:8278
Change-Id: Id9f152ec2c66467d90f49df223cb9b7c168ac2ac
Reviewed-on: https://skia-review.googlesource.com/149483
Reviewed-by: Leon Scroggins <scroggo@google.com>
Commit-Queue: Leon Scroggins <scroggo@google.com>
diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp
index 5564e89..d12646a 100644
--- a/src/codec/SkCodec.cpp
+++ b/src/codec/SkCodec.cpp
@@ -9,7 +9,6 @@
#include "SkCodec.h"
#include "SkCodecPriv.h"
#include "SkColorSpace.h"
-#include "SkColorSpaceXformPriv.h"
#include "SkData.h"
#include "SkFrameHolder.h"
#include "SkGifCodec.h"
@@ -126,26 +125,10 @@
return MakeFromStream(SkMemoryStream::Make(std::move(data)), nullptr, reader);
}
-SkCodec::SkCodec(int width, int height, const SkEncodedInfo& info,
- XformFormat srcFormat, std::unique_ptr<SkStream> stream,
- sk_sp<SkColorSpace> colorSpace, SkEncodedOrigin origin)
- : fEncodedInfo(info)
- , fSrcInfo(info.makeImageInfo(width, height, std::move(colorSpace)))
- , fSrcXformFormat(srcFormat)
- , fStream(std::move(stream))
- , fNeedsRewind(false)
- , fOrigin(origin)
- , fDstInfo()
- , fOptions()
- , fCurrScanline(-1)
- , fStartedIncrementalDecode(false)
-{}
-
-SkCodec::SkCodec(const SkEncodedInfo& info, const SkImageInfo& imageInfo,
- XformFormat srcFormat, std::unique_ptr<SkStream> stream,
- SkEncodedOrigin origin)
- : fEncodedInfo(info)
- , fSrcInfo(imageInfo)
+SkCodec::SkCodec(SkEncodedInfo&& info, XformFormat srcFormat, std::unique_ptr<SkStream> stream,
+ SkEncodedOrigin origin)
+ : fEncodedInfo(std::move(info))
+ , fSrcInfo(fEncodedInfo.makeImageInfo())
, fSrcXformFormat(srcFormat)
, fStream(std::move(stream))
, fNeedsRewind(false)
@@ -159,7 +142,7 @@
SkCodec::~SkCodec() {}
bool SkCodec::conversionSupported(const SkImageInfo& dst, SkColorType srcColor,
- bool srcIsOpaque, const SkColorSpace* srcCS) const {
+ bool srcIsOpaque, bool needsColorXform) {
if (!valid_alpha(dst.alphaType(), srcIsOpaque)) {
return false;
}
@@ -173,8 +156,8 @@
case kRGB_565_SkColorType:
return srcIsOpaque;
case kGray_8_SkColorType:
- return kGray_8_SkColorType == srcColor && srcIsOpaque &&
- !needs_color_xform(dst, srcCS);
+ SkASSERT(!needsColorXform);
+ return kGray_8_SkColorType == srcColor && srcIsOpaque;
case kAlpha_8_SkColorType:
// conceptually we can convert anything into alpha_8, but we haven't actually coded
// all of those other conversions yet, so only return true for the case we have codec.
@@ -182,7 +165,6 @@
default:
return false;
}
-
}
bool SkCodec::rewindIfNeeded() {
@@ -245,13 +227,8 @@
const Options& options) {
const int index = options.fFrameIndex;
if (0 == index) {
- if (!this->conversionSupported(info, fSrcInfo.colorType(), fEncodedInfo.opaque(),
- fSrcInfo.colorSpace())
- || !this->initializeColorXform(info, fEncodedInfo.alpha()))
- {
- return kInvalidConversion;
- }
- return kSuccess;
+ return this->initializeColorXform(info, fEncodedInfo.alpha(), fEncodedInfo.opaque())
+ ? kSuccess : kInvalidConversion;
}
if (index < 0) {
@@ -274,11 +251,6 @@
const auto* frame = frameHolder->getFrame(index);
SkASSERT(frame);
- if (!this->conversionSupported(info, fSrcInfo.colorType(), !frame->hasAlpha(),
- fSrcInfo.colorSpace())) {
- return kInvalidConversion;
- }
-
const int requiredFrame = frame->getRequiredFrame();
if (requiredFrame != kNoFrame) {
if (options.fPriorFrame != kNoFrame) {
@@ -324,7 +296,8 @@
}
}
- return this->initializeColorXform(info, frame->reportedAlpha()) ? kSuccess : kInvalidConversion;
+ return this->initializeColorXform(info, frame->reportedAlpha(), !frame->hasAlpha())
+ ? kSuccess : kInvalidConversion;
}
SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
@@ -612,63 +585,80 @@
}
}
-static inline SkColorSpaceXform::ColorFormat select_xform_format_ct(SkColorType colorType) {
+static inline bool select_xform_format(SkColorType colorType, bool forColorTable,
+ skcms_PixelFormat* outFormat) {
+ SkASSERT(outFormat);
+
switch (colorType) {
case kRGBA_8888_SkColorType:
- return SkColorSpaceXform::kRGBA_8888_ColorFormat;
+ *outFormat = skcms_PixelFormat_RGBA_8888;
+ break;
case kBGRA_8888_SkColorType:
- return SkColorSpaceXform::kBGRA_8888_ColorFormat;
+ *outFormat = skcms_PixelFormat_BGRA_8888;
+ break;
case kRGB_565_SkColorType:
+ if (forColorTable) {
#ifdef SK_PMCOLOR_IS_RGBA
- return SkColorSpaceXform::kRGBA_8888_ColorFormat;
+ *outFormat = skcms_PixelFormat_RGBA_8888;
#else
- return SkColorSpaceXform::kBGRA_8888_ColorFormat;
+ *outFormat = skcms_PixelFormat_BGRA_8888;
#endif
+ break;
+ }
+ *outFormat = skcms_PixelFormat_BGR_565;
+ break;
+ case kRGBA_F16_SkColorType:
+ *outFormat = skcms_PixelFormat_RGBA_hhhh;
+ break;
default:
- SkASSERT(false);
- return SkColorSpaceXform::kRGBA_8888_ColorFormat;
- }
-}
-
-bool SkCodec::initializeColorXform(const SkImageInfo& dstInfo, SkEncodedInfo::Alpha encodedAlpha) {
- fColorXform = nullptr;
- fXformOnDecode = false;
- if (!this->usesColorXform()) {
- return true;
- }
- // FIXME: In SkWebpCodec, if a frame is blending with a prior frame, we don't need
- // a colorXform to do a color correct premul, since the blend step will handle
- // premultiplication. But there is no way to know whether we need to blend from
- // inside this call.
- if (needs_color_xform(dstInfo, fSrcInfo.colorSpace())) {
- fColorXform = SkMakeColorSpaceXform(fSrcInfo.colorSpace(), dstInfo.colorSpace());
- if (!fColorXform) {
return false;
- }
-
- // We will apply the color xform when reading the color table unless F16 is requested.
- fXformOnDecode = SkEncodedInfo::kPalette_Color != fEncodedInfo.color()
- || kRGBA_F16_SkColorType == dstInfo.colorType();
- if (fXformOnDecode) {
- fDstXformFormat = select_xform_format(dstInfo.colorType());
- } else {
- fDstXformFormat = select_xform_format_ct(dstInfo.colorType());
- }
}
-
return true;
}
-void SkCodec::applyColorXform(void* dst, const void* src, int count, SkAlphaType at) const {
- SkASSERT(fColorXform);
- SkAssertResult(fColorXform->apply(fDstXformFormat, dst,
- fSrcXformFormat, src,
- count, at));
+bool SkCodec::initializeColorXform(const SkImageInfo& dstInfo, SkEncodedInfo::Alpha encodedAlpha,
+ bool srcIsOpaque) {
+ fXformTime = kNo_XformTime;
+ bool needsColorXform = false;
+ if (this->usesColorXform() && dstInfo.colorSpace()) {
+ dstInfo.colorSpace()->toProfile(&fDstProfile);
+ if (kRGBA_F16_SkColorType == dstInfo.colorType()
+ || !skcms_ApproximatelyEqualProfiles(fEncodedInfo.profile(), &fDstProfile) ) {
+ needsColorXform = true;
+ if (kGray_8_SkColorType == dstInfo.colorType()) {
+ return false;
+ }
+ }
+ }
+
+ if (!this->conversionSupported(dstInfo, fSrcInfo.colorType(), srcIsOpaque, needsColorXform)) {
+ return false;
+ }
+
+ if (needsColorXform) {
+ fXformTime = SkEncodedInfo::kPalette_Color != fEncodedInfo.color()
+ || kRGBA_F16_SkColorType == dstInfo.colorType()
+ ? kDecodeRow_XformTime : kPalette_XformTime;
+ if (!select_xform_format(dstInfo.colorType(), fXformTime == kPalette_XformTime,
+ &fDstXformFormat)) {
+ return false;
+ }
+ if (encodedAlpha == SkEncodedInfo::kUnpremul_Alpha
+ && dstInfo.alphaType() == kPremul_SkAlphaType) {
+ fDstXformAlphaFormat = skcms_AlphaFormat_PremulAsEncoded;
+ } else {
+ fDstXformAlphaFormat = skcms_AlphaFormat_Unpremul;
+ }
+ }
+ return true;
}
void SkCodec::applyColorXform(void* dst, const void* src, int count) const {
- auto alphaType = select_xform_alpha(fDstInfo.alphaType(), fSrcInfo.alphaType());
- this->applyColorXform(dst, src, count, alphaType);
+ const auto* srcProfile = fEncodedInfo.profile();
+ SkASSERT(srcProfile);
+ SkAssertResult(skcms_Transform(src, fSrcXformFormat, skcms_AlphaFormat_Unpremul, srcProfile,
+ dst, fDstXformFormat, fDstXformAlphaFormat, &fDstProfile,
+ count));
}
std::vector<SkCodec::FrameInfo> SkCodec::getFrameInfo() {