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