1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "Prerequisites/BsPrerequisitesUtil.h"
6
7namespace bs
8{
9 /** @addtogroup Image
10 * @{
11 */
12
13 typedef UINT32 RGBA;
14 typedef UINT32 ARGB;
15 typedef UINT32 ABGR;
16 typedef UINT32 BGRA;
17
18 /**
19 * Color represented as 4 components, each being a floating point value ranging from 0 to 1. Color components are
20 * red, green, blue and alpha.
21 */
22 class BS_UTILITY_EXPORT Color
23 {
24 public:
25 static const Color ZERO;
26 static const Color Black;
27 static const Color White;
28 static const Color Red;
29 static const Color Green;
30 static const Color Blue;
31 static const Color LightGray;
32 static const Color BansheeOrange;
33
34 constexpr explicit Color(float red = 1.0f, float green = 1.0f, float blue = 1.0f, float alpha = 1.0f )
35 :r(red), g(green), b(blue), a(alpha)
36 { }
37
38 bool operator==(const Color& rhs) const;
39 bool operator!=(const Color& rhs) const;
40
41 /** Returns the color as a 32-bit value in RGBA order. */
42 RGBA getAsRGBA() const;
43
44 /** Returns the color as a 32-bit value in ARGB order. */
45 ARGB getAsARGB() const;
46
47 /** Returns the color as a 32-bit value in BGRA order. */
48 BGRA getAsBGRA() const;
49
50 /** Returns the color as a 32-bit value in ABGR order. */
51 ABGR getAsABGR() const;
52
53 /**
54 * Convert the current color to hue, saturation and brightness values.
55 *
56 * @param[in] hue Output hue value, scaled to the [0,1] range.
57 * @param[in] saturation Output saturation level, [0,1].
58 * @param[in] brightness Output brightness level, [0,1].
59 */
60 void getHSB(float* hue, float* saturation, float* brightness) const;
61
62 /** Clamps color value to the range [0, 1]. */
63 void saturate()
64 {
65 if (r < 0)
66 r = 0;
67 else if (r > 1)
68 r = 1;
69
70 if (g < 0)
71 g = 0;
72 else if (g > 1)
73 g = 1;
74
75 if (b < 0)
76 b = 0;
77 else if (b > 1)
78 b = 1;
79
80 if (a < 0)
81 a = 0;
82 else if (a > 1)
83 a = 1;
84 }
85
86 /** Clamps colour value to the range [0, 1]. Returned saturated color as a copy. */
87 Color saturateCopy() const
88 {
89 Color ret = *this;
90 ret.saturate();
91 return ret;
92 }
93
94 float operator[] (const UINT32 i) const
95 {
96 assert(i < 4);
97
98 return *(&r+i);
99 }
100
101 float& operator[] (const UINT32 i)
102 {
103 assert(i < 4);
104
105 return *(&r+i);
106 }
107
108 /** Pointer accessor for direct copying. */
109 float* ptr()
110 {
111 return &r;
112 }
113
114 /** Pointer accessor for direct copying. */
115 const float* ptr() const
116 {
117 return &r;
118 }
119
120 Color operator+ (const Color& rhs) const
121 {
122 return Color(r + rhs.r, g + rhs.g, b + rhs.b, a + rhs.a);
123 }
124
125 Color operator- (const Color& rhs) const
126 {
127 return Color(r - rhs.r, g - rhs.g, b - rhs.b, a - rhs.a);
128 }
129
130 Color operator* (float rhs) const
131 {
132 return Color(rhs * r, rhs * g, rhs * b, rhs * a);
133 }
134
135 Color operator* (const Color& rhs) const
136 {
137 return Color(rhs.r * r, rhs.g * g, rhs.b * b, rhs.a * a);
138 }
139
140 Color operator/ (const Color& rhs) const
141 {
142 return Color(r / rhs.r, g / rhs.g, b / rhs.b, a / rhs.a);
143 }
144
145 Color operator/ (float rhs) const
146 {
147 assert(rhs != 0.0f);
148 float invRhs = 1.0f / rhs;
149
150 return Color(r * invRhs, g * invRhs, b * invRhs, a * invRhs);
151 }
152
153 friend Color operator* (float lhs, const Color& rhs)
154 {
155 return Color(lhs * rhs.r, lhs * rhs.g, lhs * rhs.b, lhs * rhs.a);
156 }
157
158 Color& operator+= (const Color& rhs)
159 {
160 r += rhs.r;
161 g += rhs.g;
162 b += rhs.b;
163 a += rhs.a;
164
165 return *this;
166 }
167
168 Color& operator-= (const Color& rhs)
169 {
170 r -= rhs.r;
171 g -= rhs.g;
172 b -= rhs.b;
173 a -= rhs.a;
174
175 return *this;
176 }
177
178 Color& operator*= (float rhs)
179 {
180 r *= rhs;
181 g *= rhs;
182 b *= rhs;
183 a *= rhs;
184
185 return *this;
186 }
187
188 Color& operator/= (float rhs)
189 {
190 assert(rhs != 0.0f);
191
192 float invRhs = 1.0f / rhs;
193
194 r *= invRhs;
195 g *= invRhs;
196 b *= invRhs;
197 a *= invRhs;
198
199 return *this;
200 }
201
202 /** Creates a color value from a 32-bit value that encodes a RGBA color. */
203 static Color fromRGBA(RGBA val);
204
205 /** Creates a color value from a 32-bit value that encodes a ARGB color. */
206 static Color fromARGB(ARGB val);
207
208 /** Creates a color value from a 32-bit value that encodes a BGRA color. */
209 static Color fromBGRA(BGRA val);
210
211 /** Creates a color value from a 32-bit value that encodes a ABGR color. */
212 static Color fromABGR(ABGR val);
213
214 /**
215 * Creates a color value from hue, saturation and brightness.
216 *
217 * @param[in] hue Hue value, scaled to the [0,1] range.
218 * @param[in] saturation Saturation level, [0,1].
219 * @param[in] brightness Brightness level, [0,1].
220 */
221 static Color fromHSB(float hue, float saturation, float brightness);
222
223 /**
224 * Linearly interpolates between the two colors using @p t. t should be in [0, 1] range, where t = 0 corresponds
225 * to the left color, while t = 1 corresponds to the right color.
226 */
227 static Color lerp(float t, const Color& a, const Color& b);
228
229 /**
230 * Linearly interpolates between the two colors using @p t. t should be in [0, 255] range, where t = 0 corresponds
231 * to the left color, while t = 1 corresponds to the right color. Operates directly on 8-bit per channel
232 * encoded color instead of on floating point values.
233 */
234 static constexpr RGBA lerp(UINT8 t, RGBA from, RGBA to)
235 {
236 constexpr UINT32 RB_MASK = 0x00FF00FF;
237 constexpr UINT32 GA_MASK = 0xFF00FF00;
238
239 // Lerp two channels at a time (this leaves 8 extra bits for each channel for results)
240 //// Red-blue first
241 const UINT32 rbFrom = from & RB_MASK;
242 const UINT32 rbTo = to & RB_MASK;
243 const UINT32 rb = (rbFrom + (((rbTo - rbFrom) * t) >> 8)) & RB_MASK;
244
245 //// Then green-alpha
246 const UINT32 gaFrom = from & GA_MASK;
247 const UINT32 gaTo = to & GA_MASK;
248 const UINT32 ga = (((gaFrom >> 8) + ((((gaTo >> 8) - (gaFrom >> 8)) * t) >> 8)) << 8) & GA_MASK;
249
250 return rb | ga;
251 }
252
253 float r, g, b, a;
254 };
255
256 /** @cond SPECIALIZATIONS */
257 BS_ALLOW_MEMCPY_SERIALIZATION(Color);
258 /** @endcond */
259
260 /** @} */
261}
262
263/** @cond SPECIALIZATIONS */
264
265namespace std
266{
267/** Hash value generator for Color. */
268template<>
269struct hash<bs::Color>
270{
271 size_t operator()(const bs::Color& color) const
272 {
273 size_t hash = 0;
274 bs::bs_hash_combine(hash, color.r);
275 bs::bs_hash_combine(hash, color.g);
276 bs::bs_hash_combine(hash, color.b);
277 bs::bs_hash_combine(hash, color.a);
278
279 return hash;
280 }
281};
282}
283
284/** @endcond */
285