• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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 private:
168     SkColorSpace() = default;
169     friend class SkColorSpace_Base;
170 
171     using INHERITED = SkRefCnt;
172 };
173 
174 enum class SkTransferFunctionBehavior {
175     /**
176      *  Converts to a linear space before premultiplying, unpremultiplying, or blending.
177      */
178     kRespect,
179 
180     /**
181      *  Premultiplies, unpremultiplies, and blends ignoring the transfer function.  Pixels are
182      *  treated as if they are linear, regardless of their transfer function encoding.
183      */
184     kIgnore,
185 };
186 
187 #endif
188