1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef COLORSPACE
17 #define COLORSPACE
18
19 #include <array>
20 #include <cfloat>
21 #include <cmath>
22 #include <map>
23 #include <utility>
24
25 #include "include/core/SkColorSpace.h"
26 #include "include/third_party/skcms/skcms.h"
27
28 namespace OHOS {
29 namespace ColorManager {
30 #define DIMES_3 3
31 #define DIMES_2 2
32
33 using Vector3 = std::array<float, DIMES_3>;
34 using Matrix3x3 = std::array<Vector3, DIMES_3>;
35 static constexpr float COLOR_EPSILON = 0.0018f; // 1/255/2 = 0.00196
36 static const std::array<float, DIMES_2> ILLUMINANT_D50_XY = {0.34567f, 0.35850f};
37 static const Vector3 ILLUMINANT_D50_XYZ = {0.964212f, 1.0f, 0.825188f};
38 static const Matrix3x3 BRADFORD = {{
39 {0.8951f, 0.2664f, -0.1614f},
40 {-0.7502f, 1.7135f, 0.0367f},
41 {0.0389f, -0.0685f, 1.0296f}}};
42 static const Matrix3x3 BRADFORD_INV = {{
43 {0.9869929f, -0.1470543f, 0.1599627f},
44 {0.4323053f, 0.5183603f, 0.0492912f},
45 {-0.0085287f, 0.0400428f, 0.9684867f},
46 }};
47
48 enum ColorSpaceName : uint32_t {
49 NONE = 0,
50 ADOBE_RGB = 1,
51 DCI_P3 = 2,
52 DISPLAY_P3 = 3,
53 SRGB = 4,
54 BT709 = 6,
55 BT601_EBU = 7,
56 BT601_SMPTE_C = 8,
57 BT2020_HLG = 9,
58 BT2020_PQ = 10,
59 P3_HLG = 11,
60 P3_PQ = 12,
61 ADOBE_RGB_LIMIT = 13,
62 DISPLAY_P3_LIMIT = 14,
63 SRGB_LIMIT = 15,
64 BT709_LIMIT = 16,
65 BT601_EBU_LIMIT = 17,
66 BT601_SMPTE_C_LIMIT = 18,
67 BT2020_HLG_LIMIT = 19,
68 BT2020_PQ_LIMIT = 20,
69 P3_HLG_LIMIT = 21,
70 P3_PQ_LIMIT = 22,
71 LINEAR_P3 = 23,
72 LINEAR_SRGB = 24,
73 LINEAR_BT709 = LINEAR_SRGB,
74 LINEAR_BT2020 = 25,
75 DISPLAY_SRGB = SRGB,
76 DISPLAY_P3_SRGB = DISPLAY_P3,
77 DISPLAY_P3_HLG = P3_HLG,
78 DISPLAY_P3_PQ = P3_PQ,
79 DISPLAY_BT2020_SRGB = 26,
80 DISPLAY_BT2020_HLG = BT2020_HLG,
81 DISPLAY_BT2020_PQ = BT2020_PQ,
82 BT2020 = 27,
83 NTSC_1953 = 28,
84 PRO_PHOTO_RGB = 29,
85 ACES = 30,
86 ACESCG = 31,
87 CIE_LAB = 32,
88 CIE_XYZ = 33,
89 EXTENDED_SRGB = 34,
90 LINEAR_EXTENDED_SRGB = 35,
91 SMPTE_C = 36,
92 CUSTOM = 5,
93 };
94
95 enum GamutMappingMode : uint32_t {
96 GAMUT_MAP_CONSTANT = 0,
97 GAMUT_MAP_EXPENSION,
98 GAMUT_MAP_HDR_CONSTANT,
99 GAMUT_MAP_HDR_EXPENSION,
100 };
101
102 struct ColorSpacePrimaries {
103 float rX;
104 float rY;
105 float gX;
106 float gY;
107 float bX;
108 float bY;
109 float wX;
110 float wY;
111 };
112
113 struct TransferFunc {
114 float g;
115 float a;
116 float b;
117 float c;
118 float d;
119 float e;
120 float f;
121 };
122
123 Matrix3x3 operator*(const Matrix3x3& a, const Matrix3x3& b);
124
125 Vector3 operator*(const Vector3& x, const Matrix3x3& a);
126
127 Vector3 operator*(const Matrix3x3& a, const Vector3& x);
128
129 Matrix3x3 operator/(const Vector3& a, const Vector3& b);
130
131 Matrix3x3 Invert(const Matrix3x3& src);
132
XYZ(const Vector3 & xyY)133 inline Vector3 XYZ(const Vector3& xyY)
134 {
135 return Vector3 {(xyY[0] * xyY[2]) / xyY[1], xyY[2],
136 ((1 - xyY[0] - xyY[1]) * xyY[2]) / xyY[1]};
137 }
138
FloatEqual(const float src,const float dst)139 inline bool FloatEqual(const float src, const float dst)
140 {
141 return fabs(src - dst) < COLOR_EPSILON;
142 }
143
ComputeWhitePoint(Matrix3x3 & toXYZ)144 inline std::array<float, DIMES_2> ComputeWhitePoint(Matrix3x3 &toXYZ)
145 {
146 Vector3 w = toXYZ * Vector3 {1.0f};
147 float sumW = w[0] + w[1] + w[2];
148 return {{w[0] / sumW, w[1] / sumW}};
149 }
150
SkToXYZToMatrix3(const skcms_Matrix3x3 & skToXYZ)151 inline Matrix3x3 SkToXYZToMatrix3(const skcms_Matrix3x3 &skToXYZ)
152 {
153 return {{{skToXYZ.vals[0][0], skToXYZ.vals[0][1], skToXYZ.vals[0][2]},
154 {skToXYZ.vals[1][0], skToXYZ.vals[1][1], skToXYZ.vals[1][2]},
155 {skToXYZ.vals[2][0], skToXYZ.vals[2][1], skToXYZ.vals[2][2]}}};
156 }
157
158 // Compute a toXYZD50 matrix from a given rgb and white point
159 Matrix3x3 ComputeXYZD50(const ColorSpacePrimaries& primaries);
160
161 // Convert toXYZ to toXYZD50 matrix with its white point
162 Matrix3x3 DXToD50(const Matrix3x3 &toXYZ, const std::array<float, DIMES_2> &wp);
163
164 class ColorSpace {
165 public:
166 ColorSpace(ColorSpaceName name);
167
168 ColorSpace(const ColorSpacePrimaries &primaries, const TransferFunc &transferFunc);
169
170 ColorSpace(const ColorSpacePrimaries &primaries, float gamma);
171
172 ColorSpace(const Matrix3x3& toXYZ, const std::array<float, 2> &whitePoint, const TransferFunc& transferFunc);
173
174 ColorSpace(const Matrix3x3& toXYZ, const std::array<float, 2>& whitePoint, float gamma);
175
176 // convert SKColorSpace to OHOS ColorSpce
177 ColorSpace(const sk_sp<SkColorSpace> src, ColorSpaceName name = ColorSpaceName::CUSTOM);
178
179 ColorSpace(const skcms_ICCProfile& srcIcc, ColorSpaceName name = ColorSpaceName::CUSTOM);
180
GetColorSpaceName()181 ColorSpaceName GetColorSpaceName() const
182 {
183 return colorSpaceName;
184 }
185
GetRGBToXYZ()186 Matrix3x3 GetRGBToXYZ() const
187 {
188 return toXYZ;
189 }
190
GetXYZToRGB()191 Matrix3x3 GetXYZToRGB() const
192 {
193 auto toRGB = Invert(toXYZ);
194 return toRGB;
195 }
196
GetWhitePoint()197 std::array<float, DIMES_2> GetWhitePoint() const
198 {
199 return whitePoint;
200 }
201
GetGamma()202 float GetGamma() const
203 {
204 return transferFunc.g;
205 }
206
207 Vector3 ToLinear(Vector3 color) const;
208 Vector3 ToNonLinear(Vector3 color) const;
209
210 // convert OHOS ColorSpce to SKColorSpace
211 sk_sp<SkColorSpace> ToSkColorSpace() const;
212
213 float clampMin = 0.0f;
214 float clampMax = 1.0f;
215
216 private:
217 skcms_Matrix3x3 ToSkiaXYZ() const;
218
219 ColorSpaceName colorSpaceName = ColorSpaceName::SRGB;
220 Matrix3x3 toXYZ;
221 std::array<float, DIMES_2> whitePoint;
222 TransferFunc transferFunc = {};
223 };
224 } // namespace ColorSpace
225 } // namespace OHOS
226 #endif // COLORSPACE
227