1 /*
2 * Copyright (c) 2021-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 #include "common/rs_color.h"
17
18 #include <algorithm>
19 #include <iomanip>
20 #include <sstream>
21
22 #ifndef ROSEN_CROSS_PLATFORM
23 #include "color_space_convertor.h"
24 #endif
25 #include "common/rs_common_def.h"
26
27 namespace OHOS {
28 namespace Rosen {
RSColor(uint32_t rgba)29 RSColor::RSColor(uint32_t rgba) noexcept
30 {
31 alpha_ = static_cast<int16_t>(rgba & 0xFF); // 0xff byte mask
32 red_ = static_cast<int16_t>((rgba & 0xFF000000) >> 24); // 0xff000000 red mask, 24 red shift
33 green_ = static_cast<int16_t>((rgba & 0x00FF0000) >> 16); // 0x00ff0000 green mask, 16 green shift
34 blue_ = static_cast<int16_t>((rgba & 0x0000FF00) >> 8); // 0x0000ff00 blue mask, 8 blue shift
35 }
36
RSColor(int16_t red,int16_t green,int16_t blue)37 RSColor::RSColor(int16_t red, int16_t green, int16_t blue) noexcept : RSColor(red, green, blue, UINT8_MAX) {}
38
RSColor(int16_t red,int16_t green,int16_t blue,int16_t alpha,GraphicColorGamut colorSpace)39 RSColor::RSColor(int16_t red, int16_t green, int16_t blue, int16_t alpha, GraphicColorGamut colorSpace) noexcept
40 {
41 alpha_ = alpha;
42 red_ = red;
43 green_ = green;
44 blue_ = blue;
45 colorSpace_ = colorSpace;
46 }
47
operator ==(const RSColor & rhs) const48 bool RSColor::operator==(const RSColor& rhs) const
49 {
50 return red_ == rhs.red_ && green_ == rhs.green_ && blue_ == rhs.blue_ && alpha_ == rhs.alpha_ &&
51 colorSpace_ == rhs.colorSpace_;
52 }
53
IsNearEqual(const RSColor & other,int16_t threshold) const54 bool RSColor::IsNearEqual(const RSColor& other, int16_t threshold) const
55 {
56 return (std::abs(red_ - other.red_) <= threshold) && (std::abs(green_ - other.green_) <= threshold) &&
57 (std::abs(blue_ - other.blue_) <= threshold) && (std::abs(alpha_ - other.alpha_) <= threshold) &&
58 (colorSpace_ == other.colorSpace_);
59 }
60
operator +(const RSColor & rhs) const61 RSColor RSColor::operator+(const RSColor& rhs) const
62 {
63 return RSColor(red_ + rhs.red_, green_ + rhs.green_, blue_ + rhs.blue_, alpha_ + rhs.alpha_, rhs.colorSpace_);
64 }
65
operator -(const RSColor & rhs) const66 RSColor RSColor::operator-(const RSColor& rhs) const
67 {
68 return RSColor(red_ - rhs.red_, green_ - rhs.green_, blue_ - rhs.blue_, alpha_ - rhs.alpha_, rhs.colorSpace_);
69 }
70
operator *(float scale) const71 RSColor RSColor::operator*(float scale) const
72 {
73 return RSColor(round(red_ * scale), round(green_ * scale), round(blue_ * scale), round(alpha_ * scale));
74 }
75
operator *=(float scale)76 RSColor& RSColor::operator*=(float scale)
77 {
78 red_ = round(red_ * scale);
79 green_ = round(green_ * scale);
80 blue_ = round(blue_ * scale);
81 alpha_ = round(alpha_ * scale);
82 return *this;
83 }
84
operator /(float scale) const85 RSColor RSColor::operator/(float scale) const
86 {
87 if (ROSEN_EQ<float>(scale, 0)) {
88 return *this;
89 }
90 return operator*(1 / scale);
91 }
92
AsRgbaInt() const93 uint32_t RSColor::AsRgbaInt() const
94 {
95 return (static_cast<uint32_t>(std::clamp<int16_t>(alpha_, 0, UINT8_MAX))) |
96 ((static_cast<uint32_t>(std::clamp<int16_t>(red_, 0, UINT8_MAX))) << 24) | // 24 red shift
97 ((static_cast<uint32_t>(std::clamp<int16_t>(green_, 0, UINT8_MAX))) << 16) | // 16 green shift
98 ((static_cast<uint32_t>(std::clamp<int16_t>(blue_, 0, UINT8_MAX))) << 8); // 8 blue shift
99 }
100
FromRgbaInt(uint32_t rgba)101 RSColor RSColor::FromRgbaInt(uint32_t rgba)
102 {
103 return RSColor(rgba);
104 }
105
AsArgbInt() const106 uint32_t RSColor::AsArgbInt() const
107 {
108 return ((static_cast<uint32_t>(std::clamp<int16_t>(alpha_, 0, UINT8_MAX))) << 24) | // 24 alpha shift
109 ((static_cast<uint32_t>(std::clamp<int16_t>(red_, 0, UINT8_MAX))) << 16) | // 16 red shift
110 ((static_cast<uint32_t>(std::clamp<int16_t>(green_, 0, UINT8_MAX))) << 8) | // 8 green shift
111 (static_cast<uint32_t>(std::clamp<int16_t>(blue_, 0, UINT8_MAX)));
112 }
113
FromArgbInt(uint32_t argb)114 RSColor RSColor::FromArgbInt(uint32_t argb)
115 {
116 uint32_t alpha = (argb >> 24) & 0xFF; // 24 is alpha shift in ARGB, 0xFF is a byte mask
117 return RSColor(((argb << 8) & 0xFFFFFF00) | alpha); // 8 is rgb shift, 0xFFFFFF00 is a rgb mask
118 }
119
AsBgraInt() const120 uint32_t RSColor::AsBgraInt() const
121 {
122 return (static_cast<uint32_t>(std::clamp<int16_t>(alpha_, 0, UINT8_MAX))) |
123 ((static_cast<uint32_t>(std::clamp<int16_t>(red_, 0, UINT8_MAX))) << 8) | // 8 red shift
124 ((static_cast<uint32_t>(std::clamp<int16_t>(green_, 0, UINT8_MAX))) << 16) | // 16 green shift
125 ((static_cast<uint32_t>(std::clamp<int16_t>(blue_, 0, UINT8_MAX))) << 24); // 24 blue shift
126 }
127
FromBgraInt(uint32_t bgra)128 RSColor RSColor::FromBgraInt(uint32_t bgra)
129 {
130 union {
131 struct {
132 uint8_t blu_ : 8;
133 uint8_t gre_ : 8;
134 uint8_t red_ : 8;
135 uint8_t alp_ : 8;
136 };
137 uint32_t bgra_;
138 } color;
139 color.bgra_ = bgra;
140 return RSColor(color.red_, color.gre_, color.blu_, color.alp_);
141 }
142
GetBlue() const143 int16_t RSColor::GetBlue() const
144 {
145 return blue_;
146 }
147
GetGreen() const148 int16_t RSColor::GetGreen() const
149 {
150 return green_;
151 }
152
GetRed() const153 int16_t RSColor::GetRed() const
154 {
155 return red_;
156 }
157
GetAlpha() const158 int16_t RSColor::GetAlpha() const
159 {
160 return alpha_;
161 }
162
GetRedF() const163 scalar RSColor::GetRedF() const
164 {
165 return static_cast<scalar>(red_) / RGB_MAX_VALUE;
166 }
167
GetGreenF() const168 scalar RSColor::GetGreenF() const
169 {
170 return static_cast<scalar>(green_) / RGB_MAX_VALUE;
171 }
172
GetBlueF() const173 scalar RSColor::GetBlueF() const
174 {
175 return static_cast<scalar>(blue_) / RGB_MAX_VALUE;
176 }
177
GetAlphaF() const178 scalar RSColor::GetAlphaF() const
179 {
180 return static_cast<scalar>(alpha_) / RGB_MAX_VALUE;
181 }
182
GetColor4f() const183 Drawing::Color4f RSColor::GetColor4f() const
184 {
185 Drawing::Color4f color4f;
186 color4f.redF_ = GetRedF();
187 color4f.greenF_ = GetGreenF();
188 color4f.blueF_ = GetBlueF();
189 color4f.alphaF_ = GetAlphaF();
190 return color4f;
191 }
192
GetColorSpace() const193 GraphicColorGamut RSColor::GetColorSpace() const
194 {
195 return colorSpace_;
196 }
197
SetBlue(int16_t blue)198 void RSColor::SetBlue(int16_t blue)
199 {
200 blue_ = blue;
201 }
202
SetGreen(int16_t green)203 void RSColor::SetGreen(int16_t green)
204 {
205 green_ = green;
206 }
207
SetRed(int16_t red)208 void RSColor::SetRed(int16_t red)
209 {
210 red_ = red;
211 }
212
SetAlpha(int16_t alpha)213 void RSColor::SetAlpha(int16_t alpha)
214 {
215 alpha_ = alpha;
216 }
217
SetColorSpace(const GraphicColorGamut colorSpace)218 void RSColor::SetColorSpace(const GraphicColorGamut colorSpace)
219 {
220 colorSpace_ = colorSpace;
221 }
222
MultiplyAlpha(float alpha)223 void RSColor::MultiplyAlpha(float alpha)
224 {
225 alpha_ = static_cast<int16_t>(alpha_ * std::clamp(alpha, 0.0f, 1.0f));
226 }
227
ConvertToP3ColorSpace()228 void RSColor::ConvertToP3ColorSpace()
229 {
230 #ifndef ROSEN_CROSS_PLATFORM
231 if (colorSpace_ == GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DISPLAY_P3) {
232 return;
233 }
234 OHOS::ColorManager::Vector3 rgbF = {GetRedF(), GetGreenF(), GetBlueF()};
235 auto rgbInP3 = OHOS::ColorManager::ColorSpaceConvertor::ConvertSRGBToP3ColorSpace(rgbF);
236 red_ = static_cast<int16_t>(round(rgbInP3[COLOR_ARRAY_RED_INDEX] * RGB_MAX_VALUE));
237 green_ = static_cast<int16_t>(round(rgbInP3[COLOR_ARRAY_GREEN_INDEX] * RGB_MAX_VALUE));
238 blue_ = static_cast<int16_t>(round(rgbInP3[COLOR_ARRAY_BLUE_INDEX] * RGB_MAX_VALUE));
239 colorSpace_ = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DISPLAY_P3;
240 #endif
241 }
242
ConvertToSRGBColorSpace()243 void RSColor::ConvertToSRGBColorSpace()
244 {
245 #ifndef ROSEN_CROSS_PLATFORM
246 if (colorSpace_ == GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB) {
247 return;
248 }
249 OHOS::ColorManager::Vector3 rgbF = {GetRedF(), GetGreenF(), GetBlueF()};
250 auto rgbInSRGB = OHOS::ColorManager::ColorSpaceConvertor::ConvertP3ToSRGBColorSpace(rgbF);
251 red_ = static_cast<int16_t>(round(rgbInSRGB[COLOR_ARRAY_RED_INDEX] * RGB_MAX_VALUE));
252 green_ = static_cast<int16_t>(round(rgbInSRGB[COLOR_ARRAY_GREEN_INDEX] * RGB_MAX_VALUE));
253 blue_ = static_cast<int16_t>(round(rgbInSRGB[COLOR_ARRAY_BLUE_INDEX] * RGB_MAX_VALUE));
254 colorSpace_ = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB;
255 #endif
256 }
257
Dump(std::string & out) const258 void RSColor::Dump(std::string& out) const
259 {
260 constexpr int32_t colorStrWidth = 8;
261 std::stringstream ss;
262 ss << "[RGBA-0x" << std::hex << std::setfill('0') << std::setw(colorStrWidth) << std::uppercase;
263 ss << AsRgbaInt() << ',';
264 out += ss.str();
265 switch (colorSpace_) {
266 case GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB:
267 out += " colorSpace: SRGB]";
268 break;
269 case GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DISPLAY_P3:
270 out += " colorSpace: DISPLAY_P3]";
271 break;
272 default:
273 out += " colorSpace: OTHER]";
274 break;
275 }
276 }
277 } // namespace Rosen
278 } // namespace OHOS
279