1.10
color.h
1/*
2 * Copyright (C) 2018 Microchip Technology Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6#ifndef EGT_COLOR_H
7#define EGT_COLOR_H
8
14#include <array>
15#include <cmath>
16#include <cstdint>
17#include <egt/detail/math.h>
18#include <egt/detail/meta.h>
19#include <egt/detail/string.h>
20#include <initializer_list>
21#include <iosfwd>
22#include <map>
23#include <string>
24#include <utility>
25#include <vector>
26
27namespace egt
28{
29inline namespace v1
30{
31
40class EGT_API Color
41{
42public:
43
45 using RGBType = uint32_t;
47 using RGBAType = uint32_t;
49 using ComponentType = uint32_t;
50
51 constexpr Color() = default;
52
63 explicit constexpr Color(RGBAType c) noexcept
64 : m_rgba
65 {
66
67 (c >> 24u) & 0xffu,
68 (c >> 16u) & 0xffu,
69 (c >> 8u) & 0xffu,
70 c & 0xffu
71 }
72 {}
73
80 constexpr Color(const Color& color, ComponentType alpha) noexcept
81 : m_rgba
82 {
83 color.m_rgba[0],
84 color.m_rgba[1],
85 color.m_rgba[2],
86 alpha
87 }
88 {}
89
98 constexpr explicit Color(ComponentType r, ComponentType g, ComponentType b, ComponentType a = 255) noexcept
99 : m_rgba
100 {
101 r & 0xffu,
102 g & 0xffu,
103 b & 0xffu,
104 a & 0xffu
105 }
106 {}
107
109
110 EGT_NODISCARD constexpr float redf() const { return m_rgba[0] / 255.f; }
111 EGT_NODISCARD constexpr float greenf() const { return m_rgba[1] / 255.f; }
112 EGT_NODISCARD constexpr float bluef() const { return m_rgba[2] / 255.f; }
113 EGT_NODISCARD constexpr float alphaf() const { return m_rgba[3] / 255.f; }
115
117
118 constexpr void redf(float v) { m_rgba[0] = detail::clamp(v, 0.f, 1.f) * 255.f; }
119 constexpr void greenf(float v) { m_rgba[1] = detail::clamp(v, 0.f, 1.f) * 255.f; }
120 constexpr void bluef(float v) { m_rgba[2] = detail::clamp(v, 0.f, 1.f) * 255.f; }
121 constexpr void alphaf(float v) { m_rgba[3] = detail::clamp(v, 0.f, 1.f) * 255.f; }
123
125
126 EGT_NODISCARD constexpr ComponentType red() const { return assert(m_rgba[0] <= 255), m_rgba[0]; }
127 EGT_NODISCARD constexpr ComponentType green() const { return assert(m_rgba[1] <= 255), m_rgba[1]; }
128 EGT_NODISCARD constexpr ComponentType blue() const { return assert(m_rgba[2] <= 255), m_rgba[2]; }
129 EGT_NODISCARD constexpr ComponentType alpha() const { return assert(m_rgba[3] <= 255), m_rgba[3]; }
131
133
134 constexpr void red(ComponentType r) { m_rgba[0] = r & 0xffu; }
135 constexpr void green(ComponentType g) { m_rgba[1] = g & 0xffu; }
136 constexpr void blue(ComponentType b) { m_rgba[2] = b & 0xffu; }
137 constexpr void alpha(ComponentType a) { m_rgba[3] = a & 0xffu; }
139
141 EGT_NODISCARD constexpr uint16_t pixel16() const
142 {
143 const uint16_t b = (blue() >> 3u) & 0x1fu;
144 const uint16_t g = ((green() >> 2u) & 0x3fu) << 5u;
145 const uint16_t r = ((red() >> 3u) & 0x1fu) << 11u;
146
147 return static_cast<uint16_t>(r | g | b);
148 }
149
151 EGT_NODISCARD static constexpr Color pixel16(uint16_t c)
152 {
153 const uint16_t b = (c) & 0x1fu;
154 const uint16_t g = (c >> 5u) & 0x3fu;
155 const uint16_t r = (c >> 11u) & 0x1fu;
156
157 return Color(r, g, b, 0xffu);
158 }
159
161 EGT_NODISCARD constexpr RGBAType pixel24() const
162 {
163 return (red() << 16u) |
164 (green() << 8u) |
165 blue() |
166 (0xff);
167 }
168
170 EGT_NODISCARD static constexpr Color pixel24(RGBAType c)
171 {
172 return Color((c >> 16u) & 0xffu,
173 (c >> 8u) & 0xffu,
174 c & 0xffu,
175 0xffu);
176 }
177
179 EGT_NODISCARD constexpr RGBAType pixel32() const
180 {
181 return (red() << 16u) |
182 (green() << 8u) |
183 blue() |
184 (alpha() << 24u);
185 }
186
188 EGT_NODISCARD static constexpr Color pixel32(RGBAType c)
189 {
190 return Color((c >> 16u) & 0xffu,
191 (c >> 8u) & 0xffu,
192 c & 0xffu,
193 (c >> 24u) & 0xffu);
194 }
195
204 void get_hsvf(float& h, float& s, float& v, float* alpha = nullptr);
205
214 void get_hslf(float& h, float& s, float& l, float* alpha = nullptr);
215
224 void get_rgbaf(float& r, float& g, float& b, float* alpha = nullptr);
225
237 EGT_NODISCARD static constexpr Color rgb(RGBType c, ComponentType alpha = 255) noexcept
238 {
239 return Color(c << 8u | alpha);
240 }
241
250 EGT_NODISCARD static constexpr Color rgbaf(float r, float g, float b, float a = 1.0)
251 {
252 Color result;
253 result.redf(r);
254 result.greenf(g);
255 result.bluef(b);
256 result.alphaf(a);
257 return result;
258 }
259
272 EGT_NODISCARD static Color css(const std::string& hex)
273 {
274 return css(hex.c_str());
275 }
276
277 EGT_NODISCARD constexpr static Color css(const char* hex)
278 {
279 return Color((detail::hextoul(hex) << 8) | 0xff);
280 }
281
285 EGT_NODISCARD std::string hex() const;
286
295 EGT_NODISCARD static Color hsvf(float h, float s, float v, float alpha = 1.0);
296
305 EGT_NODISCARD static Color hslf(float h, float s, float l, float alpha = 1.0);
306
314 EGT_NODISCARD constexpr Color shade(float factor) const
315 {
316 return Color(red() * (1.0f - factor),
317 green() * (1.0f - factor),
318 blue() * (1.0f - factor),
319 alpha());
320 }
321
329 EGT_NODISCARD constexpr Color tint(float factor) const
330 {
331 return Color(red() + ((255 - red()) * factor),
332 green() + ((255 - green()) * factor),
333 blue() + ((255 - blue()) * factor),
334 alpha());
335 }
336
340 EGT_NODISCARD Color hue(float h) const
341 {
342 auto u = std::cos(h * detail::pi<float>() / 180.0f);
343 auto w = std::sin(h * detail::pi<float>() / 180.0f);
344
345 Color ret;
346 ret.red((0.299f + 0.701f * u + 0.168f * w) * red()
347 + (0.587f - 0.587f * u + 0.330f * w) * green()
348 + (0.114f - 0.114f * u - 0.497f * w) * blue());
349 ret.green((0.299f - 0.299f * u - 0.328f * w) * red()
350 + (0.587f + 0.413f * u + 0.035f * w) * green()
351 + (0.114f - 0.114f * u + 0.292f * w) * blue());
352 ret.blue((0.299f - 0.3f * u + 1.25f * w) * red()
353 + (0.587f - 0.588f * u - 1.05f * w) * green()
354 + (0.114f + 0.886f * u - 0.203f * w) * blue());
355 return ret;
356 }
357
369 {
370 m_rgba[0] = (c >> 24u) & 0xffu;
371 m_rgba[1] = (c >> 16u) & 0xffu;
372 m_rgba[2] = (c >> 8u) & 0xffu;
373 m_rgba[3] = c & 0xffu;
374
375 return *this;
376 }
377
379 template<class T>
380 constexpr Color operator+(T scalar) const
381 {
382 return Color::rgbaf(redf() + scalar,
383 greenf() + scalar,
384 bluef() + scalar,
385 alphaf() + scalar);
386 }
387
389 template<class T>
390 constexpr Color operator-(T scalar) const
391 {
392 return Color::rgbaf(redf() - scalar,
393 greenf() - scalar,
394 bluef() - scalar,
395 alphaf() - scalar);
396 }
397
399 template<class T>
400 constexpr Color operator*(T scalar) const
401 {
402 return Color::rgbaf(redf() * scalar,
403 greenf() * scalar,
404 bluef() * scalar,
405 alphaf() * scalar);
406 }
407
409 template<class T>
410 constexpr Color operator/(T scalar) const
411 {
412 return Color::rgbaf(redf() / scalar,
413 greenf() / scalar,
414 bluef() / scalar,
415 alphaf() / scalar);
416 }
417
419 constexpr Color operator+(const Color& rhs) const
420 {
421 return Color::rgbaf(redf() + rhs.redf(),
422 greenf() + rhs.greenf(),
423 bluef() + rhs.bluef(),
424 alphaf() + rhs.alphaf());
425 }
426
428 constexpr Color operator-(const Color& rhs) const
429 {
430 return Color::rgbaf(redf() - rhs.redf(),
431 greenf() - rhs.greenf(),
432 bluef() - rhs.bluef(),
433 alphaf() - rhs.alphaf());
434 }
435
437 Color operator*(const Color& rhs) const
438 {
439 return Color::rgbaf(redf() * rhs.redf(),
440 greenf() * rhs.greenf(),
441 bluef() * rhs.bluef(),
442 alphaf() * rhs.alphaf());
443 }
444
446 constexpr Color operator/(const Color& rhs) const
447 {
448 return Color::rgbaf(redf() / rhs.redf(),
449 greenf() / rhs.greenf(),
450 bluef() / rhs.bluef(),
451 alphaf() / rhs.alphaf());
452 }
453
461 static Color interp_hsv(const Color& a, const Color& b, float t);
462
470 static Color interp_hsl(const Color& a, const Color& b, float t);
471
482 static Color interp_rgba(const Color& a, const Color& b, float t);
483
484protected:
485
494 ComponentType m_rgba[4] {};
495};
496
497static_assert(detail::rule_of_5<Color>(), "must fulfill rule of 5");
498
500constexpr bool operator==(const Color& lhs, const Color& rhs)
501{
502 return lhs.red() == rhs.red() &&
503 lhs.green() == rhs.green() &&
504 lhs.blue() == rhs.blue() &&
505 lhs.alpha() == rhs.alpha();
506}
507
509constexpr bool operator!=(const Color& lhs, const Color& rhs)
510{
511 return !(lhs == rhs);
512}
513
515template<class T>
516constexpr Color operator+(T scalar, const Color& rhs)
517{
518 return Color::rgbaf(rhs.redf() + scalar,
519 rhs.greenf() + scalar,
520 rhs.bluef() + scalar,
521 rhs.alphaf() + scalar);
522}
523
525template<class T>
526constexpr Color operator-(T scalar, const Color& rhs)
527{
528 return Color::rgbaf(rhs.redf() - scalar,
529 rhs.greenf() - scalar,
530 rhs.bluef() - scalar,
531 rhs.alphaf() - scalar);
532}
533
535template<class T>
536constexpr Color operator*(T scalar, const Color& rhs)
537{
538 return Color::rgbaf(rhs.redf() * scalar,
539 rhs.greenf() * scalar,
540 rhs.bluef() * scalar,
541 rhs.alphaf() * scalar);
542}
543
545template<class T>
546constexpr Color operator/(T scalar, const Color& rhs)
547{
548 return Color::rgbaf(rhs.redf() / scalar,
549 rhs.greenf() / scalar,
550 rhs.bluef() / scalar,
551 rhs.alphaf() / scalar);
552}
553
555EGT_API std::ostream& operator<<(std::ostream& os, const Color& color);
556
557namespace experimental
558{
559
564class EGT_API ColorMap
565{
566public:
567
569 enum class Interpolation
570 {
571 rgba,
572 hsv,
573 hsl
574 };
575
577 using StepsArray = std::vector<Color>;
578
582 explicit ColorMap(Interpolation interp) noexcept
583 : m_interp(interp)
584 {}
585
590 explicit ColorMap(StepsArray steps, Interpolation interp = Interpolation::rgba)
591 : m_steps(std::move(steps)),
592 m_interp(interp)
593 {}
594
599 template<class T>
600 explicit ColorMap(std::initializer_list<T> steps, Interpolation interp = Interpolation::rgba)
601 : m_interp(interp)
602 {
603 m_steps.insert(m_steps.end(), steps.begin(), steps.end());
604 }
605
607 void step(const Color& color)
608 {
609 m_steps.emplace_back(color);
610 for (auto& x : m_cache)
611 x.clear();
612 }
613
615 void steps(const StepsArray& steps)
616 {
617 m_steps = steps;
618 for (auto& x : m_cache)
619 x.clear();
620 }
621
627 Color interp(float t) const;
628
637 Color interp_cached(float t, size_t accuracy = 1000) const;
638
640 const StepsArray& steps() const { return m_steps; }
641
643 bool empty() const { return m_steps.empty(); }
644
646 size_t count() const { return m_steps.size(); }
647
648protected:
649
652
654 mutable std::array<std::map<size_t, Color>, 3> m_cache{};
655
657 Interpolation m_interp{Interpolation::rgba};
658};
659
660}
661
662}
663}
664
665#endif
32 bit RGBA color.
Definition color.h:41
constexpr void red(ComponentType r)
Set RGBA component value individually from 0 to 255.
Definition color.h:134
constexpr Color operator-(T scalar) const
Color operator.
Definition color.h:390
EGT_NODISCARD constexpr ComponentType blue() const
Definition color.h:128
static EGT_NODISCARD constexpr Color pixel32(RGBAType c)
Create a Color from a 24 bit pixel representation.
Definition color.h:188
EGT_NODISCARD constexpr uint16_t pixel16() const
Get a 16 bit pixel representation of the Color.
Definition color.h:141
EGT_NODISCARD constexpr float greenf() const
Definition color.h:111
constexpr Color operator/(const Color &rhs) const
Color operator.
Definition color.h:446
constexpr void green(ComponentType g)
Definition color.h:135
EGT_NODISCARD constexpr Color tint(float factor) const
Create a tint (lighter) color based off this color given a factor.
Definition color.h:329
constexpr Color(ComponentType r, ComponentType g, ComponentType b, ComponentType a=255) noexcept
Create a color with the specified RGBA component values.
Definition color.h:98
EGT_NODISCARD static constexpr Color css(const char *hex)
Definition color.h:277
EGT_NODISCARD constexpr RGBAType pixel32() const
Get a 32 bit pixel representation of the Color.
Definition color.h:179
EGT_NODISCARD constexpr RGBAType pixel24() const
Get a 24 bit pixel representation of the Color.
Definition color.h:161
static EGT_NODISCARD Color css(const std::string &hex)
Create a Color with a hex CSS string.
Definition color.h:272
static EGT_NODISCARD constexpr Color pixel24(RGBAType c)
Create a Color from a 24 bit pixel representation.
Definition color.h:170
constexpr void bluef(float v)
Definition color.h:120
EGT_NODISCARD constexpr ComponentType red() const
Get RGBA component value as value from 0 to 255.
Definition color.h:126
Color operator*(const Color &rhs) const
Color operator.
Definition color.h:437
static EGT_NODISCARD constexpr Color rgbaf(float r, float g, float b, float a=1.0)
Create a color from float values.
Definition color.h:250
constexpr void blue(ComponentType b)
Definition color.h:136
static Color interp_hsl(const Color &a, const Color &b, float t)
Perform linear interpolation between two colors in the HSL color space.
EGT_NODISCARD constexpr ComponentType alpha() const
Definition color.h:129
constexpr Color operator+(const Color &rhs) const
Color operator.
Definition color.h:419
EGT_NODISCARD std::string hex() const
Return a string hex representation of the color.
constexpr void greenf(float v)
Definition color.h:119
constexpr void redf(float v)
Set RGBA component value as a float from 0.0 to 1.0.
Definition color.h:118
void get_hsvf(float &h, float &s, float &v, float *alpha=nullptr)
Get the hue, saturation, value, and alpha channel components of the color.
EGT_NODISCARD constexpr Color shade(float factor) const
Create a shade (darker) color based off this color given a factor.
Definition color.h:314
static Color interp_hsv(const Color &a, const Color &b, float t)
Perform linear interpolation between two colors in the HSV color space.
EGT_NODISCARD constexpr float bluef() const
Definition color.h:112
constexpr Color operator-(const Color &rhs) const
Color operator.
Definition color.h:428
EGT_NODISCARD constexpr float redf() const
Get RGBA component value as a float from 0.0 to 1.0.
Definition color.h:110
static EGT_NODISCARD Color hsvf(float h, float s, float v, float alpha=1.0)
Create a color from HSV values.
uint32_t RGBAType
Red/Green/Blue/Alpha type.
Definition color.h:47
Color & operator=(RGBAType c)
Assign an RGBA value.
Definition color.h:368
constexpr Color(const Color &color, ComponentType alpha) noexcept
Create a color from an existing color, but with the specified alpha value.
Definition color.h:80
static EGT_NODISCARD Color hslf(float h, float s, float l, float alpha=1.0)
Create a color from HSL values.
constexpr Color()=default
constexpr Color operator+(T scalar) const
Color operator.
Definition color.h:380
static Color interp_rgba(const Color &a, const Color &b, float t)
Perform linear interpolation between two colors in the RGB color space.
constexpr void alpha(ComponentType a)
Definition color.h:137
static EGT_NODISCARD constexpr Color pixel16(uint16_t c)
Create a Color from a 16 bit pixel representation.
Definition color.h:151
EGT_NODISCARD constexpr float alphaf() const
Definition color.h:113
EGT_NODISCARD Color hue(float h) const
Create a new color by applying a hue value.
Definition color.h:340
constexpr Color operator/(T scalar) const
Color operator.
Definition color.h:410
constexpr Color(RGBAType c) noexcept
Create a color with the specified RGBA value.
Definition color.h:63
EGT_NODISCARD constexpr ComponentType green() const
Definition color.h:127
void get_hslf(float &h, float &s, float &l, float *alpha=nullptr)
Get the hue, saturation, lightness, and alpha channel components of the color.
void get_rgbaf(float &r, float &g, float &b, float *alpha=nullptr)
Get the red, green, blue, and alpha channel components of the color.
constexpr Color operator*(T scalar) const
Color operator.
Definition color.h:400
constexpr void alphaf(float v)
Definition color.h:121
uint32_t RGBType
Red/Green/Blue type.
Definition color.h:45
uint32_t ComponentType
Single component of Red/Green/Blue/Alpha type.
Definition color.h:49
static EGT_NODISCARD constexpr Color rgb(RGBType c, ComponentType alpha=255) noexcept
Create a color from only a RGB value with separate alpha channel component.
Definition color.h:237
A ColorMap contains a series of sequential color steps that can be used for generating colors by inte...
Definition color.h:565
Color interp_cached(float t, size_t accuracy=1000) const
Get a color at the specified offset.
size_t count() const
Count the number of color steps.
Definition color.h:646
bool empty() const
Are there any color steps?
Definition color.h:643
std::vector< Color > StepsArray
Type used for color steps array.
Definition color.h:577
void steps(const StepsArray &steps)
Set the color steps.
Definition color.h:615
void step(const Color &color)
Append a color step.
Definition color.h:607
Interpolation
Interpolation color space method.
Definition color.h:570
ColorMap(StepsArray steps, Interpolation interp=Interpolation::rgba)
Definition color.h:590
ColorMap(Interpolation interp) noexcept
Definition color.h:582
const StepsArray & steps() const
Get a reference to the color steps array.
Definition color.h:640
Color interp(float t) const
Get a color at the specified offset.
StepsArray m_steps
Steps in the color map.
Definition color.h:651
ColorMap(std::initializer_list< T > steps, Interpolation interp=Interpolation::rgba)
Definition color.h:600
constexpr Color operator-(T scalar, const Color &rhs)
Color operator.
Definition color.h:526
constexpr bool operator!=(const Color &lhs, const Color &rhs)
Color operator.
Definition color.h:509
EGT_API std::ostream & operator<<(std::ostream &os, const Color &color)
Overloaded std::ostream insertion operator.
constexpr Color operator+(T scalar, const Color &rhs)
Color operator.
Definition color.h:516
constexpr Color operator/(T scalar, const Color &rhs)
Color operator.
Definition color.h:546
constexpr bool operator==(const Color &lhs, const Color &rhs)
Color operator.
Definition color.h:500
constexpr Color operator*(T scalar, const Color &rhs)
Color operator.
Definition color.h:536
EGT framework namespace.
Definition animation.h:24