• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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     ACES,
51     ACESCG,
52     ADOBE_RGB,
53     BT2020,
54     BT709,
55     CIE_LAB,
56     CIE_XYZ,
57     DCI_P3,
58     DISPLAY_P3,
59     EXTENDED_SRGB,
60     LINEAR_EXTENDED_SRGB,
61     LINEAR_SRGB,
62     NTSC_1953,
63     PRO_PHOTO_RGB,
64     SMPTE_C,
65     SRGB,
66     CUSTOM,
67 };
68 
69 enum GamutMappingMode : uint32_t {
70     GAMUT_MAP_CONSTANT = 0,
71     GAMUT_MAP_EXPENSION,
72     GAMUT_MAP_HDR_CONSTANT,
73     GAMUT_MAP_HDR_EXPENSION,
74 };
75 
76 struct ColorSpacePrimaries {
77     float rX;
78     float rY;
79     float gX;
80     float gY;
81     float bX;
82     float bY;
83     float wX;
84     float wY;
85 };
86 
87 struct TransferFunc {
88     float g;
89     float a;
90     float b;
91     float c;
92     float d;
93     float e;
94     float f;
95 };
96 
97 Matrix3x3 operator*(const Matrix3x3& a, const Matrix3x3& b);
98 
99 Vector3 operator*(const Vector3& x, const Matrix3x3& a);
100 
101 Vector3 operator*(const Matrix3x3& a, const Vector3& x);
102 
103 Matrix3x3 operator/(const Vector3& a, const Vector3& b);
104 
105 Matrix3x3 Invert(const Matrix3x3& src);
106 
XYZ(const Vector3 & xyY)107 inline Vector3 XYZ(const Vector3& xyY)
108 {
109     return Vector3 {(xyY[0] * xyY[2]) / xyY[1], xyY[2],
110         ((1 - xyY[0] - xyY[1]) * xyY[2]) / xyY[1]};
111 }
112 
FloatEqual(const float src,const float dst)113 inline bool FloatEqual(const float src, const float dst)
114 {
115     return fabs(src - dst) < COLOR_EPSILON;
116 }
117 
ComputeWhitePoint(Matrix3x3 & toXYZ)118 inline std::array<float, DIMES_2> ComputeWhitePoint(Matrix3x3 &toXYZ)
119 {
120     Vector3 w = toXYZ * Vector3 {1.0f};
121     float sumW = w[0] + w[1] + w[2];
122     return {{w[0] / sumW, w[1] / sumW}};
123 }
124 
SkToXYZToMatrix3(const skcms_Matrix3x3 & skToXYZ)125 inline Matrix3x3 SkToXYZToMatrix3(const skcms_Matrix3x3 &skToXYZ)
126 {
127     return {{{skToXYZ.vals[0][0], skToXYZ.vals[0][1], skToXYZ.vals[0][2]},
128         {skToXYZ.vals[1][0], skToXYZ.vals[1][1], skToXYZ.vals[1][2]},
129         {skToXYZ.vals[2][0], skToXYZ.vals[2][1], skToXYZ.vals[2][2]}}};
130 }
131 
132 // Compute a toXYZD50 matrix from a given rgb and white point
133 Matrix3x3 ComputeXYZD50(const ColorSpacePrimaries& primaries);
134 
135 // Convert toXYZ to toXYZD50 matrix with its white point
136 Matrix3x3 DXToD50(const Matrix3x3 &toXYZ, const std::array<float, DIMES_2> &wp);
137 
138 class ColorSpace {
139 public:
140     ColorSpace(ColorSpaceName name);
141 
142     ColorSpace(const ColorSpacePrimaries &primaries, const TransferFunc &transferFunc);
143 
144     ColorSpace(const ColorSpacePrimaries &primaries, float gamma);
145 
146     ColorSpace(const Matrix3x3& toXYZ, const std::array<float, 2> &whitePoint, const TransferFunc& transferFunc);
147 
148     ColorSpace(const Matrix3x3& toXYZ, const std::array<float, 2>& whitePoint, float gamma);
149 
150     // convert SKColorSpace to OHOS ColorSpce
151     ColorSpace(const sk_sp<SkColorSpace> src, ColorSpaceName name = ColorSpaceName::CUSTOM);
152 
153     ColorSpace(const skcms_ICCProfile& srcIcc, ColorSpaceName name = ColorSpaceName::CUSTOM);
154 
GetColorSpaceName()155     ColorSpaceName GetColorSpaceName() const
156     {
157         return colorSpaceName;
158     }
159 
GetRGBToXYZ()160     Matrix3x3 GetRGBToXYZ() const
161     {
162         return toXYZ;
163     }
164 
GetXYZToRGB()165     Matrix3x3 GetXYZToRGB() const
166     {
167         auto toRGB = Invert(toXYZ);
168         return toRGB;
169     }
170 
GetWhitePoint()171     std::array<float, DIMES_2> GetWhitePoint() const
172     {
173         return whitePoint;
174     }
175 
GetGamma()176     float GetGamma() const
177     {
178         return transferFunc.g;
179     }
180 
181     Vector3 ToLinear(Vector3 color) const;
182     Vector3 ToNonLinear(Vector3 color) const;
183 
184     // convert OHOS ColorSpce to SKColorSpace
185     sk_sp<SkColorSpace> ToSkColorSpace() const;
186 
187     float clampMin = 0.0f;
188     float clampMax = 1.0f;
189 
190 private:
191     skcms_Matrix3x3 ToSkiaXYZ() const;
192 
193     ColorSpaceName colorSpaceName = ColorSpaceName::SRGB;
194     Matrix3x3 toXYZ;
195     std::array<float, DIMES_2> whitePoint;
196     TransferFunc transferFunc = {};
197 };
198 } // namespace ColorSpace
199 } // namespace OHOS
200 #endif  // COLORSPACE
201