• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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