Line data Source code
1 : /*
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 :
8 : #ifndef SkColorSpace_DEFINED
9 : #define SkColorSpace_DEFINED
10 :
11 : #include "SkMatrix44.h"
12 : #include "SkRefCnt.h"
13 :
14 : class SkData;
15 :
16 : /**
17 : * Describes a color gamut with primaries and a white point.
18 : */
19 : struct SK_API SkColorSpacePrimaries {
20 : float fRX, fRY;
21 : float fGX, fGY;
22 : float fBX, fBY;
23 : float fWX, fWY;
24 :
25 : /**
26 : * Convert primaries and a white point to a toXYZD50 matrix, the preferred color gamut
27 : * representation of SkColorSpace.
28 : */
29 : bool toXYZD50(SkMatrix44* toXYZD50) const;
30 : };
31 :
32 : /**
33 : * Contains the coefficients for a common transfer function equation, specified as
34 : * a transformation from a curved space to linear.
35 : *
36 : * LinearVal = C*InputVal + F , for 0.0f <= InputVal < D
37 : * LinearVal = (A*InputVal + B)^G + E, for D <= InputVal <= 1.0f
38 : *
39 : * Function is undefined if InputVal is not in [ 0.0f, 1.0f ].
40 : * Resulting LinearVals must be in [ 0.0f, 1.0f ].
41 : * Function must be positive and increasing.
42 : */
43 : struct SK_API SkColorSpaceTransferFn {
44 : float fG;
45 : float fA;
46 : float fB;
47 : float fC;
48 : float fD;
49 : float fE;
50 : float fF;
51 :
52 : /**
53 : * Produces a new parametric transfer function equation that is the mathematical inverse of
54 : * this one.
55 : */
56 : SkColorSpaceTransferFn invert() const;
57 : };
58 :
59 0 : class SK_API SkColorSpace : public SkRefCnt {
60 : public:
61 :
62 : /**
63 : * Create the sRGB color space.
64 : */
65 : static sk_sp<SkColorSpace> MakeSRGB();
66 :
67 : /**
68 : * Colorspace with the sRGB primaries, but a linear (1.0) gamma. Commonly used for
69 : * half-float surfaces, and high precision individual colors (gradient stops, etc...)
70 : */
71 : static sk_sp<SkColorSpace> MakeSRGBLinear();
72 :
73 : enum RenderTargetGamma : uint8_t {
74 : kLinear_RenderTargetGamma,
75 :
76 : /**
77 : * Transfer function is the canonical sRGB curve, which has a short linear segment
78 : * followed by a 2.4f exponential.
79 : */
80 : kSRGB_RenderTargetGamma,
81 : };
82 :
83 : enum Gamut {
84 : kSRGB_Gamut,
85 : kAdobeRGB_Gamut,
86 : kDCIP3_D65_Gamut,
87 : kRec2020_Gamut,
88 : };
89 :
90 : /**
91 : * Create an SkColorSpace from a transfer function and a color gamut.
92 : *
93 : * Transfer function can be specified as an enum or as the coefficients to an equation.
94 : * Gamut can be specified as an enum or as the matrix transformation to XYZ D50.
95 : */
96 : static sk_sp<SkColorSpace> MakeRGB(RenderTargetGamma gamma, Gamut gamut);
97 : static sk_sp<SkColorSpace> MakeRGB(RenderTargetGamma gamma, const SkMatrix44& toXYZD50);
98 : static sk_sp<SkColorSpace> MakeRGB(const SkColorSpaceTransferFn& coeffs, Gamut gamut);
99 : static sk_sp<SkColorSpace> MakeRGB(const SkColorSpaceTransferFn& coeffs,
100 : const SkMatrix44& toXYZD50);
101 :
102 : /**
103 : * Create an SkColorSpace from an ICC profile.
104 : */
105 : static sk_sp<SkColorSpace> MakeICC(const void*, size_t);
106 :
107 : /**
108 : * Returns true if the color space gamma is near enough to be approximated as sRGB.
109 : * This includes the canonical sRGB transfer function as well as a 2.2f exponential
110 : * transfer function.
111 : */
112 : bool gammaCloseToSRGB() const;
113 :
114 : /**
115 : * Returns true if the color space gamma is linear.
116 : */
117 : bool gammaIsLinear() const;
118 :
119 : /**
120 : * If the transfer function can be represented as coefficients to the standard
121 : * equation, returns true and sets |fn| to the proper values.
122 : *
123 : * If not, returns false.
124 : */
125 : bool isNumericalTransferFn(SkColorSpaceTransferFn* fn) const;
126 :
127 : /**
128 : * Returns true and sets |toXYZD50| if the color gamut can be described as a matrix.
129 : * Returns false otherwise.
130 : */
131 : bool toXYZD50(SkMatrix44* toXYZD50) const;
132 :
133 : /**
134 : * Returns true if the color space is sRGB.
135 : * Returns false otherwise.
136 : *
137 : * This allows a little bit of tolerance, given that we might see small numerical error
138 : * in some cases: converting ICC fixed point to float, converting white point to D50,
139 : * rounding decisions on transfer function and matrix.
140 : *
141 : * This does not consider a 2.2f exponential transfer function to be sRGB. While these
142 : * functions are similar (and it is sometimes useful to consider them together), this
143 : * function checks for logical equality.
144 : */
145 : bool isSRGB() const;
146 :
147 : /**
148 : * Returns nullptr on failure. Fails when we fallback to serializing ICC data and
149 : * the data is too large to serialize.
150 : */
151 : sk_sp<SkData> serialize() const;
152 :
153 : /**
154 : * If |memory| is nullptr, returns the size required to serialize.
155 : * Otherwise, serializes into |memory| and returns the size.
156 : */
157 : size_t writeToMemory(void* memory) const;
158 :
159 : static sk_sp<SkColorSpace> Deserialize(const void* data, size_t length);
160 :
161 : /**
162 : * If both are null, we return true. If one is null and the other is not, we return false.
163 : * If both are non-null, we do a deeper compare.
164 : */
165 : static bool Equals(const SkColorSpace* src, const SkColorSpace* dst);
166 :
167 : protected:
168 1 : SkColorSpace() {}
169 : };
170 :
171 : enum class SkTransferFunctionBehavior {
172 : /**
173 : * Converts to a linear space before premultiplying, unpremultiplying, or blending.
174 : */
175 : kRespect,
176 :
177 : /**
178 : * Premultiplies, unpremultiplies, and blends ignoring the transfer function. Pixels are
179 : * treated as if they are linear, regardless of their transfer function encoding.
180 : */
181 : kIgnore,
182 : };
183 :
184 : #endif
|