diff options
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(); @@ -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 @@ -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; |