Euphoria
rgb.h
Go to the documentation of this file.
1 #pragma once
2 
3 
4 
5 #include "base/cint.h"
6 #include "base/colors.h"
7 #include "base/angle.h"
9 #include "base/default_parse.h"
10 
11 
12 namespace eu
13 {
14  // U8 colors: 0 - 255
15  struct Rgbi;
16  struct Rgbai;
17 
18  // float based colors: 0.0 - 1.0
19  struct Rgb;
20  struct Rgba;
21 
22 
24  // rgb no alpha support - int based
25  struct Rgbi
26  {
27  U8 r;
28  U8 g;
29  U8 b;
30 
31  constexpr Rgbi(U8 red, U8 green, U8 blue);
32  constexpr explicit Rgbi(U8 gray);
33  constexpr Rgbi(NamedColor color);
34  constexpr explicit Rgbi(const Rgb& c);
35 
36  [[nodiscard]] constexpr static Rgbi from_hex(unsigned int hex);
37  [[nodiscard]] constexpr int to_hex() const;
38  };
39 
40 
42  // rgb with alpha - int based
43 
44  struct Rgbai
45  {
46  U8 r;
47  U8 g;
48  U8 b;
49  U8 a;
50 
51  constexpr Rgbai(const Rgbi& c, U8 alpha = 255);
52  constexpr Rgbai(U8 red, U8 green, U8 blue, U8 alpha = 255);
53  constexpr Rgbai(U8 gray, U8 alpha = 255);
54  constexpr explicit Rgbai(const Rgba& c);
55  };
56 
57 
59  // rgb no alpha support - float based
60 
61  struct Rgb
62  {
63  float r;
64  float g;
65  float b;
66 
67  Rgb(float red, float green, float blue);
68  explicit Rgb(float gray);
69 
70  Rgb(NamedColor color);
71 
72  [[nodiscard]] static Rgb from_hex(unsigned int hex);
73  [[nodiscard]] float get_length() const;
74  [[nodiscard]] float get_length_squared() const;
75  [[nodiscard]] float calc_luminance() const;
76 
77  void operator+=(const Rgb& rhs);
78  void operator-=(const Rgb& rhs);
79  void operator/=(float rhs);
80 
81  // memberwise multiplication
82  void operator*=(const Rgb& rhs);
83 
84 
85  };
86 
87 
88  Rgb operator+(const Rgb& lhs, const Rgb& rhs);
89  Rgb operator-(const Rgb& lhs, const Rgb& rhs);
90 
91  // memberwise multiplication
92  Rgb operator*(const Rgb& lhs, const Rgb& rhs);
93  Rgb operator/(const Rgb& lhs, float rhs);
94  Rgb operator*(const Rgb& lhs, float rhs);
95  Rgb operator*(float lhs, const Rgb& rhs);
96  float dot(const Rgb& lhs, const Rgb& rhs);
97  Rgb clamp(const Rgb& r);
98 
99 
101  // HSL
102 
103  struct Hsl
104  {
105  // hue, saturation, lightness
106  Angle h; // the most noticeable color that stands out to your eye
107  float s; // the "brilliance" (0-1)
108  float l; // the light or darkness (0-1)
109 
110  // todo(Gustav): why are these angles and not a Hsl?
111  static constexpr Angle red = Angle::from_percent_of_360(0.0f);
112  static constexpr Angle yellow = Angle::from_percent_of_360(1 / 6.0f);
113  static constexpr Angle green = Angle::from_percent_of_360(2 / 6.0f);
114  static constexpr Angle cyan = Angle::from_percent_of_360(3 / 6.0f);
115  static constexpr Angle blue = Angle::from_percent_of_360(4 / 6.0f);
116  static constexpr Angle magenta = Angle::from_percent_of_360(5 / 6.0f);
117  };
118 
119  enum class IsAbsolute
120  {
121  yes,
122  no
123  };
124 
126  // Util functions
127 
128  Hsl get_saturated(const Hsl& ahsl, float amount, IsAbsolute method);
129  Hsl get_desaturated(const Hsl& ahsl, float amount, IsAbsolute method);
130  Hsl get_lightened(const Hsl& ahsl, float amount, IsAbsolute method);
131  Hsl get_darkened(const Hsl& ahsl, float amount, IsAbsolute method);
132 
136  Rgb get_shaded_color(const Rgb& color, float percentage);
137 
138 
140  // rgb with alpha - float based
141 
142  struct Rgba
143  {
144  float r;
145  float g;
146  float b;
147  float a;
148 
149  Rgba(float red, float green, float blue, float alpha = 1.0f);
150  Rgba(const Rgb& c, float alpha = 1.0f);
151  };
152 
153 
155  // For printing
156 
157  std::string to_string(const Rgbi& v);
158  std::string to_string(const Rgbai& v);
159  std::string to_string(const Rgb& v);
160  std::string to_string(const Rgba& v);
161  std::string to_string(const Hsl& v);
162 
163 
165  // Default compare
166 
167  bool operator==(const Rgbi& lhs, const Rgbi& rhs);
168  bool operator!=(const Rgbi& lhs, const Rgbi& rhs);
169 
170  bool operator==(const Rgbai& lhs, const Rgbai& rhs);
171  bool operator!=(const Rgbai& lhs, const Rgbai& rhs);
172 
174  // Convert functions (rgb)
175 
176  Rgb to_rgb(const Rgbi& c);
177  Rgb to_rgb(const Rgba& c);
178  Rgb to_rgb(const Rgbai& c);
179  Rgb to_rgb(const Hsl& c);
180 
181  // Convert functions (hsl)
182 
183  Hsl to_hsl(const Rgb& c);
184 
185  // Convert functions (rgbi)
186 
187  Rgbi to_rgbi(const Rgb& c);
188  Rgbi to_rgbi(const Rgba& c);
189  Rgbi to_rgbi(const Rgbai& c);
190 
191  // convert functions rgba
192  Rgba to_rgba(const Rgbai& c);
193  Rgbai to_rgbai(const Rgba& c);
194 
195 
197  // Transforms
198 
199  Rgb lerp_rgb(const Rgb& from, float v, const Rgb& to);
200 
202  // Printing/Exporting
203  std::string to_js_hex_color(const Rgbi& c);
204  std::string to_html_rgb(const Rgbi& c);
205 
206 
208  // Parsing
209  [[nodiscard]] Result<Rgbi> to_rgbi(const std::string& value);
210 
211 
213  // Internal utility
214 
215  namespace colorutil
216  {
217  // internal function, exposed for unit tests
218  constexpr U8 get_component(unsigned int i, unsigned int steps)
219  {
220  const auto bit_steps = 8 * steps;
221  const auto value = static_cast<int>((i >> bit_steps) & 0xff);
222  return static_cast<U8>(value);
223  }
224 
225  constexpr U8 get_red(unsigned int c)
226  {
227  return get_component(c, 2);
228  }
229 
230  constexpr U8 get_green(unsigned int c)
231  {
232  return get_component(c, 1);
233  }
234 
235  constexpr U8 get_blue(unsigned int c)
236  {
237  return get_component(c, 0);
238  }
239 
240  constexpr float to_float(U8 c)
241  {
242  return static_cast<float>(c) / 255.0f;
243  }
244 
245  constexpr U8 to_unsigned_char(float f)
246  {
247  return static_cast<U8>(static_cast<int>(f * 255.0f));
248  }
249 
250  constexpr unsigned int to_color_hex
251  (unsigned int r, unsigned int g, unsigned int b)
252  {
253  return ((r & 0xff) << 16) + ((g & 0xff) << 8) + (b & 0xff);
254  }
255 
256  constexpr
257  unsigned int
259  {
260  switch(color)
261  {
262  case NamedColor::white: return to_color_hex(255, 255, 255);
263  case NamedColor::light_gray: return to_color_hex(160, 160, 160);
264  case NamedColor::gray: return to_color_hex(127, 127, 127);
265  case NamedColor::dark_gray: return to_color_hex(87, 87, 87);
266  case NamedColor::black: return to_color_hex(0, 0, 0);
267  case NamedColor::red: return to_color_hex(173, 35, 35);
268  case NamedColor::pure_red: return to_color_hex(255, 0, 0);
269  case NamedColor::blue: return to_color_hex(42, 75, 215);
270  case NamedColor::pure_blue: return to_color_hex(0, 0, 255);
271  case NamedColor::light_blue: return to_color_hex(157, 175, 255);
272  case NamedColor::normal_blue: return to_color_hex(127, 127, 255);
273  case NamedColor::cornflower_blue: return to_color_hex(100, 149, 237);
274  case NamedColor::green: return to_color_hex(29, 105, 20);
275  case NamedColor::pure_green: return to_color_hex(0, 255, 0);
276  case NamedColor::light_green: return to_color_hex(129, 197, 122);
277  case NamedColor::yellow: return to_color_hex(255, 238, 51);
278  case NamedColor::pure_yellow: return to_color_hex(255, 255, 0);
279  case NamedColor::orange: return to_color_hex(255, 146, 51);
280  case NamedColor::pure_orange: return to_color_hex(255, 127, 0);
281  case NamedColor::brown: return to_color_hex(129, 74, 25);
282  case NamedColor::pure_brown: return to_color_hex(250, 75, 0);
283  case NamedColor::purple: return to_color_hex(129, 38, 192);
284  case NamedColor::pure_purple: return to_color_hex(128, 0, 128);
285  case NamedColor::pink: return to_color_hex(255, 205, 243);
286  case NamedColor::pure_pink: return to_color_hex(255, 192, 203);
287  case NamedColor::pure_beige: return to_color_hex(245, 245, 220);
288  case NamedColor::tan: return to_color_hex(233, 222, 187);
289  case NamedColor::pure_tan: return to_color_hex(210, 180, 140);
290  case NamedColor::cyan: return to_color_hex(41, 208, 208);
291  case NamedColor::pure_cyan: return to_color_hex(0, 255, 255);
292 
293  default: return to_color_hex(0, 0, 0);
294  }
295  }
296 
297 
298  constexpr
299  unsigned int
301  {
302  switch(color)
303  {
304  case BangWongPalette::black: return to_color_hex(0, 0, 0);
305  case BangWongPalette::organge: return to_color_hex(230, 159, 0);
306  case BangWongPalette::blue_sky: return to_color_hex(86, 180, 233);
307  case BangWongPalette::green_bluish: return to_color_hex(0, 158, 115);
308  case BangWongPalette::yellow: return to_color_hex(240, 228, 66);
309  case BangWongPalette::blue: return to_color_hex(0, 114, 178);
310  case BangWongPalette::red_vermillion: return to_color_hex(213, 94, 0);
311  case BangWongPalette::purple_redish: return to_color_hex(204, 121, 167);
312  default: return to_color_hex(0, 0, 0);
313  }
314  }
315 
316  unsigned int
317  from_string_to_hex(const std::string& str);
318  }
319 
320 
321 
322  // -----------------------------------------------------------------------
323  // implementation
324 
325  constexpr
326  Rgbi::Rgbi(U8 red, U8 green, U8 blue)
327  : r(red), g(green), b(blue)
328  {
329  }
330 
331 
332  constexpr
334  : r(gray), g(gray), b(gray)
335  {
336  }
337 
338 
339  constexpr
341  : Rgbi(Rgbi::from_hex(colorutil::to_color_hex(color)))
342  {
343  }
344 
345 
346  constexpr
347  Rgbi::Rgbi(const Rgb& c)
348  : r(colorutil::to_unsigned_char(c.r))
349  , g(colorutil::to_unsigned_char(c.g))
350  , b(colorutil::to_unsigned_char(c.b))
351  {}
352 
353 
354  [[nodiscard]] constexpr Rgbi
355  Rgbi::from_hex(unsigned int hex)
356  {
357  return
358  {
359  colorutil::get_red(hex),
362  };
363  }
364 
365 
366  constexpr
367  int
368  Rgbi::to_hex() const
369  {
370  const auto value = [](int i, int steps) -> int { return i << (8 * steps); };
371  return value(r, 2) | value(g, 1) | value(b, 0);
372  }
373 
374 
375  constexpr
376  Rgbai::Rgbai(const Rgbi& c, U8 alpha)
377  : r(c.r), g(c.g), b(c.b), a(alpha)
378  {
379  }
380 
381 
382  constexpr
383  Rgbai::Rgbai(U8 red, U8 green, U8 blue, U8 alpha)
384  : r(red), g(green), b(blue), a(alpha)
385  {
386  }
387 
388  constexpr
389  Rgbai::Rgbai(U8 gray, U8 alpha)
390  : r(gray), g(gray), b(gray), a(alpha)
391  {
392  }
393 
394 
395  constexpr
396  Rgbai::Rgbai(const Rgba& c)
397  : r(colorutil::to_unsigned_char(c.r))
398  , g(colorutil::to_unsigned_char(c.g))
399  , b(colorutil::to_unsigned_char(c.b))
400  , a(colorutil::to_unsigned_char(c.a))
401  {
402  }
403 
404 }
405 
406 namespace eu
407 {
408 
409  template<>
411  {
412  enum { value = 1 };
413 
414  static std::string to_string(const Rgbi& c)
415  {
416  return eu::to_string(c);
417  }
418 
419  static Result<Rgbi> parse(const std::string& value)
420  {
421  return to_rgbi(value);
422  }
423  };
424 
426 }
427 
constexpr unsigned int to_color_hex(unsigned int r, unsigned int g, unsigned int b)
Definition: rgb.h:251
constexpr U8 get_green(unsigned int c)
Definition: rgb.h:230
constexpr unsigned int to_color_hex(BangWongPalette color)
Definition: rgb.h:300
constexpr U8 get_component(unsigned int i, unsigned int steps)
Definition: rgb.h:218
constexpr float to_float(U8 c)
Definition: rgb.h:240
constexpr U8 to_unsigned_char(float f)
Definition: rgb.h:245
constexpr U8 get_red(unsigned int c)
Definition: rgb.h:225
constexpr U8 get_blue(unsigned int c)
Definition: rgb.h:235
unsigned int from_string_to_hex(const std::string &str)
Definition: assert.h:90
Rgbai to_rgbai(const Rgba &c)
Definition: rgb.cc:395
Angle operator+(const Angle &lhs, const Angle &rhs)
Definition: angle.cc:123
bool operator==(const Lrud< T > &lhs, const Lrud< T > &rhs)
Definition: lrud.h:75
Rgbi to_rgbi(const Rgb &c)
Definition: rgb.cc:352
BangWongPalette
Definition: colors.h:163
Angle operator-(const Angle &lhs, const Angle &rhs)
Definition: angle.cc:132
Hsl get_saturated(const Hsl &ahsl, float amount, IsAbsolute method)
Definition: rgb.cc:435
Angle operator/(const Angle &lhs, float rhs)
Definition: angle.cc:141
Hsl get_lightened(const Hsl &ahsl, float amount, IsAbsolute method)
Definition: rgb.cc:469
Rgb to_rgb(const Rgbi &c)
Definition: rgb.cc:229
std::string to_html_rgb(const Rgbi &c)
Definition: rgb.cc:427
NamedColor
Definition: colors.h:12
IsAbsolute
Definition: rgb.h:120
std::uint8_t U8
Definition: ints.h:15
std::string to_string(const Aabb &a)
Definition: aabb.cc:110
Hsl to_hsl(const Rgb &c)
Definition: rgb.cc:291
bool operator!=(const Lrud< T > &lhs, const Lrud< T > &rhs)
Definition: lrud.h:88
Rgb get_shaded_color(const Rgb &color, float percentage)
Makes a color brighter or darker.
Definition: rgb.cc:503
DEFAULT_INTERPOLATE(Angle, lerp_angle)
Rgba to_rgba(const Rgbai &c)
Definition: rgb.cc:381
Rgb lerp_rgb(const Rgb &from, float v, const Rgb &to)
Definition: rgb.cc:410
Hsl get_darkened(const Hsl &ahsl, float amount, IsAbsolute method)
Definition: rgb.cc:486
std::string to_js_hex_color(const Rgbi &c)
Definition: rgb.cc:422
Angle operator*(const Angle &lhs, float rhs)
Definition: angle.cc:149
float dot(const quatf &lhs, const quatf &rhs)
Definition: quat.cc:363
Rgb clamp(const Rgb &c)
Definition: rgb.cc:144
Hsl get_desaturated(const Hsl &ahsl, float amount, IsAbsolute method)
Definition: rgb.cc:452
ADD_DEFAULT_FORMATTER(eu::Rgbi, std::string, eu::to_string)
constexpr float from_percent_of_360() const
Definition: angle.h:56
Definition: rgb.h:104
static constexpr Angle green
Definition: rgb.h:113
static constexpr Angle blue
Definition: rgb.h:115
static constexpr Angle magenta
Definition: rgb.h:116
static constexpr Angle red
Definition: rgb.h:111
Angle h
Definition: rgb.h:106
float l
Definition: rgb.h:108
static constexpr Angle cyan
Definition: rgb.h:114
float s
Definition: rgb.h:107
static constexpr Angle yellow
Definition: rgb.h:112
Definition: rgb.h:62
void operator-=(const Rgb &rhs)
Definition: rgb.cc:62
void operator/=(float rhs)
Definition: rgb.cc:80
float calc_luminance() const
Definition: rgb.cc:46
Rgb(float red, float green, float blue)
Definition: rgb.cc:16
float b
Definition: rgb.h:65
float get_length_squared() const
Definition: rgb.cc:39
float g
Definition: rgb.h:64
static Rgb from_hex(unsigned int hex)
Definition: rgb.cc:23
void operator*=(const Rgb &rhs)
Definition: rgb.cc:71
float r
Definition: rgb.h:63
void operator+=(const Rgb &rhs)
Definition: rgb.cc:53
float get_length() const
Definition: rgb.cc:33
Definition: rgb.h:143
float r
Definition: rgb.h:144
Rgba(float red, float green, float blue, float alpha=1.0f)
Definition: rgb.cc:163
float a
Definition: rgb.h:147
float g
Definition: rgb.h:145
float b
Definition: rgb.h:146
Definition: rgb.h:45
U8 g
Definition: rgb.h:47
constexpr Rgbai(const Rgbi &c, U8 alpha=255)
Definition: rgb.h:376
U8 r
Definition: rgb.h:46
U8 b
Definition: rgb.h:48
U8 a
Definition: rgb.h:49
Definition: rgb.h:26
U8 b
Definition: rgb.h:29
constexpr int to_hex() const
Definition: rgb.h:368
U8 r
Definition: rgb.h:27
constexpr static Rgbi from_hex(unsigned int hex)
Definition: rgb.h:355
constexpr Rgbi(U8 red, U8 green, U8 blue)
Definition: rgb.h:326
U8 g
Definition: rgb.h:28
static std::string to_string(const Rgbi &c)
Definition: rgb.h:414
static Result< Rgbi > parse(const std::string &value)
Definition: rgb.h:419