Reland "Add SkColorSpaceXform_skcms"
This reverts commit8103ecae7b
. Reason for revert: Investigated the 565 diffs, they appear to be *more* correct. Original change's description: > Revert "Add SkColorSpaceXform_skcms" > > This reverts commit67f62b1a61
. > > Reason for revert: I want to investigate the image/colorimage gold diffs. May be correct, but some of them are pretty large. > > Original change's description: > > Add SkColorSpaceXform_skcms > > > > Currently only enabled in Skia dev builds. Passes all unit > > tests. Has some GM differences, but nothing major. > > > > Bug: skia: > > Change-Id: Ib87f8cff44649c731e829f063ccef448d67d1910 > > Reviewed-on: https://skia-review.googlesource.com/112520 > > Commit-Queue: Brian Osman <brianosman@google.com> > > Reviewed-by: Mike Klein <mtklein@google.com> > > TBR=mtklein@google.com,brianosman@google.com,reed@google.com > > Change-Id: Ib4d7174f5c2700d6f742f488e740e5a6c87ac7a8 > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Bug: skia: > Reviewed-on: https://skia-review.googlesource.com/113880 > Reviewed-by: Brian Osman <brianosman@google.com> > Commit-Queue: Brian Osman <brianosman@google.com> TBR=mtklein@google.com,brianosman@google.com,reed@google.com Change-Id: I6501ff55349a6aeed62bb64afc47f789e8cc3460 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: skia: Reviewed-on: https://skia-review.googlesource.com/114040 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
4000a5e622
commit
57337d90a5
3
BUILD.gn
3
BUILD.gn
@ -726,11 +726,12 @@ optional("raw") {
|
|||||||
optional("skcms") {
|
optional("skcms") {
|
||||||
enabled = skia_use_skcms
|
enabled = skia_use_skcms
|
||||||
|
|
||||||
|
public_defines = [ "SK_USE_SKCMS" ]
|
||||||
deps = [
|
deps = [
|
||||||
"//third_party/skcms",
|
"//third_party/skcms",
|
||||||
]
|
]
|
||||||
sources = [
|
sources = [
|
||||||
# TODO
|
"src/core/SkColorSpaceXform_skcms.cpp",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,6 +241,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
static bool Equals(const SkColorSpace* src, const SkColorSpace* dst);
|
static bool Equals(const SkColorSpace* src, const SkColorSpace* dst);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this color space was constructed from an ICC profile, return that profile data.
|
||||||
|
* Otherise, return nullptr.
|
||||||
|
*/
|
||||||
|
const SkData* profileData() const { return this->onProfileData(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual const SkMatrix44* onToXYZD50() const = 0;
|
virtual const SkMatrix44* onToXYZD50() const = 0;
|
||||||
virtual uint32_t onToXYZD50Hash() const = 0;
|
virtual uint32_t onToXYZD50Hash() const = 0;
|
||||||
|
@ -48,10 +48,8 @@ static constexpr SkColorSpaceTransferFn gSRGB_TransferFn =
|
|||||||
static constexpr SkColorSpaceTransferFn g2Dot2_TransferFn =
|
static constexpr SkColorSpaceTransferFn g2Dot2_TransferFn =
|
||||||
{ 2.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
|
{ 2.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
|
||||||
// gLinear_TransferFn.fD > 1.0f: Make sure that we use the linear segment of
|
|
||||||
// the transfer function even when the x-value is 1.0f.
|
|
||||||
static constexpr SkColorSpaceTransferFn gLinear_TransferFn =
|
static constexpr SkColorSpaceTransferFn gLinear_TransferFn =
|
||||||
{ 0.0f, 0.0f, 0.0f, 1.0f, 1.0000001f, 0.0f, 0.0f };
|
{ 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
|
||||||
static constexpr SkColorSpaceTransferFn gDCIP3_TransferFn =
|
static constexpr SkColorSpaceTransferFn gDCIP3_TransferFn =
|
||||||
{ 2.399994f, 0.947998047f, 0.0520019531f, 0.0769958496f, 0.0390014648f, 0.0f, 0.0f };
|
{ 2.399994f, 0.947998047f, 0.0520019531f, 0.0769958496f, 0.0390014648f, 0.0f, 0.0f };
|
||||||
|
@ -317,9 +317,14 @@ std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform_Base::New(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (src->toXYZD50()) {
|
if (src->toXYZD50()) {
|
||||||
|
#if defined(SK_USE_SKCMS)
|
||||||
|
// TODO: Use this unconditionally, once A2B transform is implemented in skcms.
|
||||||
|
return MakeSkcmsXform(src, dst, premulBehavior);
|
||||||
|
#else
|
||||||
return skstd::make_unique<SkColorSpaceXform_XYZ>(static_cast<SkColorSpace_XYZ*>(src),
|
return skstd::make_unique<SkColorSpaceXform_XYZ>(static_cast<SkColorSpace_XYZ*>(src),
|
||||||
static_cast<SkColorSpace_XYZ*>(dst),
|
static_cast<SkColorSpace_XYZ*>(dst),
|
||||||
premulBehavior);
|
premulBehavior);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return skstd::make_unique<SkColorSpaceXform_A2B>(static_cast<SkColorSpace_A2B*>(src),
|
return skstd::make_unique<SkColorSpaceXform_A2B>(static_cast<SkColorSpace_A2B*>(src),
|
||||||
static_cast<SkColorSpace_XYZ*>(dst));
|
static_cast<SkColorSpace_XYZ*>(dst));
|
||||||
|
@ -71,4 +71,9 @@ private:
|
|||||||
// For testing. Bypasses opts for when src and dst color spaces are equal.
|
// For testing. Bypasses opts for when src and dst color spaces are equal.
|
||||||
std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace_XYZ* space);
|
std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace_XYZ* space);
|
||||||
|
|
||||||
|
#if defined(SK_USE_SKCMS)
|
||||||
|
std::unique_ptr<SkColorSpaceXform> MakeSkcmsXform(SkColorSpace* src, SkColorSpace* dst,
|
||||||
|
SkTransferFunctionBehavior premulBehavior);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
119
src/core/SkColorSpaceXform_skcms.cpp
Normal file
119
src/core/SkColorSpaceXform_skcms.cpp
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 Google Inc.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SkColorSpaceXform.h"
|
||||||
|
#include "SkData.h"
|
||||||
|
#include "SkMakeUnique.h"
|
||||||
|
#include "skcms.h"
|
||||||
|
|
||||||
|
class SkColorSpaceXform_skcms : public SkColorSpaceXform {
|
||||||
|
public:
|
||||||
|
SkColorSpaceXform_skcms(const skcms_ICCProfile& srcProfile,
|
||||||
|
const skcms_ICCProfile& dstProfile,
|
||||||
|
skcms_AlphaFormat premulFormat)
|
||||||
|
: fSrcProfile(srcProfile)
|
||||||
|
, fDstProfile(dstProfile)
|
||||||
|
, fPremulFormat(premulFormat)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool apply(ColorFormat, void*, ColorFormat, const void*, int, SkAlphaType) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
skcms_ICCProfile fSrcProfile;
|
||||||
|
skcms_ICCProfile fDstProfile;
|
||||||
|
skcms_AlphaFormat fPremulFormat;
|
||||||
|
};
|
||||||
|
|
||||||
|
static skcms_PixelFormat get_skcms_format(SkColorSpaceXform::ColorFormat fmt) {
|
||||||
|
switch (fmt) {
|
||||||
|
case SkColorSpaceXform::kRGBA_8888_ColorFormat:
|
||||||
|
return skcms_PixelFormat_RGBA_8888;
|
||||||
|
case SkColorSpaceXform::kBGRA_8888_ColorFormat:
|
||||||
|
return skcms_PixelFormat_BGRA_8888;
|
||||||
|
case SkColorSpaceXform::kRGB_U16_BE_ColorFormat:
|
||||||
|
return skcms_PixelFormat_RGB_161616;
|
||||||
|
case SkColorSpaceXform::kRGBA_U16_BE_ColorFormat:
|
||||||
|
return skcms_PixelFormat_RGBA_16161616;
|
||||||
|
case SkColorSpaceXform::kRGBA_F16_ColorFormat:
|
||||||
|
return skcms_PixelFormat_RGBA_hhhh;
|
||||||
|
case SkColorSpaceXform::kRGBA_F32_ColorFormat:
|
||||||
|
return skcms_PixelFormat_RGBA_ffff;
|
||||||
|
case SkColorSpaceXform::kBGR_565_ColorFormat:
|
||||||
|
return skcms_PixelFormat_BGR_565;
|
||||||
|
default:
|
||||||
|
SkDEBUGFAIL("Invalid ColorFormat");
|
||||||
|
return skcms_PixelFormat_RGBA_8888;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkColorSpaceXform_skcms::apply(ColorFormat dstFormat, void* dst,
|
||||||
|
ColorFormat srcFormat, const void* src,
|
||||||
|
int count, SkAlphaType alphaType) const {
|
||||||
|
skcms_AlphaFormat srcAlpha = skcms_AlphaFormat_Unpremul;
|
||||||
|
skcms_AlphaFormat dstAlpha = kPremul_SkAlphaType == alphaType ? fPremulFormat
|
||||||
|
: skcms_AlphaFormat_Unpremul;
|
||||||
|
|
||||||
|
return skcms_Transform(src, get_skcms_format(srcFormat), srcAlpha, &fSrcProfile,
|
||||||
|
dst, get_skcms_format(dstFormat), dstAlpha, &fDstProfile, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cs_to_profile(const SkColorSpace* cs, skcms_ICCProfile* profile) {
|
||||||
|
if (cs->profileData()) {
|
||||||
|
bool result = skcms_Parse(cs->profileData()->data(), cs->profileData()->size(), profile);
|
||||||
|
// We shouldn't encounter color spaces that were constructed from invalid profiles!
|
||||||
|
SkASSERT(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkMatrix44 toXYZ;
|
||||||
|
SkColorSpaceTransferFn tf;
|
||||||
|
if (cs->toXYZD50(&toXYZ) && cs->isNumericalTransferFn(&tf)) {
|
||||||
|
memset(profile, 0, sizeof(*profile));
|
||||||
|
|
||||||
|
profile->has_trc = true;
|
||||||
|
profile->trc[0].parametric.g = tf.fG;
|
||||||
|
profile->trc[0].parametric.a = tf.fA;
|
||||||
|
profile->trc[0].parametric.b = tf.fB;
|
||||||
|
profile->trc[0].parametric.c = tf.fC;
|
||||||
|
profile->trc[0].parametric.d = tf.fD;
|
||||||
|
profile->trc[0].parametric.e = tf.fE;
|
||||||
|
profile->trc[0].parametric.f = tf.fF;
|
||||||
|
profile->trc[1].parametric = profile->trc[0].parametric;
|
||||||
|
profile->trc[2].parametric = profile->trc[0].parametric;
|
||||||
|
|
||||||
|
profile->has_toXYZD50 = true;
|
||||||
|
for (int r = 0; r < 3; ++r) {
|
||||||
|
for (int c = 0; c < 3; ++c) {
|
||||||
|
profile->toXYZD50.vals[r][c] = toXYZ.get(r, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It should be impossible to make a color space that gets here with our available factories.
|
||||||
|
// All ICC-based profiles have profileData. All remaining factories produce XYZ spaces with
|
||||||
|
// a single (numerical) transfer function.
|
||||||
|
SkDEBUGFAIL("How did we get here?");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<SkColorSpaceXform> MakeSkcmsXform(SkColorSpace* src, SkColorSpace* dst,
|
||||||
|
SkTransferFunctionBehavior premulBehavior) {
|
||||||
|
// Construct skcms_ICCProfiles from each color space. For now, support A2B and XYZ.
|
||||||
|
// Eventually, only need to support XYZ. Map premulBehavior to one of the two premul formats
|
||||||
|
// in skcms.
|
||||||
|
skcms_ICCProfile srcProfile, dstProfile;
|
||||||
|
|
||||||
|
if (!cs_to_profile(src, &srcProfile) || !cs_to_profile(dst, &dstProfile)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
skcms_AlphaFormat premulFormat = SkTransferFunctionBehavior::kRespect == premulBehavior
|
||||||
|
? skcms_AlphaFormat_PremulLinear : skcms_AlphaFormat_PremulAsEncoded;
|
||||||
|
return skstd::make_unique<SkColorSpaceXform_skcms>(srcProfile, dstProfile, premulFormat);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user