aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bench/ColorCanvasDrawBitmapBench.cpp2
-rw-r--r--bench/ColorSpaceXformBench.cpp4
-rw-r--r--bench/VertexColorSpaceBench.cpp4
-rw-r--r--bench/nanobench.cpp5
-rw-r--r--dm/DM.cpp13
-rw-r--r--gm/makecolorspace.cpp4
-rw-r--r--gm/p3.cpp6
-rw-r--r--gm/pictureshadercache.cpp9
-rw-r--r--gm/readpixels.cpp5
-rw-r--r--gm/tosrgb_colorfilter.cpp13
-rw-r--r--include/core/SkColorSpace.h65
-rw-r--r--src/codec/SkAndroidCodec.cpp8
-rw-r--r--src/codec/SkRawCodec.cpp17
-rw-r--r--src/core/SkColorSpace.cpp227
-rw-r--r--src/core/SkColorSpacePriv.h76
-rw-r--r--src/core/SkColorSpaceXformSteps.cpp4
-rw-r--r--src/core/SkICC.cpp30
-rw-r--r--src/gpu/GrColorSpaceXform.cpp1
-rw-r--r--tests/AndroidCodecTest.cpp20
-rw-r--r--tests/CanvasTest.cpp4
-rw-r--r--tests/CodecTest.cpp14
-rw-r--r--tests/ColorSpaceTest.cpp259
-rw-r--r--tests/DeferredDisplayListTest.cpp3
-rw-r--r--tests/ICCTest.cpp45
-rw-r--r--tests/ImageTest.cpp17
-rw-r--r--tests/NonlinearBlendingTest.cpp3
-rw-r--r--tests/SkColorSpaceXformStepsTest.cpp4
-rw-r--r--tests/TableColorFilterTest.cpp3
-rw-r--r--tests/ToSRGBColorFilter.cpp3
-rw-r--r--tools/flags/SkCommonFlagsConfig.cpp7
-rw-r--r--tools/viewer/Viewer.cpp8
-rw-r--r--tools/viewer/Viewer.h2
32 files changed, 585 insertions, 300 deletions
diff --git a/bench/ColorCanvasDrawBitmapBench.cpp b/bench/ColorCanvasDrawBitmapBench.cpp
index a7877f4792..c150e7974b 100644
--- a/bench/ColorCanvasDrawBitmapBench.cpp
+++ b/bench/ColorCanvasDrawBitmapBench.cpp
@@ -54,5 +54,5 @@ DEF_BENCH(return new ColorCanvasDrawBitmap(nullptr, SkColorSpace::MakeSRGB(), "n
DEF_BENCH(return new ColorCanvasDrawBitmap(SkColorSpace::MakeSRGB(), SkColorSpace::MakeSRGB(),
"sRGB_to_sRGB");)
DEF_BENCH(return new ColorCanvasDrawBitmap(
- SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kAdobeRGB),
+ SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kAdobeRGB_Gamut),
SkColorSpace::MakeSRGB(), "AdobeRGB_to_sRGB");)
diff --git a/bench/ColorSpaceXformBench.cpp b/bench/ColorSpaceXformBench.cpp
index b7b6b7d68d..fc95e8e5ea 100644
--- a/bench/ColorSpaceXformBench.cpp
+++ b/bench/ColorSpaceXformBench.cpp
@@ -34,8 +34,8 @@ struct ColorSpaceXformBench : public Benchmark {
void onDelayedSetup() override {
sk_sp<SkColorSpace> src = SkColorSpace::MakeSRGB(),
- dst = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
- SkNamedGamut::kDCIP3);
+ dst = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut);
fSteps = skstd::make_unique<SkColorSpaceXformSteps>(src.get(), kOpaque_SkAlphaType,
dst.get(), kPremul_SkAlphaType);
diff --git a/bench/VertexColorSpaceBench.cpp b/bench/VertexColorSpaceBench.cpp
index 164a2b4ade..129d0ff6f1 100644
--- a/bench/VertexColorSpaceBench.cpp
+++ b/bench/VertexColorSpaceBench.cpp
@@ -257,8 +257,8 @@ public:
GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
- auto p3 = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
- SkNamedGamut::kDCIP3);
+ auto p3 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut);
auto xform = GrColorSpaceXform::Make(sk_srgb_singleton(), kUnpremul_SkAlphaType,
p3.get(), kUnpremul_SkAlphaType);
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp
index 35fcefac01..21bed94212 100644
--- a/bench/nanobench.cpp
+++ b/bench/nanobench.cpp
@@ -478,7 +478,10 @@ static void create_config(const SkCommandLineConfig* config, SkTArray<Config>* c
CPU_CONFIG(565, kRaster_Backend, kRGB_565_SkColorType, kOpaque_SkAlphaType, nullptr)
// 'narrow' has a gamut narrower than sRGB, and different transfer function.
- auto narrow = SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, gNarrow_toXYZD50),
+ SkMatrix44 narrow_gamut;
+ narrow_gamut.set3x3RowMajorf(gNarrow_toXYZD50);
+
+ auto narrow = SkColorSpace::MakeRGB(k2Dot2Curve_SkGammaNamed, narrow_gamut),
srgb = SkColorSpace::MakeSRGB(),
srgbLinear = SkColorSpace::MakeSRGBLinear();
diff --git a/dm/DM.cpp b/dm/DM.cpp
index 6f63b369b6..1694676670 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -833,7 +833,7 @@ static bool gather_srcs() {
static sk_sp<SkColorSpace> rec2020() {
return SkColorSpace::MakeRGB({2.22222f, 0.909672f, 0.0903276f, 0.222222f, 0.0812429f, 0, 0},
- SkNamedGamut::kRec2020);
+ SkColorSpace::kRec2020_Gamut);
}
static void push_sink(const SkCommandLineConfig& config, Sink* s) {
@@ -925,10 +925,14 @@ static Sink* create_sink(const GrContextOptions& grCtxOptions, const SkCommandLi
// Configs relevant to color management testing (and 8888 for reference).
// 'narrow' has a gamut narrower than sRGB, and different transfer function.
- auto narrow = SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, gNarrow_toXYZD50),
+ SkMatrix44 narrow_gamut;
+ narrow_gamut.set3x3RowMajorf(gNarrow_toXYZD50);
+
+ auto narrow = SkColorSpace::MakeRGB(k2Dot2Curve_SkGammaNamed, narrow_gamut),
srgb = SkColorSpace::MakeSRGB(),
srgbLinear = SkColorSpace::MakeSRGBLinear(),
- p3 = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
+ p3 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut);
SINK( "f16", RasterSink, kRGBA_F16_SkColorType, srgbLinear);
SINK( "srgb", RasterSink, kRGBA_8888_SkColorType, srgb );
@@ -954,7 +958,8 @@ static Sink* create_via(const SkString& tag, Sink* wrapped) {
#define VIA(t, via, ...) if (tag.equals(t)) return new via(__VA_ARGS__)
VIA("gbr", ViaCSXform, wrapped, rgb_to_gbr(), true);
VIA("p3", ViaCSXform, wrapped,
- SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3), false);
+ SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut), false);
VIA("lite", ViaLite, wrapped);
#ifdef TEST_VIA_SVG
VIA("svg", ViaSVG, wrapped);
diff --git a/gm/makecolorspace.cpp b/gm/makecolorspace.cpp
index 2f5acd699e..c7e603d9ac 100644
--- a/gm/makecolorspace.cpp
+++ b/gm/makecolorspace.cpp
@@ -48,8 +48,8 @@ protected:
}
void onDraw(SkCanvas* canvas) override {
- sk_sp<SkColorSpace> wideGamut = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
- SkNamedGamut::kAdobeRGB);
+ sk_sp<SkColorSpace> wideGamut = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kAdobeRGB_Gamut);
sk_sp<SkColorSpace> wideGamutLinear = wideGamut->makeLinearGamma();
// Lazy images
diff --git a/gm/p3.cpp b/gm/p3.cpp
index a67ab7229b..28e86447a4 100644
--- a/gm/p3.cpp
+++ b/gm/p3.cpp
@@ -94,7 +94,8 @@ static void compare_pixel(const char* label,
}
DEF_SIMPLE_GM(p3, canvas, 450, 1300) {
- auto p3 = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
+ auto p3 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut);
auto srgb = SkColorSpace::MakeSRGB();
auto p3_to_srgb = [&](SkColor4f c) {
@@ -355,7 +356,8 @@ DEF_SIMPLE_GM(p3, canvas, 450, 1300) {
}
DEF_SIMPLE_GM(p3_ovals, canvas, 450, 320) {
- auto p3 = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
+ auto p3 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut);
// Test cases that exercise each Op in GrOvalOpFactory.cpp
diff --git a/gm/pictureshadercache.cpp b/gm/pictureshadercache.cpp
index e3badd801d..b3e2c26ab4 100644
--- a/gm/pictureshadercache.cpp
+++ b/gm/pictureshadercache.cpp
@@ -60,12 +60,9 @@ public:
{
// Render in a funny color space that converts green to yellow.
- skcms_Matrix3x3 greenToYellow = {{
- { 1, 1, 0 },
- { 0, 1, 0 },
- { 0, 0, 1 },
- }};
- sk_sp<SkColorSpace> gty = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
+ SkMatrix44 greenToYellow;
+ greenToYellow.setFloat(0, 1, 1.0f);
+ sk_sp<SkColorSpace> gty = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
greenToYellow);
SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100, std::move(gty));
sk_sp<SkSurface> surface(SkSurface::MakeRaster(info));
diff --git a/gm/readpixels.cpp b/gm/readpixels.cpp
index e69803bcf0..8250860901 100644
--- a/gm/readpixels.cpp
+++ b/gm/readpixels.cpp
@@ -62,9 +62,10 @@ static sk_sp<SkImage> make_picture_image() {
}
static sk_sp<SkColorSpace> make_parametric_transfer_fn(const SkColorSpacePrimaries& primaries) {
- skcms_Matrix3x3 toXYZD50;
+ SkMatrix44 toXYZD50;
SkAssertResult(primaries.toXYZD50(&toXYZD50));
- skcms_TransferFunction fn = { 1.8f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f };
+ SkColorSpaceTransferFn fn;
+ fn.fA = 1.f; fn.fB = 0.f; fn.fC = 0.f; fn.fD = 0.f; fn.fE = 0.f; fn.fF = 0.f; fn.fG = 1.8f;
return SkColorSpace::MakeRGB(fn, toXYZD50);
}
diff --git a/gm/tosrgb_colorfilter.cpp b/gm/tosrgb_colorfilter.cpp
index 8637386922..d9c7890aae 100644
--- a/gm/tosrgb_colorfilter.cpp
+++ b/gm/tosrgb_colorfilter.cpp
@@ -26,17 +26,20 @@ DEF_SIMPLE_GM_BG(tosrgb_colorfilter, canvas, 130, 130, SK_ColorBLACK) {
canvas->drawBitmapRect(bmp, SkRect::MakeXYWH(10, 10, 50, 50), nullptr);
auto srgb = SkColorSpace::MakeSRGB();
- auto rec2020 = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kRec2020);
+ auto rec2020 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kRec2020_Gamut);
// NarrowGamut RGB (an artifically smaller than sRGB gamut)
- skcms_Matrix3x3 narrowGamutRGBMatrix;
- SkAssertResult(skcms_PrimariesToXYZD50(
+ SkColorSpacePrimaries narrowPrimaries = {
0.54f, 0.33f, // Rx, Ry
0.33f, 0.50f, // Gx, Gy
0.25f, 0.20f, // Bx, By
0.3127f, 0.3290f, // Wx, Wy
- &narrowGamutRGBMatrix));
- auto narrow = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, narrowGamutRGBMatrix);
+ };
+ SkMatrix44 narrowGamutRGBMatrix;
+ narrowPrimaries.toXYZD50(&narrowGamutRGBMatrix);
+ auto narrow = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ narrowGamutRGBMatrix);
SkPaint paint;
diff --git a/include/core/SkColorSpace.h b/include/core/SkColorSpace.h
index 6013c2a308..26771f3ce1 100644
--- a/include/core/SkColorSpace.h
+++ b/include/core/SkColorSpace.h
@@ -8,14 +8,13 @@
#ifndef SkColorSpace_DEFINED
#define SkColorSpace_DEFINED
-#include "../private/SkFixed.h"
#include "../private/SkOnce.h"
-#include "../../third_party/skcms/skcms.h"
#include "SkMatrix44.h"
#include "SkRefCnt.h"
#include <memory>
class SkData;
+struct skcms_ICCProfile;
enum SkGammaNamed {
kLinear_SkGammaNamed,
@@ -42,8 +41,6 @@ struct SK_API SkColorSpacePrimaries {
* representation of SkColorSpace.
*/
bool toXYZD50(SkMatrix44* toXYZD50) const;
-
- bool toXYZD50(skcms_Matrix3x3* toXYZD50) const;
};
/**
@@ -65,56 +62,6 @@ struct SK_API SkColorSpaceTransferFn {
float fF;
};
-namespace SkNamedTransferFn {
-
-// Like SkNamedGamut::kSRGB, keeping this bitwise exactly the same as skcms makes things fastest.
-static constexpr skcms_TransferFunction kSRGB =
- { 2.4f, (float)(1/1.055), (float)(0.055/1.055), (float)(1/12.92), 0.04045f, 0.0f, 0.0f };
-
-static constexpr skcms_TransferFunction k2Dot2 =
- { 2.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
-
-static constexpr skcms_TransferFunction kLinear =
- { 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
-
-}
-
-namespace SkNamedGamut {
-
-static constexpr skcms_Matrix3x3 kSRGB = {{
- // ICC fixed-point (16.16) representation, taken from skcms. Please keep them exactly in sync.
- // 0.436065674f, 0.385147095f, 0.143066406f,
- // 0.222488403f, 0.716873169f, 0.060607910f,
- // 0.013916016f, 0.097076416f, 0.714096069f,
- { SkFixedToFloat(0x6FA2), SkFixedToFloat(0x6299), SkFixedToFloat(0x24A0) },
- { SkFixedToFloat(0x38F5), SkFixedToFloat(0xB785), SkFixedToFloat(0x0F84) },
- { SkFixedToFloat(0x0390), SkFixedToFloat(0x18DA), SkFixedToFloat(0xB6CF) },
-}};
-
-static constexpr skcms_Matrix3x3 kAdobeRGB = {{
- // ICC fixed-point (16.16) repesentation of:
- // 0.60974, 0.20528, 0.14919,
- // 0.31111, 0.62567, 0.06322,
- // 0.01947, 0.06087, 0.74457,
- { SkFixedToFloat(0x9c18), SkFixedToFloat(0x348d), SkFixedToFloat(0x2631) },
- { SkFixedToFloat(0x4fa5), SkFixedToFloat(0xa02c), SkFixedToFloat(0x102f) },
- { SkFixedToFloat(0x04fc), SkFixedToFloat(0x0f95), SkFixedToFloat(0xbe9c) },
-}};
-
-static constexpr skcms_Matrix3x3 kDCIP3 = {{
- { 0.515102f, 0.291965f, 0.157153f },
- { 0.241182f, 0.692236f, 0.0665819f },
- { -0.00104941f, 0.0418818f, 0.784378f },
-}};
-
-static constexpr skcms_Matrix3x3 kRec2020 = {{
- { 0.673459f, 0.165661f, 0.125100f, },
- { 0.279033f, 0.675338f, 0.0456288f },
- { -0.00193139f, 0.0299794f, 0.797162f },
-}};
-
-}
-
class SK_API SkColorSpace : public SkNVRefCnt<SkColorSpace> {
public:
/**
@@ -160,12 +107,6 @@ public:
static sk_sp<SkColorSpace> MakeRGB(SkGammaNamed gammaNamed, const SkMatrix44& toXYZD50);
/**
- * Create an SkColorSpace from a transfer function and a row-major 3x3 transformation to XYZ.
- */
- static sk_sp<SkColorSpace> MakeRGB(const skcms_TransferFunction& transferFn,
- const skcms_Matrix3x3& toXYZ);
-
- /**
* Create an SkColorSpace from a parsed (skcms) ICC profile.
*/
static sk_sp<SkColorSpace> Make(const skcms_ICCProfile&);
@@ -195,16 +136,12 @@ public:
*/
bool isNumericalTransferFn(SkColorSpaceTransferFn* fn) const;
- bool isNumericalTransferFn(skcms_TransferFunction* fn) const;
-
/**
* Returns true and sets |toXYZD50| if the color gamut can be described as a matrix.
* Returns false otherwise.
*/
bool toXYZD50(SkMatrix44* toXYZD50) const;
- bool toXYZD50(skcms_Matrix3x3* toXYZD50) const;
-
/**
* Returns a hash of the gamut transformation to XYZ D50. Allows for fast equality checking
* of gamuts, at the (very small) risk of collision.
diff --git a/src/codec/SkAndroidCodec.cpp b/src/codec/SkAndroidCodec.cpp
index d741d6d29b..581640f411 100644
--- a/src/codec/SkAndroidCodec.cpp
+++ b/src/codec/SkAndroidCodec.cpp
@@ -164,8 +164,9 @@ sk_sp<SkColorSpace> SkAndroidCodec::computeOutputColorSpace(SkColorType outputCo
switch (outputColorType) {
case kRGBA_8888_SkColorType:
case kBGRA_8888_SkColorType: {
- // If |prefColorSpace| is supplied, choose it.
- if (prefColorSpace) {
+ // If |prefColorSpace| is supported, choose it.
+ SkColorSpaceTransferFn fn;
+ if (prefColorSpace && prefColorSpace->isNumericalTransferFn(&fn)) {
return prefColorSpace;
}
@@ -178,7 +179,8 @@ sk_sp<SkColorSpace> SkAndroidCodec::computeOutputColorSpace(SkColorType outputCo
}
if (is_wide_gamut(*encodedProfile)) {
- return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
+ return SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut);
}
}
diff --git a/src/codec/SkRawCodec.cpp b/src/codec/SkRawCodec.cpp
index a8ec40bff4..fb7efb9b7b 100644
--- a/src/codec/SkRawCodec.cpp
+++ b/src/codec/SkRawCodec.cpp
@@ -612,6 +612,17 @@ private:
bool fIsXtransImage;
};
+static constexpr skcms_Matrix3x3 gAdobe_RGB_to_XYZD50 = {{
+ // ICC fixed-point (16.16) repesentation of:
+ // 0.60974, 0.20528, 0.14919,
+ // 0.31111, 0.62567, 0.06322,
+ // 0.01947, 0.06087, 0.74457,
+ { SkFixedToFloat(0x9c18), SkFixedToFloat(0x348d), SkFixedToFloat(0x2631) }, // Rx, Gx, Bx
+ { SkFixedToFloat(0x4fa5), SkFixedToFloat(0xa02c), SkFixedToFloat(0x102f) }, // Ry, Gy, By
+ { SkFixedToFloat(0x04fc), SkFixedToFloat(0x0f95), SkFixedToFloat(0xbe9c) }, // Rz, Gz, Bz
+}};
+
+
/*
* Tries to handle the image with PIEX. If PIEX returns kOk and finds the preview image, create a
* SkJpegCodec. If PIEX returns kFail, then the file is invalid, return nullptr. In other cases,
@@ -638,10 +649,12 @@ std::unique_ptr<SkCodec> SkRawCodec::MakeFromStream(std::unique_ptr<SkStream> st
std::unique_ptr<SkEncodedInfo::ICCProfile> profile;
if (imageData.color_space == ::piex::PreviewImageData::kAdobeRgb) {
+ constexpr skcms_TransferFunction twoDotTwo =
+ { 2.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
skcms_ICCProfile skcmsProfile;
skcms_Init(&skcmsProfile);
- skcms_SetTransferFunction(&skcmsProfile, &SkNamedTransferFn::k2Dot2);
- skcms_SetXYZD50(&skcmsProfile, &SkNamedGamut::kAdobeRGB);
+ skcms_SetTransferFunction(&skcmsProfile, &twoDotTwo);
+ skcms_SetXYZD50(&skcmsProfile, &gAdobe_RGB_to_XYZD50);
profile = SkEncodedInfo::ICCProfile::Make(skcmsProfile);
}
diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp
index 1471095f31..66ddaf4104 100644
--- a/src/core/SkColorSpace.cpp
+++ b/src/core/SkColorSpace.cpp
@@ -20,10 +20,6 @@ bool SkColorSpacePrimaries::toXYZD50(SkMatrix44* toXYZ_D50) const {
return true;
}
-bool SkColorSpacePrimaries::toXYZD50(skcms_Matrix3x3* toXYZ_D50) const {
- return skcms_PrimariesToXYZD50(fRX, fRY, fGX, fGY, fBX, fBY, fWX, fWY, toXYZ_D50);
-}
-
static bool is_3x3(const SkMatrix44& m44) {
return m44.getFloat(0, 3) == 0.0f
&& m44.getFloat(1, 3) == 0.0f
@@ -61,9 +57,9 @@ SkColorSpace::SkColorSpace(SkGammaNamed gammaNamed,
fToXYZD50Hash = SkOpts::hash_fn(fToXYZD50_3x3, 9*sizeof(float), 0);
switch (fGammaNamed) {
- case kSRGB_SkGammaNamed: transferFn = & SkNamedTransferFn::kSRGB.g; break;
- case k2Dot2Curve_SkGammaNamed: transferFn = & SkNamedTransferFn::k2Dot2.g; break;
- case kLinear_SkGammaNamed: transferFn = &SkNamedTransferFn::kLinear.g; break;
+ case kSRGB_SkGammaNamed: transferFn = & gSRGB_TransferFn.fG; break;
+ case k2Dot2Curve_SkGammaNamed: transferFn = & g2Dot2_TransferFn.fG; break;
+ case kLinear_SkGammaNamed: transferFn = &gLinear_TransferFn.fG; break;
case kNonStandard_SkGammaNamed: break;
}
memcpy(fTransferFn, transferFn, 7*sizeof(float));
@@ -77,12 +73,12 @@ sk_sp<SkColorSpace> SkColorSpace::MakeRGB(SkGammaNamed gammaNamed, const SkMatri
}
switch (gammaNamed) {
case kSRGB_SkGammaNamed:
- if (xyz_almost_equal(toXYZD50, &SkNamedGamut::kSRGB.vals[0][0])) {
+ if (xyz_almost_equal(toXYZD50, gSRGB_toXYZD50)) {
return SkColorSpace::MakeSRGB();
}
break;
case kLinear_SkGammaNamed:
- if (xyz_almost_equal(toXYZD50, &SkNamedGamut::kSRGB.vals[0][0])) {
+ if (xyz_almost_equal(toXYZD50, gSRGB_toXYZD50)) {
return SkColorSpace::MakeSRGBLinear();
}
break;
@@ -140,16 +136,6 @@ sk_sp<SkColorSpace> SkColorSpace::MakeRGB(const SkColorSpaceTransferFn& coeffs,
return SkColorSpace::MakeRGB(coeffs, toXYZD50);
}
-sk_sp<SkColorSpace> SkColorSpace::MakeRGB(const skcms_TransferFunction& transferFn,
- const skcms_Matrix3x3& toXYZ) {
- SkMatrix44 toXYZD50;
- toXYZD50.set3x3RowMajorf(&toXYZ.vals[0][0]);
- SkColorSpaceTransferFn tf;
- memcpy(&tf, &transferFn, sizeof(tf));
- // Going through this old path makes sure we classify transferFn as an SkGammaNamed
- return SkColorSpace::MakeRGB(tf, toXYZD50);
-}
-
class SkColorSpaceSingletonFactory {
public:
static SkColorSpace* Make(SkGammaNamed gamma, const float to_xyz[9]) {
@@ -162,12 +148,12 @@ public:
SkColorSpace* sk_srgb_singleton() {
static SkColorSpace* cs = SkColorSpaceSingletonFactory::Make(kSRGB_SkGammaNamed,
- &SkNamedGamut::kSRGB.vals[0][0]);
+ gSRGB_toXYZD50);
return cs;
}
SkColorSpace* sk_srgb_linear_singleton() {
static SkColorSpace* cs = SkColorSpaceSingletonFactory::Make(kLinear_SkGammaNamed,
- &SkNamedGamut::kSRGB.vals[0][0]);
+ gSRGB_toXYZD50);
return cs;
}
@@ -210,11 +196,6 @@ bool SkColorSpace::isNumericalTransferFn(SkColorSpaceTransferFn* coeffs) const {
return true;
}
-bool SkColorSpace::isNumericalTransferFn(skcms_TransferFunction* coeffs) const {
- this->transferFn(&coeffs->g);
- return true;
-}
-
void SkColorSpace::transferFn(float gabcdef[7]) const {
memcpy(gabcdef, &fTransferFn, 7*sizeof(float));
}
@@ -229,10 +210,6 @@ bool SkColorSpace::toXYZD50(SkMatrix44* toXYZD50) const {
return true;
}
-bool SkColorSpace::toXYZD50(skcms_Matrix3x3* toXYZD50) const {
- memcpy(toXYZD50, fToXYZD50_3x3, 9*sizeof(float));
- return true;
-}
void SkColorSpace::gamutTransformTo(const SkColorSpace* dst, float src_to_dst[9]) const {
dst->computeLazyDstFields();
@@ -336,53 +313,201 @@ sk_sp<SkColorSpace> SkColorSpace::Make(const skcms_ICCProfile& profile) {
///////////////////////////////////////////////////////////////////////////////////////////////////
enum Version {
- k0_Version, // Initial version, now deprecated
- k1_Version, // Simple header (version tag) + 16 floats
+ k0_Version, // Initial version, header + flags for matrix and profile
+};
- kCurrent_Version = k1_Version,
+enum NamedColorSpace {
+ kSRGB_NamedColorSpace,
+ // No longer a singleton, preserved to support reading data from branches m65 and older
+ kAdobeRGB_NamedColorSpace,
+ kSRGBLinear_NamedColorSpace,
};
struct ColorSpaceHeader {
- uint8_t fVersion = kCurrent_Version;
+ /**
+ * It is only valid to set zero or one flags.
+ * Setting multiple flags is invalid.
+ */
+
+ /**
+ * If kMatrix_Flag is set, we will write 12 floats after the header.
+ */
+ static constexpr uint8_t kMatrix_Flag = 1 << 0;
+
+ /**
+ * If kICC_Flag is set, we will write an ICC profile after the header.
+ * The ICC profile will be written as a uint32 size, followed immediately
+ * by the data (padded to 4 bytes).
+ * DEPRECATED / UNUSED
+ */
+ static constexpr uint8_t kICC_Flag = 1 << 1;
+
+ /**
+ * If kTransferFn_Flag is set, we will write 19 floats after the header.
+ * The first seven represent the transfer fn, and the next twelve are the
+ * matrix.
+ */
+ static constexpr uint8_t kTransferFn_Flag = 1 << 3;
+
+ static ColorSpaceHeader Pack(Version version, uint8_t named, uint8_t gammaNamed, uint8_t flags)
+ {
+ ColorSpaceHeader header;
+
+ SkASSERT(k0_Version == version);
+ header.fVersion = (uint8_t) version;
+
+ SkASSERT(named <= kSRGBLinear_NamedColorSpace);
+ header.fNamed = (uint8_t) named;
+
+ SkASSERT(gammaNamed <= kNonStandard_SkGammaNamed);
+ header.fGammaNamed = (uint8_t) gammaNamed;
+
+ SkASSERT(flags <= kTransferFn_Flag);
+ header.fFlags = flags;
+ return header;
+ }
+
+ uint8_t fVersion; // Always zero
+ uint8_t fNamed; // Must be a SkColorSpace::Named
+ uint8_t fGammaNamed; // Must be a SkGammaNamed
+ uint8_t fFlags;
};
size_t SkColorSpace::writeToMemory(void* memory) const {
- if (memory) {
- *((ColorSpaceHeader*)memory) = ColorSpaceHeader();
- memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
+ // If we have a named profile, only write the enum.
+ const SkGammaNamed gammaNamed = this->gammaNamed();
+ if (this == sk_srgb_singleton()) {
+ if (memory) {
+ *((ColorSpaceHeader*) memory) = ColorSpaceHeader::Pack(
+ k0_Version, kSRGB_NamedColorSpace, gammaNamed, 0);
+ }
+ return sizeof(ColorSpaceHeader);
+ } else if (this == sk_srgb_linear_singleton()) {
+ if (memory) {
+ *((ColorSpaceHeader*) memory) = ColorSpaceHeader::Pack(
+ k0_Version, kSRGBLinear_NamedColorSpace, gammaNamed, 0);
+ }
+ return sizeof(ColorSpaceHeader);
+ }
- memcpy(memory, fTransferFn, 7 * sizeof(float));
- memory = SkTAddOffset<void>(memory, 7 * sizeof(float));
+ // If we have a named gamma, write the enum and the matrix.
+ switch (gammaNamed) {
+ case kSRGB_SkGammaNamed:
+ case k2Dot2Curve_SkGammaNamed:
+ case kLinear_SkGammaNamed: {
+ if (memory) {
+ *((ColorSpaceHeader*) memory) =
+ ColorSpaceHeader::Pack(k0_Version, 0, gammaNamed,
+ ColorSpaceHeader::kMatrix_Flag);
+ memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
+ SkMatrix44 m44;
+ this->toXYZD50(&m44);
+ m44.as3x4RowMajorf((float*) memory);
+ }
+ return sizeof(ColorSpaceHeader) + 12 * sizeof(float);
+ }
+ default: {
+ SkColorSpaceTransferFn transferFn;
+ SkAssertResult(this->isNumericalTransferFn(&transferFn));
+
+ if (memory) {
+ *((ColorSpaceHeader*) memory) =
+ ColorSpaceHeader::Pack(k0_Version, 0, gammaNamed,
+ ColorSpaceHeader::kTransferFn_Flag);
+ memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
+
+ *(((float*) memory) + 0) = transferFn.fA;
+ *(((float*) memory) + 1) = transferFn.fB;
+ *(((float*) memory) + 2) = transferFn.fC;
+ *(((float*) memory) + 3) = transferFn.fD;
+ *(((float*) memory) + 4) = transferFn.fE;
+ *(((float*) memory) + 5) = transferFn.fF;
+ *(((float*) memory) + 6) = transferFn.fG;
+ memory = SkTAddOffset<void>(memory, 7 * sizeof(float));
+
+ SkMatrix44 m44;
+ this->toXYZD50(&m44);
+ m44.as3x4RowMajorf((float*) memory);
+ }
- memcpy(memory, fToXYZD50_3x3, 9 * sizeof(float));
+ return sizeof(ColorSpaceHeader) + 19 * sizeof(float);
+ }
}
- return sizeof(ColorSpaceHeader) + 16 * sizeof(float);
}
sk_sp<SkData> SkColorSpace::serialize() const {
- sk_sp<SkData> data = SkData::MakeUninitialized(this->writeToMemory(nullptr));
+ size_t size = this->writeToMemory(nullptr);
+ if (0 == size) {
+ return nullptr;
+ }
+
+ sk_sp<SkData> data = SkData::MakeUninitialized(size);
this->writeToMemory(data->writable_data());
return data;
}
sk_sp<SkColorSpace> SkColorSpace::Deserialize(const void* data, size_t length) {
- if (length < sizeof(ColorSpaceHeader) + 16 * sizeof(float)) {
+ if (length < sizeof(ColorSpaceHeader)) {
return nullptr;
}
ColorSpaceHeader header = *((const ColorSpaceHeader*) data);
data = SkTAddOffset<const void>(data, sizeof(ColorSpaceHeader));
- if (header.fVersion != kCurrent_Version) {
- return nullptr;
+ length -= sizeof(ColorSpaceHeader);
+ if (0 == header.fFlags) {
+ switch ((NamedColorSpace)header.fNamed) {
+ case kSRGB_NamedColorSpace:
+ return SkColorSpace::MakeSRGB();
+ case kSRGBLinear_NamedColorSpace:
+ return SkColorSpace::MakeSRGBLinear();
+ case kAdobeRGB_NamedColorSpace:
+ return SkColorSpace::MakeRGB(g2Dot2_TransferFn, SkColorSpace::kAdobeRGB_Gamut);
+ }
}
- skcms_TransferFunction transferFn;
- memcpy(&transferFn, data, 7 * sizeof(float));
- data = SkTAddOffset<const void>(data, 7 * sizeof(float));
+ switch ((SkGammaNamed) header.fGammaNamed) {
+ case kSRGB_SkGammaNamed:
+ case k2Dot2Curve_SkGammaNamed:
+ case kLinear_SkGammaNamed: {
+ if (ColorSpaceHeader::kMatrix_Flag != header.fFlags || length < 12 * sizeof(float)) {
+ return nullptr;
+ }
- skcms_Matrix3x3 toXYZ;
- memcpy(&toXYZ, data, 9*sizeof(float));
- return SkColorSpace::MakeRGB(transferFn, toXYZ);
+ SkMatrix44 toXYZ;
+ toXYZ.set3x4RowMajorf((const float*) data);
+ return SkColorSpace::MakeRGB((SkGammaNamed) header.fGammaNamed, toXYZ);
+ }
+ default:
+ break;
+ }
+
+ switch (header.fFlags) {
+ case ColorSpaceHeader::kICC_Flag: {
+ // Deprecated and unsupported code path
+ return nullptr;
+ }
+ case ColorSpaceHeader::kTransferFn_Flag: {
+ if (length < 19 * sizeof(float)) {
+ return nullptr;
+ }
+
+ SkColorSpaceTransferFn transferFn;
+ transferFn.fA = *(((const float*) data) + 0);
+ transferFn.fB = *(((const float*) data) + 1);
+ transferFn.fC = *(((const float*) data) + 2);
+ transferFn.fD = *(((const float*) data) + 3);
+ transferFn.fE = *(((const float*) data) + 4);
+ transferFn.fF = *(((const float*) data) + 5);
+ transferFn.fG = *(((const float*) data) + 6);
+ data = SkTAddOffset<const void>(data, 7 * sizeof(float));
+
+ SkMatrix44 toXYZ;
+ toXYZ.set3x4RowMajorf((const float*) data);
+ return SkColorSpace::MakeRGB(transferFn, toXYZ);
+ }
+ default:
+ return nullptr;
+ }
}
bool SkColorSpace::Equals(const SkColorSpace* x, const SkColorSpace* y) {
diff --git a/src/core/SkColorSpacePriv.h b/src/core/SkColorSpacePriv.h
index 298b932aed..4d93d59432 100644
--- a/src/core/SkColorSpacePriv.h
+++ b/src/core/SkColorSpacePriv.h
@@ -14,26 +14,70 @@
#define SkColorSpacePrintf(...)
+static constexpr float gSRGB_toXYZD50[] {
+ // These are taken from skcms, and there originally from 16-bit fixed point.
+ // For best results, please keep them exactly in sync with skcms.
+ 0.436065674f, 0.385147095f, 0.143066406f,
+ 0.222488403f, 0.716873169f, 0.060607910f,
+ 0.013916016f, 0.097076416f, 0.714096069f,
+};
+
+static constexpr float gAdobeRGB_toXYZD50[] {
+ // ICC fixed-point (16.16) repesentation of:
+ // 0.60974, 0.20528, 0.14919,
+ // 0.31111, 0.62567, 0.06322,
+ // 0.01947, 0.06087, 0.74457,
+ SkFixedToFloat(0x9c18), SkFixedToFloat(0x348d), SkFixedToFloat(0x2631), // Rx, Gx, Bx
+ SkFixedToFloat(0x4fa5), SkFixedToFloat(0xa02c), SkFixedToFloat(0x102f), // Ry, Gy, By
+ SkFixedToFloat(0x04fc), SkFixedToFloat(0x0f95), SkFixedToFloat(0xbe9c), // Rz, Gz, Bz
+};
+
+static constexpr float gDCIP3_toXYZD50[] {
+ 0.515102f, 0.291965f, 0.157153f, // Rx, Gx, Bx
+ 0.241182f, 0.692236f, 0.0665819f, // Ry, Gy, By
+ -0.00104941f, 0.0418818f, 0.784378f, // Rz, Gz, Bz
+};
+
+static constexpr float gRec2020_toXYZD50[] {
+ 0.673459f, 0.165661f, 0.125100f, // Rx, Gx, Bx
+ 0.279033f, 0.675338f, 0.0456288f, // Ry, Gy, By
+ -0.00193139f, 0.0299794f, 0.797162f, // Rz, Gz, Bz
+};
+
// A gamut narrower than sRGB, useful for testing.
-static constexpr skcms_Matrix3x3 gNarrow_toXYZD50 = {{
- { 0.190974f, 0.404865f, 0.368380f },
- { 0.114746f, 0.582937f, 0.302318f },
- { 0.032925f, 0.153615f, 0.638669f },
-}};
+static constexpr float gNarrow_toXYZD50[] {
+ 0.190974f, 0.404865f, 0.368380f,
+ 0.114746f, 0.582937f, 0.302318f,
+ 0.032925f, 0.153615f, 0.638669f,
+};
+
+// Like gSRGB_toXYZD50, keeping this bitwise exactly the same as skcms makes things fastest.
+static constexpr SkColorSpaceTransferFn gSRGB_TransferFn =
+#ifdef SK_LEGACY_SRGB_TRANSFER_FUNCTION
+ { 2.4f, 1.0f / 1.055f, 0.055f / 1.055f, 1.0f / 12.92f, 0.04045f, 0.0f, 0.0f };
+#else
+ { 2.4f, (float)(1/1.055), (float)(0.055/1.055), (float)(1/12.92), 0.04045f, 0.0f, 0.0f };
+#endif
+
+static constexpr SkColorSpaceTransferFn g2Dot2_TransferFn =
+ { 2.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+
+static constexpr SkColorSpaceTransferFn gLinear_TransferFn =
+ { 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
static inline void to_xyz_d50(SkMatrix44* toXYZD50, SkColorSpace::Gamut gamut) {
switch (gamut) {
case SkColorSpace::kSRGB_Gamut:
- toXYZD50->set3x3RowMajorf(&SkNamedGamut::kSRGB.vals[0][0]);
+ toXYZD50->set3x3RowMajorf(gSRGB_toXYZD50);
break;
case SkColorSpace::kAdobeRGB_Gamut:
- toXYZD50->set3x3RowMajorf(&SkNamedGamut::kAdobeRGB.vals[0][0]);
+ toXYZD50->set3x3RowMajorf(gAdobeRGB_toXYZD50);
break;
case SkColorSpace::kDCIP3_D65_Gamut:
- toXYZD50->set3x3RowMajorf(&SkNamedGamut::kDCIP3.vals[0][0]);
+ toXYZD50->set3x3RowMajorf(gDCIP3_toXYZD50);
break;
case SkColorSpace::kRec2020_Gamut:
- toXYZD50->set3x3RowMajorf(&SkNamedGamut::kRec2020.vals[0][0]);
+ toXYZD50->set3x3RowMajorf(gRec2020_toXYZD50);
break;
}
}
@@ -105,13 +149,13 @@ static inline bool is_valid_transfer_fn(const SkColorSpaceTransferFn& coeffs) {
}
static inline bool is_almost_srgb(const SkColorSpaceTransferFn& coeffs) {
- return transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.a, coeffs.fA) &&
- transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.b, coeffs.fB) &&
- transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.c, coeffs.fC) &&
- transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.d, coeffs.fD) &&
- transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.e, coeffs.fE) &&
- transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.f, coeffs.fF) &&
- transfer_fn_almost_equal(SkNamedTransferFn::kSRGB.g, coeffs.fG);
+ return transfer_fn_almost_equal(gSRGB_TransferFn.fA, coeffs.fA) &&
+ transfer_fn_almost_equal(gSRGB_TransferFn.fB, coeffs.fB) &&
+ transfer_fn_almost_equal(gSRGB_TransferFn.fC, coeffs.fC) &&
+ transfer_fn_almost_equal(gSRGB_TransferFn.fD, coeffs.fD) &&
+ transfer_fn_almost_equal(gSRGB_TransferFn.fE, coeffs.fE) &&
+ transfer_fn_almost_equal(gSRGB_TransferFn.fF, coeffs.fF) &&
+ transfer_fn_almost_equal(gSRGB_TransferFn.fG, coeffs.fG);
}
static inline bool is_almost_2dot2(const SkColorSpaceTransferFn& coeffs) {
diff --git a/src/core/SkColorSpaceXformSteps.cpp b/src/core/SkColorSpaceXformSteps.cpp
index 5fff91025c..a2f73fc860 100644
--- a/src/core/SkColorSpaceXformSteps.cpp
+++ b/src/core/SkColorSpaceXformSteps.cpp
@@ -53,10 +53,10 @@ SkColorSpaceXformSteps::SkColorSpaceXformSteps(SkColorSpace* src, SkAlphaType sr
this->src_to_dst_matrix[8] = row_major[8];
} else {
#ifdef SK_DEBUG
- skcms_Matrix3x3 srcM, dstM;
+ SkMatrix44 srcM, dstM;
src->toXYZD50(&srcM);
dst->toXYZD50(&dstM);
- SkASSERT(0 == memcmp(&srcM, &dstM, 9*sizeof(float)) && "Hash collision");
+ SkASSERT(0 == memcmp(&srcM, &dstM, 16*sizeof(SkMScalar)) && "Hash collision");
#endif
}
diff --git a/src/core/SkICC.cpp b/src/core/SkICC.cpp
index d1db49e514..a9df5b0f93 100644
--- a/src/core/SkICC.cpp
+++ b/src/core/SkICC.cpp
@@ -206,14 +206,14 @@ static bool nearly_equal(float x, float y) {
}
static bool nearly_equal(const SkColorSpaceTransferFn& u,
- const skcms_TransferFunction& v) {
- return nearly_equal(u.fG, v.g)
- && nearly_equal(u.fA, v.a)
- && nearly_equal(u.fB, v.b)
- && nearly_equal(u.fC, v.c)
- && nearly_equal(u.fD, v.d)
- && nearly_equal(u.fE, v.e)
- && nearly_equal(u.fF, v.f);
+ const SkColorSpaceTransferFn& v) {
+ return nearly_equal(u.fG, v.fG)
+ && nearly_equal(u.fA, v.fA)
+ && nearly_equal(u.fB, v.fB)
+ && nearly_equal(u.fC, v.fC)
+ && nearly_equal(u.fD, v.fD)
+ && nearly_equal(u.fE, v.fE)
+ && nearly_equal(u.fF, v.fF);
}
static bool nearly_equal(const float u[9], const float v[9]) {
@@ -228,23 +228,23 @@ static bool nearly_equal(const float u[9], const float v[9]) {
// Return nullptr if the color profile doen't have a special name.
const char* get_color_profile_description(const SkColorSpaceTransferFn& fn,
const float toXYZD50[9]) {
- bool srgb_xfer = nearly_equal(fn, SkNamedTransferFn::kSRGB);
- bool srgb_gamut = nearly_equal(toXYZD50, &SkNamedGamut::kSRGB.vals[0][0]);
+ bool srgb_xfer = nearly_equal(fn, gSRGB_TransferFn);
+ bool srgb_gamut = nearly_equal(toXYZD50, gSRGB_toXYZD50);
if (srgb_xfer && srgb_gamut) {
return "sRGB";
}
- bool line_xfer = nearly_equal(fn, SkNamedTransferFn::kLinear);
+ bool line_xfer = nearly_equal(fn, gLinear_TransferFn);
if (line_xfer && srgb_gamut) {
return "Linear Transfer with sRGB Gamut";
}
- bool twoDotTwo = nearly_equal(fn, SkNamedTransferFn::k2Dot2);
+ bool twoDotTwo = nearly_equal(fn, g2Dot2_TransferFn);
if (twoDotTwo && srgb_gamut) {
return "2.2 Transfer with sRGB Gamut";
}
- if (twoDotTwo && nearly_equal(toXYZD50, &SkNamedGamut::kAdobeRGB.vals[0][0])) {
+ if (twoDotTwo && nearly_equal(toXYZD50, gAdobeRGB_toXYZD50)) {
return "AdobeRGB";
}
- bool dcip3_gamut = nearly_equal(toXYZD50, &SkNamedGamut::kDCIP3.vals[0][0]);
+ bool dcip3_gamut = nearly_equal(toXYZD50, gDCIP3_toXYZD50);
if (srgb_xfer || line_xfer) {
if (srgb_xfer && dcip3_gamut) {
return "sRGB Transfer with DCI-P3 Gamut";
@@ -252,7 +252,7 @@ const char* get_color_profile_description(const SkColorSpaceTransferFn& fn,
if (line_xfer && dcip3_gamut) {
return "Linear Transfer with DCI-P3 Gamut";
}
- bool rec2020 = nearly_equal(toXYZD50, &SkNamedGamut::kRec2020.vals[0][0]);
+ bool rec2020 = nearly_equal(toXYZD50, gRec2020_toXYZD50);
if (srgb_xfer && rec2020) {
return "sRGB Transfer with Rec-BT-2020 Gamut";
}
diff --git a/src/gpu/GrColorSpaceXform.cpp b/src/gpu/GrColorSpaceXform.cpp
index 2cd5e5a0ea..e8cb662aff 100644
--- a/src/gpu/GrColorSpaceXform.cpp
+++ b/src/gpu/GrColorSpaceXform.cpp
@@ -8,6 +8,7 @@
#include "GrColorSpaceXform.h"
#include "SkColorSpace.h"
#include "SkColorSpacePriv.h"
+#include "SkMatrix44.h"
#include "glsl/GrGLSLColorSpaceXformHelper.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
diff --git a/tests/AndroidCodecTest.cpp b/tests/AndroidCodecTest.cpp
index 49415f8f93..3381d4f5ce 100644
--- a/tests/AndroidCodecTest.cpp
+++ b/tests/AndroidCodecTest.cpp
@@ -15,6 +15,7 @@
#include "SkEncodedImageFormat.h"
#include "SkImageGenerator.h"
#include "SkImageInfo.h"
+#include "SkMatrix44.h"
#include "SkPixmapPriv.h"
#include "SkRefCnt.h"
#include "SkSize.h"
@@ -156,7 +157,8 @@ DEF_TEST(AndroidCodec_wide, r) {
return;
}
- auto expected = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
+ auto expected = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut);
REPORTER_ASSERT(r, SkColorSpace::Equals(cs.get(), expected.get()));
}
@@ -188,15 +190,17 @@ DEF_TEST(AndroidCodec_P3, r) {
REPORTER_ASSERT(r, !cs->isSRGB());
REPORTER_ASSERT(r, cs->gammaCloseToSRGB());
- skcms_Matrix3x3 matrix;
+ SkMatrix44 matrix;
cs->toXYZD50(&matrix);
- static constexpr skcms_Matrix3x3 kExpected = {{
- { 0.426254272f, 0.369018555f, 0.168914795f },
- { 0.226013184f, 0.685974121f, 0.0880126953f },
- { 0.0116729736f, 0.0950927734f, 0.71812439f },
- }};
- REPORTER_ASSERT(r, 0 == memcmp(&matrix, &kExpected, sizeof(skcms_Matrix3x3)));
+ SkMatrix44 expected;
+ static constexpr float kExpected[] = {
+ 0.426254272f, 0.369018555f, 0.168914795f,
+ 0.226013184f, 0.685974121f, 0.0880126953f,
+ 0.0116729736f, 0.0950927734f, 0.71812439f,
+ };
+ expected.set3x3RowMajorf(kExpected);
+ REPORTER_ASSERT(r, matrix == expected);
}
DEF_TEST(AndroidCodec_orientation, r) {
diff --git a/tests/CanvasTest.cpp b/tests/CanvasTest.cpp
index 8aeb0c4995..bf30dd9c55 100644
--- a/tests/CanvasTest.cpp
+++ b/tests/CanvasTest.cpp
@@ -813,8 +813,8 @@ DEF_TEST(CanvasClipType, r) {
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
DEF_TEST(Canvas_LegacyColorBehavior, r) {
- sk_sp<SkColorSpace> cs = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
- SkNamedGamut::kAdobeRGB);
+ sk_sp<SkColorSpace> cs = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kAdobeRGB_Gamut);
// Make a Adobe RGB bitmap.
SkBitmap bitmap;
diff --git a/tests/CodecTest.cpp b/tests/CodecTest.cpp
index 8c918a8395..bd988f6637 100644
--- a/tests/CodecTest.cpp
+++ b/tests/CodecTest.cpp
@@ -26,6 +26,7 @@
#include "SkMD5.h"
#include "SkMakeUnique.h"
#include "SkMalloc.h"
+#include "SkMatrix44.h"
#include "SkPixmap.h"
#include "SkPngChunkReader.h"
#include "SkPngEncoder.h"
@@ -1024,7 +1025,7 @@ static void check_color_xform(skiatest::Reporter* r, const char* path) {
const int dstWidth = subsetWidth / opts.fSampleSize;
const int dstHeight = subsetHeight / opts.fSampleSize;
- auto colorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, SkNamedGamut::kAdobeRGB);
+ auto colorSpace = SkColorSpace::MakeRGB(g2Dot2_TransferFn, SkColorSpace::kAdobeRGB_Gamut);
SkImageInfo dstInfo = codec->getInfo().makeWH(dstWidth, dstHeight)
.makeColorType(kN32_SkColorType)
.makeColorSpace(colorSpace);
@@ -1590,21 +1591,22 @@ static void test_encode_icc(skiatest::Reporter* r, SkEncodedImageFormat format)
// Test with P3 color space.
SkDynamicMemoryWStream p3Buf;
- sk_sp<SkColorSpace> p3 = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
+ sk_sp<SkColorSpace> p3 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut);
pixmap.setColorSpace(p3);
encode_format(&p3Buf, pixmap, format);
sk_sp<SkData> p3Data = p3Buf.detachAsData();
std::unique_ptr<SkCodec> p3Codec(SkCodec::MakeFromData(p3Data));
REPORTER_ASSERT(r, p3Codec->getInfo().colorSpace()->gammaCloseToSRGB());
- skcms_Matrix3x3 mat0, mat1;
+ SkMatrix44 mat0, mat1;
bool success = p3->toXYZD50(&mat0);
REPORTER_ASSERT(r, success);
success = p3Codec->getInfo().colorSpace()->toXYZD50(&mat1);
REPORTER_ASSERT(r, success);
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- REPORTER_ASSERT(r, color_space_almost_equal(mat0.vals[i][j], mat1.vals[i][j]));
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ REPORTER_ASSERT(r, color_space_almost_equal(mat0.get(i, j), mat1.get(i, j)));
}
}
}
diff --git a/tests/ColorSpaceTest.cpp b/tests/ColorSpaceTest.cpp
index 1deb8eeee0..42986e950e 100644
--- a/tests/ColorSpaceTest.cpp
+++ b/tests/ColorSpaceTest.cpp
@@ -11,6 +11,7 @@
#include "SkColorSpacePriv.h"
#include "SkData.h"
#include "SkImageInfo.h"
+#include "SkMatrix44.h"
#include "SkRefCnt.h"
#include "SkStream.h"
#include "SkTypes.h"
@@ -33,13 +34,20 @@ static void test_space(skiatest::Reporter* r, SkColorSpace* space,
REPORTER_ASSERT(r, nullptr != space);
REPORTER_ASSERT(r, expectedGamma == space->gammaNamed());
- skcms_Matrix3x3 mat;
+ SkMatrix44 mat;
space->toXYZD50(&mat);
+ const float src[] = {
+ 1, 0, 0, 1,
+ 0, 1, 0, 1,
+ 0, 0, 1, 1,
+ };
const float* ref[3] = { red, green, blue };
+ float dst[4];
for (int i = 0; i < 3; ++i) {
- REPORTER_ASSERT(r, almost_equal(ref[i][0], mat.vals[0][i]));
- REPORTER_ASSERT(r, almost_equal(ref[i][1], mat.vals[1][i]));
- REPORTER_ASSERT(r, almost_equal(ref[i][2], mat.vals[2][i]));
+ mat.mapScalars(&src[i*4], dst);
+ REPORTER_ASSERT(r, almost_equal(ref[i][0], dst[0]));
+ REPORTER_ASSERT(r, almost_equal(ref[i][1], dst[1]));
+ REPORTER_ASSERT(r, almost_equal(ref[i][2], dst[2]));
}
}
@@ -62,6 +70,12 @@ static void test_path(skiatest::Reporter* r, const char* path,
test_space(r, colorSpace.get(), red, green, blue, expectedGamma);
}
+static constexpr float g_sRGB_XYZ[]{
+ 0.4358f, 0.3853f, 0.1430f, // Rx, Gx, Bx
+ 0.2224f, 0.7170f, 0.0606f, // Ry, Gy, Gz
+ 0.0139f, 0.0971f, 0.7139f, // Rz, Gz, Bz
+};
+
static constexpr float g_sRGB_R[]{ 0.4358f, 0.2224f, 0.0139f };
static constexpr float g_sRGB_G[]{ 0.3853f, 0.7170f, 0.0971f };
static constexpr float g_sRGB_B[]{ 0.1430f, 0.0606f, 0.7139f };
@@ -79,9 +93,9 @@ DEF_TEST(ColorSpaceParseICCProfiles, r) {
kSRGB_SkGammaNamed);
#endif
- const float red[] = { 0.385117f, 0.716904f, 0.0970612f };
+ const float red[] = { 0.385117f, 0.716904f, 0.0970612f };
const float green[] = { 0.143051f, 0.0606079f, 0.713913f };
- const float blue[] = { 0.436035f, 0.222488f, 0.013916f };
+ const float blue[] = { 0.436035f, 0.222488f, 0.013916f };
test_path(r, "images/icc-v2-gbr.jpg", red, green, blue, k2Dot2Curve_SkGammaNamed);
test_path(r, "images/webp-color-profile-crash.webp",
@@ -94,6 +108,80 @@ DEF_TEST(ColorSpaceParseICCProfiles, r) {
red, green, blue, kNonStandard_SkGammaNamed);
}
+DEF_TEST(ColorSpaceSRGBCompare, r) {
+ // Create an sRGB color space by name
+ sk_sp<SkColorSpace> namedColorSpace = SkColorSpace::MakeSRGB();
+
+ // Create an sRGB color space by value
+ SkMatrix44 srgbToxyzD50;
+ srgbToxyzD50.set3x3RowMajorf(g_sRGB_XYZ);
+ sk_sp<SkColorSpace> rgbColorSpace =
+ SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, srgbToxyzD50);
+ REPORTER_ASSERT(r, rgbColorSpace == namedColorSpace);
+
+ SkColorSpaceTransferFn srgbFn;
+ srgbFn.fA = (1.0f / 1.055f);
+ srgbFn.fB = (0.055f / 1.055f);
+ srgbFn.fC = (1.0f / 12.92f);
+ srgbFn.fD = 0.04045f;
+ srgbFn.fE = 0.0f;
+ srgbFn.fF = 0.0f;
+ srgbFn.fG = 2.4f;
+ sk_sp<SkColorSpace> rgbColorSpace2 = SkColorSpace::MakeRGB(srgbFn, srgbToxyzD50);
+ REPORTER_ASSERT(r, rgbColorSpace2 == namedColorSpace);
+
+ // Change a single value from the sRGB matrix
+ srgbToxyzD50.set(2, 2, 0.5f);
+ sk_sp<SkColorSpace> strangeColorSpace =
+ SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, srgbToxyzD50);
+ REPORTER_ASSERT(r, strangeColorSpace != namedColorSpace);
+}
+
+DEF_TEST(ColorSpaceSRGBLinearCompare, r) {
+ // Create the linear sRGB color space by name
+ sk_sp<SkColorSpace> namedColorSpace = SkColorSpace::MakeSRGBLinear();
+
+ // Create the linear sRGB color space via the sRGB color space's makeLinearGamma()
+ auto srgb = SkColorSpace::MakeSRGB();
+ sk_sp<SkColorSpace> viaSrgbColorSpace = srgb->makeLinearGamma();
+ REPORTER_ASSERT(r, namedColorSpace == viaSrgbColorSpace);
+
+ // Create a linear sRGB color space by value
+ SkMatrix44 srgbToxyzD50;
+ srgbToxyzD50.set3x3RowMajorf(g_sRGB_XYZ);
+ sk_sp<SkColorSpace> rgbColorSpace =
+ SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, srgbToxyzD50);
+ REPORTER_ASSERT(r, rgbColorSpace == namedColorSpace);
+
+ SkColorSpaceTransferFn linearExpFn;
+ linearExpFn.fA = 1.0f;
+ linearExpFn.fB = 0.0f;
+ linearExpFn.fC = 0.0f;
+ linearExpFn.fD = 0.0f;
+ linearExpFn.fE = 0.0f;
+ linearExpFn.fF = 0.0f;
+ linearExpFn.fG = 1.0f;
+ sk_sp<SkColorSpace> rgbColorSpace2 = SkColorSpace::MakeRGB(linearExpFn, srgbToxyzD50);
+ REPORTER_ASSERT(r, rgbColorSpace2 == namedColorSpace);
+
+ SkColorSpaceTransferFn linearFn;
+ linearFn.fA = 0.0f;
+ linearFn.fB = 0.0f;
+ linearFn.fC = 1.0f;
+ linearFn.fD = 1.0f;
+ linearFn.fE = 0.0f;
+ linearFn.fF = 0.0f;
+ linearFn.fG = 0.0f;
+ sk_sp<SkColorSpace> rgbColorSpace3 = SkColorSpace::MakeRGB(linearFn, srgbToxyzD50);
+ REPORTER_ASSERT(r, rgbColorSpace3 == namedColorSpace);
+
+ // Change a single value from the sRGB matrix
+ srgbToxyzD50.set(2, 2, 0.5f);
+ sk_sp<SkColorSpace> strangeColorSpace =
+ SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, srgbToxyzD50);
+ REPORTER_ASSERT(r, strangeColorSpace != namedColorSpace);
+}
+
static void test_serialize(skiatest::Reporter* r, sk_sp<SkColorSpace> space, bool isNamed) {
sk_sp<SkData> data1 = space->serialize();
@@ -131,19 +219,15 @@ DEF_TEST(ColorSpace_Serialize, r) {
test("icc_profiles/HP_ZR30w.icc");
test("icc_profiles/HP_Z32x.icc");
- skcms_TransferFunction fn;
- fn.a = 1.0f;
- fn.b = 0.0f;
- fn.c = 1.0f;
- fn.d = 0.5f;
- fn.e = 0.0f;
- fn.f = 0.0f;
- fn.g = 1.0f;
- skcms_Matrix3x3 toXYZ = {{
- { 1, 0, 0 },
- { 0, 1, 0 },
- { 0, 0, 1 },
- }};
+ SkColorSpaceTransferFn fn;
+ fn.fA = 1.0f;
+ fn.fB = 0.0f;
+ fn.fC = 1.0f;
+ fn.fD = 0.5f;
+ fn.fE = 0.0f;
+ fn.fF = 0.0f;
+ fn.fG = 1.0f;
+ SkMatrix44 toXYZ(SkMatrix44::kIdentity_Constructor);
test_serialize(r, SkColorSpace::MakeRGB(fn, toXYZ), false);
}
@@ -164,19 +248,15 @@ DEF_TEST(ColorSpace_Equals, r) {
sk_sp<SkColorSpace> z30 = parse("icc_profiles/HP_ZR30w.icc");
sk_sp<SkColorSpace> z32 = parse("icc_profiles/HP_Z32x.icc");
- skcms_TransferFunction fn;
- fn.a = 1.0f;
- fn.b = 0.0f;
- fn.c = 1.0f;
- fn.d = 0.5f;
- fn.e = 0.0f;
- fn.f = 0.0f;
- fn.g = 1.0f;
- skcms_Matrix3x3 toXYZ = {{
- { 1, 0, 0 },
- { 0, 1, 0 },
- { 0, 0, 1 },
- }};
+ SkColorSpaceTransferFn fn;
+ fn.fA = 1.0f;
+ fn.fB = 0.0f;
+ fn.fC = 1.0f;
+ fn.fD = 0.5f;
+ fn.fE = 0.0f;
+ fn.fF = 0.0f;
+ fn.fG = 1.0f;
+ SkMatrix44 toXYZ(SkMatrix44::kIdentity_Constructor);
sk_sp<SkColorSpace> rgb4 = SkColorSpace::MakeRGB(fn, toXYZ);
REPORTER_ASSERT(r, SkColorSpace::Equals(nullptr, nullptr));
@@ -193,20 +273,28 @@ DEF_TEST(ColorSpace_Equals, r) {
REPORTER_ASSERT(r, !SkColorSpace::Equals(srgb.get(), rgb4.get()));
}
-static inline bool matrix_almost_equal(const skcms_Matrix3x3& a, const skcms_Matrix3x3& b) {
- for (int r = 0; r < 3; ++r) {
- for (int c = 0; c < 3; ++c) {
- if (!almost_equal(a.vals[r][c], b.vals[r][c])) {
- return false;
- }
- }
- }
- return true;
+static inline bool matrix_almost_equal(const SkMatrix44& a, const SkMatrix44& b) {
+ return almost_equal(a.get(0, 0), b.get(0, 0)) &&
+ almost_equal(a.get(0, 1), b.get(0, 1)) &&
+ almost_equal(a.get(0, 2), b.get(0, 2)) &&
+ almost_equal(a.get(0, 3), b.get(0, 3)) &&
+ almost_equal(a.get(1, 0), b.get(1, 0)) &&
+ almost_equal(a.get(1, 1), b.get(1, 1)) &&
+ almost_equal(a.get(1, 2), b.get(1, 2)) &&
+ almost_equal(a.get(1, 3), b.get(1, 3)) &&
+ almost_equal(a.get(2, 0), b.get(2, 0)) &&
+ almost_equal(a.get(2, 1), b.get(2, 1)) &&
+ almost_equal(a.get(2, 2), b.get(2, 2)) &&
+ almost_equal(a.get(2, 3), b.get(2, 3)) &&
+ almost_equal(a.get(3, 0), b.get(3, 0)) &&
+ almost_equal(a.get(3, 1), b.get(3, 1)) &&
+ almost_equal(a.get(3, 2), b.get(3, 2)) &&
+ almost_equal(a.get(3, 3), b.get(3, 3));
}
static inline void check_primaries(skiatest::Reporter* r, const SkColorSpacePrimaries& primaries,
- const skcms_Matrix3x3& reference) {
- skcms_Matrix3x3 toXYZ;
+ const SkMatrix44& reference) {
+ SkMatrix44 toXYZ;
bool result = primaries.toXYZD50(&toXYZ);
REPORTER_ASSERT(r, result);
REPORTER_ASSERT(r, matrix_almost_equal(toXYZ, reference));
@@ -214,16 +302,21 @@ static inline void check_primaries(skiatest::Reporter* r, const SkColorSpacePrim
DEF_TEST(ColorSpace_Primaries, r) {
// sRGB primaries (D65)
- skcms_Matrix3x3 srgbToXYZ;
- bool result = skcms_PrimariesToXYZD50(
- 0.64f, 0.33f,
- 0.30f, 0.60f,
- 0.15f, 0.06f,
- 0.3127f, 0.3290f,
- &srgbToXYZ);
+ SkColorSpacePrimaries srgb;
+ srgb.fRX = 0.64f;
+ srgb.fRY = 0.33f;
+ srgb.fGX = 0.30f;
+ srgb.fGY = 0.60f;
+ srgb.fBX = 0.15f;
+ srgb.fBY = 0.06f;
+ srgb.fWX = 0.3127f;
+ srgb.fWY = 0.3290f;
+ SkMatrix44 srgbToXYZ;
+ bool result = srgb.toXYZD50(&srgbToXYZ);
REPORTER_ASSERT(r, result);
- sk_sp<SkColorSpace> space = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, srgbToXYZ);
+ sk_sp<SkColorSpace> space = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ srgbToXYZ);
REPORTER_ASSERT(r, SkColorSpace::MakeSRGB() == space);
// ProPhoto (D50)
@@ -236,11 +329,10 @@ DEF_TEST(ColorSpace_Primaries, r) {
proPhoto.fBY = 0.0001f;
proPhoto.fWX = 0.34567f;
proPhoto.fWY = 0.35850f;
- skcms_Matrix3x3 proToXYZ = {{
- { 0.7976749f, 0.1351917f, 0.0313534f },
- { 0.2880402f, 0.7118741f, 0.0000857f },
- { 0.0000000f, 0.0000000f, 0.8252100f },
- }};
+ SkMatrix44 proToXYZ;
+ proToXYZ.set3x3(0.7976749f, 0.2880402f, 0.0000000f,
+ 0.1351917f, 0.7118741f, 0.0000000f,
+ 0.0313534f, 0.0000857f, 0.8252100f);
check_primaries(r, proPhoto, proToXYZ);
// NTSC (C)
@@ -253,11 +345,10 @@ DEF_TEST(ColorSpace_Primaries, r) {
ntsc.fBY = 0.08f;
ntsc.fWX = 0.31006f;
ntsc.fWY = 0.31616f;
- skcms_Matrix3x3 ntscToXYZ = {{
- { 0.6343706f, 0.1852204f, 0.1446290f },
- { 0.3109496f, 0.5915984f, 0.0974520f },
- { -0.0011817f, 0.0555518f, 0.7708399f }
- }};
+ SkMatrix44 ntscToXYZ;
+ ntscToXYZ.set3x3(0.6343706f, 0.3109496f, -0.0011817f,
+ 0.1852204f, 0.5915984f, 0.0555518f,
+ 0.1446290f, 0.0974520f, 0.7708399f);
check_primaries(r, ntsc, ntscToXYZ);
// DCI P3 (D65)
@@ -270,8 +361,9 @@ DEF_TEST(ColorSpace_Primaries, r) {
p3.fBY = 0.060f;
p3.fWX = 0.3127f;
p3.fWY = 0.3290f;
- space = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
- skcms_Matrix3x3 reference;
+ space = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut);
+ SkMatrix44 reference;
SkAssertResult(space->toXYZD50(&reference));
check_primaries(r, p3, reference);
@@ -285,7 +377,8 @@ DEF_TEST(ColorSpace_Primaries, r) {
rec2020.fBY = 0.046f;
rec2020.fWX = 0.3127f;
rec2020.fWY = 0.3290f;
- space = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kRec2020);
+ space = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kRec2020_Gamut);
SkAssertResult(space->toXYZD50(&reference));
check_primaries(r, rec2020, reference);
}
@@ -293,16 +386,18 @@ DEF_TEST(ColorSpace_Primaries, r) {
DEF_TEST(ColorSpace_MatrixHash, r) {
sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
- skcms_TransferFunction fn;
- fn.a = 1.0f;
- fn.b = 0.0f;
- fn.c = 0.0f;
- fn.d = 0.0f;
- fn.e = 0.0f;
- fn.f = 0.0f;
- fn.g = 3.0f;
+ SkColorSpaceTransferFn fn;
+ fn.fA = 1.0f;
+ fn.fB = 0.0f;
+ fn.fC = 0.0f;
+ fn.fD = 0.0f;
+ fn.fE = 0.0f;
+ fn.fF = 0.0f;
+ fn.fG = 3.0f;
- sk_sp<SkColorSpace> strange = SkColorSpace::MakeRGB(fn, SkNamedGamut::kSRGB);
+ SkMatrix44 srgbMat;
+ srgbMat.set3x3RowMajorf(gSRGB_toXYZD50);
+ sk_sp<SkColorSpace> strange = SkColorSpace::MakeRGB(fn, srgbMat);
REPORTER_ASSERT(r, srgb->toXYZD50Hash() == strange->toXYZD50Hash());
}
@@ -310,15 +405,15 @@ DEF_TEST(ColorSpace_MatrixHash, r) {
DEF_TEST(ColorSpace_IsSRGB, r) {
sk_sp<SkColorSpace> srgb0 = SkColorSpace::MakeSRGB();
- skcms_TransferFunction fn;
- fn.a = 1.0f;
- fn.b = 0.0f;
- fn.c = 0.0f;
- fn.d = 0.0f;
- fn.e = 0.0f;
- fn.f = 0.0f;
- fn.g = 2.2f;
- sk_sp<SkColorSpace> twoDotTwo = SkColorSpace::MakeRGB(fn, SkNamedGamut::kSRGB);
+ SkColorSpaceTransferFn fn;
+ fn.fA = 1.0f;
+ fn.fB = 0.0f;
+ fn.fC = 0.0f;
+ fn.fD = 0.0f;
+ fn.fE = 0.0f;
+ fn.fF = 0.0f;
+ fn.fG = 2.2f;
+ sk_sp<SkColorSpace> twoDotTwo = SkColorSpace::MakeRGB(fn, SkColorSpace::kSRGB_Gamut);
REPORTER_ASSERT(r, srgb0->isSRGB());
REPORTER_ASSERT(r, !twoDotTwo->isSRGB());
diff --git a/tests/DeferredDisplayListTest.cpp b/tests/DeferredDisplayListTest.cpp
index 8e49446408..3f03ae1069 100644
--- a/tests/DeferredDisplayListTest.cpp
+++ b/tests/DeferredDisplayListTest.cpp
@@ -296,7 +296,8 @@ public:
case 4:
// This just needs to be a colorSpace different from that returned by MakeSRGB().
// In this case we just change the gamut.
- fColorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kAdobeRGB);
+ fColorSpace = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kAdobeRGB_Gamut);
break;
case kSampleCount:
fSampleCount = 4;
diff --git a/tests/ICCTest.cpp b/tests/ICCTest.cpp
index efe39a4715..f82bfa4f8e 100644
--- a/tests/ICCTest.cpp
+++ b/tests/ICCTest.cpp
@@ -15,13 +15,56 @@
#include "../third_party/skcms/skcms.h"
+DEF_TEST(WriteICCProfile, r) {
+ auto adobeRGB = SkColorSpace::MakeRGB(g2Dot2_TransferFn, SkColorSpace::kAdobeRGB_Gamut);
+
+ struct {
+ SkColorSpaceTransferFn fn;
+ const float* toXYZD50;
+ const char* desc;
+ sk_sp<SkColorSpace> want;
+ } tests[] = {
+ {g2Dot2_TransferFn, gAdobeRGB_toXYZD50, "AdobeRGB", adobeRGB},
+ { gSRGB_TransferFn, gSRGB_toXYZD50, "sRGB", SkColorSpace::MakeSRGB()},
+ };
+
+ for (auto test : tests) {
+ sk_sp<SkData> profile = SkWriteICCProfile(test.fn, test.toXYZD50);
+ REPORTER_ASSERT(r, profile);
+
+ skcms_ICCProfile parsed;
+ REPORTER_ASSERT(r, skcms_Parse(profile->data(), profile->size(), &parsed));
+
+ sk_sp<SkColorSpace> got = SkColorSpace::Make(parsed);
+ REPORTER_ASSERT(r, got);
+ REPORTER_ASSERT(r, SkColorSpace::Equals(got.get(), test.want.get()));
+
+ skcms_ICCTag desc;
+ REPORTER_ASSERT(r, skcms_GetTagBySignature(&parsed,
+ SkSetFourByteTag('d','e','s','c'),
+ &desc));
+
+ // Rather than really carefully break down the 'desc' tag,
+ // just check our expected description is somewhere in there (as big-endian UTF-16).
+ uint8_t big_endian_utf16[16];
+ for (size_t i = 0; i < strlen(test.desc); i++) {
+ big_endian_utf16[2*i+0] = 0;
+ big_endian_utf16[2*i+1] = test.desc[i];
+ }
+
+ SkString haystack((const char*)desc.buf, desc.size),
+ needle ((const char*)big_endian_utf16, 2*strlen(test.desc));
+ REPORTER_ASSERT(r, haystack.contains(needle.c_str()));
+ }
+}
+
DEF_TEST(AdobeRGB, r) {
if (sk_sp<SkData> profile = GetResourceAsData("icc_profiles/AdobeRGB1998.icc")) {
skcms_ICCProfile parsed;
REPORTER_ASSERT(r, skcms_Parse(profile->data(), profile->size(), &parsed));
auto got = SkColorSpace::Make(parsed);
- auto want = SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, SkNamedGamut::kAdobeRGB);
+ auto want = SkColorSpace::MakeRGB(g2Dot2_TransferFn, SkColorSpace::kAdobeRGB_Gamut);
REPORTER_ASSERT(r, SkColorSpace::Equals(got.get(), want.get()));
}
}
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index 1ad49dde7c..9b788216e8 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -1168,13 +1168,13 @@ DEF_TEST(Image_ColorSpace, r) {
REPORTER_ASSERT(r, srgb.get() == image->colorSpace());
image = GetResourceAsImage("images/webp-color-profile-lossy.webp");
- skcms_TransferFunction fn;
+ SkColorSpaceTransferFn fn;
bool success = image->colorSpace()->isNumericalTransferFn(&fn);
REPORTER_ASSERT(r, success);
- REPORTER_ASSERT(r, color_space_almost_equal(1.8f, fn.g));
+ REPORTER_ASSERT(r, color_space_almost_equal(1.8f, fn.fG));
- sk_sp<SkColorSpace> rec2020 = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
- SkNamedGamut::kRec2020);
+ sk_sp<SkColorSpace> rec2020 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kRec2020_Gamut);
image = create_picture_image(rec2020);
REPORTER_ASSERT(r, SkColorSpace::Equals(rec2020.get(), image->colorSpace()));
@@ -1195,10 +1195,11 @@ DEF_TEST(Image_ColorSpace, r) {
}
DEF_TEST(Image_makeColorSpace, r) {
- sk_sp<SkColorSpace> p3 = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
- skcms_TransferFunction fn;
- fn.a = 1.f; fn.b = 0.f; fn.c = 0.f; fn.d = 0.f; fn.e = 0.f; fn.f = 0.f; fn.g = 1.8f;
- sk_sp<SkColorSpace> adobeGamut = SkColorSpace::MakeRGB(fn, SkNamedGamut::kAdobeRGB);
+ sk_sp<SkColorSpace> p3 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut);
+ SkColorSpaceTransferFn fn;
+ fn.fA = 1.f; fn.fB = 0.f; fn.fC = 0.f; fn.fD = 0.f; fn.fE = 0.f; fn.fF = 0.f; fn.fG = 1.8f;
+ sk_sp<SkColorSpace> adobeGamut = SkColorSpace::MakeRGB(fn, SkColorSpace::kAdobeRGB_Gamut);
SkBitmap srgbBitmap;
srgbBitmap.allocPixels(SkImageInfo::MakeS32(1, 1, kOpaque_SkAlphaType));
diff --git a/tests/NonlinearBlendingTest.cpp b/tests/NonlinearBlendingTest.cpp
index 768d964fcd..e91dda8a98 100644
--- a/tests/NonlinearBlendingTest.cpp
+++ b/tests/NonlinearBlendingTest.cpp
@@ -12,7 +12,8 @@
DEF_TEST(SkColorSpaceXformSteps_vs_skcms, r) {
auto srgb = SkColorSpace::MakeSRGB();
- auto dp3 = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
+ auto dp3 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut);
skcms_ICCProfile srgb_profile;
srgb->toProfile(&srgb_profile);
diff --git a/tests/SkColorSpaceXformStepsTest.cpp b/tests/SkColorSpaceXformStepsTest.cpp
index 6b15385c38..f0ae414c60 100644
--- a/tests/SkColorSpaceXformStepsTest.cpp
+++ b/tests/SkColorSpaceXformStepsTest.cpp
@@ -11,8 +11,8 @@
DEF_TEST(SkColorSpaceXformSteps, r) {
auto srgb = SkColorSpace::MakeSRGB(),
- adobe = SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, SkNamedGamut::kAdobeRGB),
- srgb22 = SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, SkNamedGamut::kSRGB),
+ adobe = SkColorSpace::MakeRGB(g2Dot2_TransferFn, SkColorSpace::kAdobeRGB_Gamut),
+ srgb22 = SkColorSpace::MakeRGB(g2Dot2_TransferFn, SkColorSpace:: kSRGB_Gamut),
srgb1 = srgb ->makeLinearGamma(),
adobe1 = adobe->makeLinearGamma();
diff --git a/tests/TableColorFilterTest.cpp b/tests/TableColorFilterTest.cpp
index bb5df60b8b..857aa7ed69 100644
--- a/tests/TableColorFilterTest.cpp
+++ b/tests/TableColorFilterTest.cpp
@@ -17,7 +17,8 @@
DEF_TEST(TableColorFilter, r) {
// Using a wide source gamut will make saturated colors go well out of range of sRGB.
- auto rec2020 = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kRec2020);
+ auto rec2020 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kRec2020_Gamut);
sk_sp<SkColorFilter> to_srgb = SkToSRGBColorFilter::Make(rec2020);
// Any table will work fine here. An identity table makes testing easy.
diff --git a/tests/ToSRGBColorFilter.cpp b/tests/ToSRGBColorFilter.cpp
index 519ffb8a35..01c5673d4d 100644
--- a/tests/ToSRGBColorFilter.cpp
+++ b/tests/ToSRGBColorFilter.cpp
@@ -22,7 +22,8 @@ DEF_TEST(SkToSRGBColorFilter, r) {
REPORTER_ASSERT(r, nullptr == SkToSRGBColorFilter::Make(nullptr));
// Here's a realistic conversion.
- auto dci_p3 = SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear, SkNamedGamut::kDCIP3);
+ auto dci_p3 = SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut);
REPORTER_ASSERT(r, nullptr != SkToSRGBColorFilter::Make(dci_p3));
}
diff --git a/tools/flags/SkCommonFlagsConfig.cpp b/tools/flags/SkCommonFlagsConfig.cpp
index 44e79ac513..66a5b2a7ba 100644
--- a/tools/flags/SkCommonFlagsConfig.cpp
+++ b/tools/flags/SkCommonFlagsConfig.cpp
@@ -309,13 +309,16 @@ static bool parse_option_gpu_color(const SkString& value,
*outColorSpace = SkColorSpace::MakeSRGB();
} else if (value.equals("p3")) {
*outColorType = kRGBA_8888_SkColorType;
- *outColorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
+ *outColorSpace = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut);
} else if (value.equals("esrgb")) {
*outColorType = kRGBA_F16_SkColorType;
*outColorSpace = SkColorSpace::MakeSRGB();
} else if (value.equals("narrow") || value.equals("enarrow")) {
+ SkMatrix44 narrow_gamut;
+ narrow_gamut.set3x3RowMajorf(gNarrow_toXYZD50);
*outColorType = value.equals("narrow") ? kRGBA_8888_SkColorType : kRGBA_F16_SkColorType;
- *outColorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, gNarrow_toXYZD50);
+ *outColorSpace = SkColorSpace::MakeRGB(k2Dot2Curve_SkGammaNamed, narrow_gamut);
} else if (value.equals("f16")) {
*outColorType = kRGBA_F16_SkColorType;
*outColorSpace = SkColorSpace::MakeSRGBLinear();
diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp
index 7ec001bac0..fcae406db7 100644
--- a/tools/viewer/Viewer.cpp
+++ b/tools/viewer/Viewer.cpp
@@ -185,7 +185,7 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
, fColorMode(ColorMode::kLegacy)
, fColorSpacePrimaries(gSrgbPrimaries)
// Our UI can only tweak gamma (currently), so start out gamma-only
- , fColorSpaceTransferFn(SkNamedTransferFn::k2Dot2)
+ , fColorSpaceTransferFn(g2Dot2_TransferFn)
, fZoomLevel(0.0f)
, fRotation(0.0f)
, fOffset{0.5f, 0.5f}
@@ -748,7 +748,7 @@ void Viewer::updateTitle() {
}
title.appendf(" %s Gamma %f",
curPrimaries >= 0 ? gNamedPrimaries[curPrimaries].fName : "Custom",
- fColorSpaceTransferFn.g);
+ fColorSpaceTransferFn.fG);
}
const DisplayParams& params = fWindow->getRequestedDisplayParams();
@@ -1091,7 +1091,7 @@ void Viewer::drawSlide(SkCanvas* canvas) {
// If we're in any of the color managed modes, construct the color space we're going to use
sk_sp<SkColorSpace> colorSpace = nullptr;
if (ColorMode::kLegacy != fColorMode) {
- skcms_Matrix3x3 toXYZ;
+ SkMatrix44 toXYZ;
SkAssertResult(fColorSpacePrimaries.toXYZD50(&toXYZ));
colorSpace = SkColorSpace::MakeRGB(fColorSpaceTransferFn, toXYZ);
}
@@ -1835,7 +1835,7 @@ void Viewer::drawImGui() {
}
// Let user adjust the gamma
- ImGui::SliderFloat("Gamma", &fColorSpaceTransferFn.g, 0.5f, 3.5f);
+ ImGui::SliderFloat("Gamma", &fColorSpaceTransferFn.fG, 0.5f, 3.5f);
if (ImGui::Combo("Primaries", &primariesIdx,
"sRGB\0AdobeRGB\0P3\0Rec. 2020\0Custom\0\0")) {
diff --git a/tools/viewer/Viewer.h b/tools/viewer/Viewer.h
index 2cff48676c..e140eb4537 100644
--- a/tools/viewer/Viewer.h
+++ b/tools/viewer/Viewer.h
@@ -138,7 +138,7 @@ private:
// Color properties for slide rendering
ColorMode fColorMode;
SkColorSpacePrimaries fColorSpacePrimaries;
- skcms_TransferFunction fColorSpaceTransferFn;
+ SkColorSpaceTransferFn fColorSpaceTransferFn;
// transform data
SkScalar fZoomLevel;