blob: 9b650b32b45ece199a3532a44ef191c752a2ac39 [file] [log] [blame]
raftias94888332016-10-18 10:02:51 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Ravi Mistry113d05f2016-12-17 01:31:03 +00008#include "SkColorSpace_XYZ.h"
9#include "SkColorSpacePriv.h"
raftias94888332016-10-18 10:02:51 -070010#include "SkColorSpaceXform_Base.h"
Matt Sarette151bdb2017-01-04 11:05:05 -050011#include "SkOpts.h"
raftias94888332016-10-18 10:02:51 -070012
Matt Sarettf3880932017-03-24 10:06:03 -040013SkColorSpace_XYZ::SkColorSpace_XYZ(SkGammaNamed gammaNamed, const SkMatrix44& toXYZD50)
14 : INHERITED(nullptr)
raftias94888332016-10-18 10:02:51 -070015 , fGammaNamed(gammaNamed)
16 , fGammas(nullptr)
17 , fToXYZD50(toXYZD50)
Matt Sarette151bdb2017-01-04 11:05:05 -050018 , fToXYZD50Hash(SkOpts::hash_fn(toXYZD50.values(), 16 * sizeof(SkMScalar), 0))
raftias94888332016-10-18 10:02:51 -070019 , fFromXYZD50(SkMatrix44::kUninitialized_Constructor)
20{}
21
22SkColorSpace_XYZ::SkColorSpace_XYZ(SkGammaNamed gammaNamed, sk_sp<SkGammas> gammas,
Matt Sarettf3880932017-03-24 10:06:03 -040023 const SkMatrix44& toXYZD50, sk_sp<SkData> profileData)
24 : INHERITED(std::move(profileData))
raftias94888332016-10-18 10:02:51 -070025 , fGammaNamed(gammaNamed)
26 , fGammas(std::move(gammas))
27 , fToXYZD50(toXYZD50)
Matt Sarette151bdb2017-01-04 11:05:05 -050028 , fToXYZD50Hash(SkOpts::hash_fn(toXYZD50.values(), 16 * sizeof(SkMScalar), 0))
raftias54761282016-12-01 13:44:07 -050029 , fFromXYZD50(SkMatrix44::kUninitialized_Constructor) {
30 SkASSERT(!fGammas || 3 == fGammas->channels());
raftias197e3112016-12-01 15:31:29 -050031 if (fGammas) {
32 for (int i = 0; i < fGammas->channels(); ++i) {
33 if (SkGammas::Type::kTable_Type == fGammas->type(i)) {
34 SkASSERT(fGammas->data(i).fTable.fSize >= 2);
35 }
36 }
37 }
raftias54761282016-12-01 13:44:07 -050038}
raftias94888332016-10-18 10:02:51 -070039
40const SkMatrix44* SkColorSpace_XYZ::fromXYZD50() const {
41 fFromXYZOnce([this] {
42 if (!fToXYZD50.invert(&fFromXYZD50)) {
43 // If a client gives us a dst gamut with a transform that we can't invert, we will
44 // simply give them back a transform to sRGB gamut.
45 SkDEBUGFAIL("Non-invertible XYZ matrix, defaulting to sRGB");
46 SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor);
47 srgbToxyzD50.set3x3RowMajorf(gSRGB_toXYZD50);
48 srgbToxyzD50.invert(&fFromXYZD50);
49 }
50 });
51 return &fFromXYZD50;
52}
53
54bool SkColorSpace_XYZ::onGammaCloseToSRGB() const {
55 return kSRGB_SkGammaNamed == fGammaNamed || k2Dot2Curve_SkGammaNamed == fGammaNamed;
56}
57
58bool SkColorSpace_XYZ::onGammaIsLinear() const {
59 return kLinear_SkGammaNamed == fGammaNamed;
60}
61
Ravi Mistry113d05f2016-12-17 01:31:03 +000062bool SkColorSpace_XYZ::onIsNumericalTransferFn(SkColorSpaceTransferFn* coeffs) const {
63 if (named_to_parametric(coeffs, fGammaNamed)) {
64 return true;
65 }
66
67 SkASSERT(fGammas);
68 if (fGammas->data(0) != fGammas->data(1) || fGammas->data(0) != fGammas->data(2)) {
69 return false;
70 }
71
72 if (fGammas->isValue(0)) {
73 value_to_parametric(coeffs, fGammas->data(0).fValue);
74 return true;
75 }
76
77 if (fGammas->isParametric(0)) {
78 *coeffs = fGammas->params(0);
79 return true;
80 }
81
82 return false;
83}
84
Mike Kleinb1e6cfd2017-06-12 15:20:33 -040085sk_sp<SkColorSpace> SkColorSpace_XYZ::makeLinearGamma() const {
raftias94888332016-10-18 10:02:51 -070086 if (this->gammaIsLinear()) {
Mike Kleinb1e6cfd2017-06-12 15:20:33 -040087 return sk_ref_sp(const_cast<SkColorSpace_XYZ*>(this));
raftias94888332016-10-18 10:02:51 -070088 }
Matt Sarettf3880932017-03-24 10:06:03 -040089 return SkColorSpace_Base::MakeRGB(kLinear_SkGammaNamed, fToXYZD50);
raftias94888332016-10-18 10:02:51 -070090}
91
Mike Kleinb1e6cfd2017-06-12 15:20:33 -040092sk_sp<SkColorSpace> SkColorSpace_XYZ::makeSRGBGamma() const {
Brian Osman12313f02016-11-07 09:42:37 -050093 if (this->gammaCloseToSRGB()) {
Mike Kleinb1e6cfd2017-06-12 15:20:33 -040094 return sk_ref_sp(const_cast<SkColorSpace_XYZ*>(this));
Brian Osman12313f02016-11-07 09:42:37 -050095 }
Matt Sarettf3880932017-03-24 10:06:03 -040096 return SkColorSpace_Base::MakeRGB(kSRGB_SkGammaNamed, fToXYZD50);
Brian Osman12313f02016-11-07 09:42:37 -050097}
98
raftias94888332016-10-18 10:02:51 -070099void SkColorSpace_XYZ::toDstGammaTables(const uint8_t* tables[3], sk_sp<SkData>* storage,
100 int numTables) const {
101 fToDstGammaOnce([this, numTables] {
102 const bool gammasAreMatching = numTables <= 1;
103 fDstStorage =
104 SkData::MakeUninitialized(numTables * SkColorSpaceXform_Base::kDstGammaTableSize);
105 SkColorSpaceXform_Base::BuildDstGammaTables(fToDstGammaTables,
106 (uint8_t*) fDstStorage->writable_data(), this,
107 gammasAreMatching);
108 });
109
110 *storage = fDstStorage;
111 tables[0] = fToDstGammaTables[0];
112 tables[1] = fToDstGammaTables[1];
113 tables[2] = fToDstGammaTables[2];
114}