Lamp-Da 0.1
A compact lantern project
Loading...
Searching...
No Matches
utils.hpp
Go to the documentation of this file.
1
5#ifndef MODES_COLORS_UTILS_HPP
6#define MODES_COLORS_UTILS_HPP
7
9
10#include "src/system/ext/scale8.h"
11#include "src/system/ext/math8.h"
12
13#include <cstdint>
14
15//
16// Color utilities likely already defined elsewhere
17// (but this time in pure constexpr-able INLINE c++)
18//
19
21namespace lampda::modes::colors {
22
24static constexpr LMBD_INLINE uint32_t fromRGB(uint8_t r, uint8_t g, uint8_t b)
25{
26 uint32_t rx = r;
27 uint32_t gx = g;
28 return (rx << 16) | (gx << 8) | b;
29}
30
32struct ToRGB
33{
35 constexpr LMBD_INLINE ToRGB(uint32_t color) :
36 r {(uint8_t)((color >> 16) & 0xff)},
37 g {(uint8_t)((color >> 8) & 0xff)},
38 b {(uint8_t)(color & 0xff)}
39 {
40 }
41
42 uint8_t r;
43 uint8_t g;
44 uint8_t b;
45};
46
48static constexpr LMBD_INLINE uint32_t fromGrey(uint32_t w) { return fromRGB(w, w, w); }
49
51static constexpr uint8_t colorRotation[360] = {
52 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 15, 17, 18,
53 20, 22, 24, 26, 28, 30, 32, 35, 37, 39, 42, 44, 47, 49, 52, 55, 58, 60, 63, 66, 69, 72,
54 75, 78, 81, 85, 88, 91, 94, 97, 101, 104, 107, 111, 114, 117, 121, 124, 127, 131, 134, 137, 141, 144,
55 147, 150, 154, 157, 160, 163, 167, 170, 173, 176, 179, 182, 185, 188, 191, 194, 197, 200, 202, 205, 208, 210,
56 213, 215, 217, 220, 222, 224, 226, 229, 231, 232, 234, 236, 238, 239, 241, 242, 244, 245, 246, 248, 249, 250,
57 251, 251, 252, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 253, 252, 251, 251, 250,
58 249, 248, 246, 245, 244, 242, 241, 239, 238, 236, 234, 232, 231, 229, 226, 224, 222, 220, 217, 215, 213, 210,
59 208, 205, 202, 200, 197, 194, 191, 188, 185, 182, 179, 176, 173, 170, 167, 163, 160, 157, 154, 150, 147, 144,
60 141, 137, 134, 131, 127, 124, 121, 117, 114, 111, 107, 104, 101, 97, 94, 91, 88, 85, 81, 78, 75, 72,
61 69, 66, 63, 60, 58, 55, 52, 49, 47, 44, 42, 39, 37, 35, 32, 30, 28, 26, 24, 22, 20, 18,
62 17, 15, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0,
63 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
65 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
66 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
67 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
68 0, 0, 0, 0, 0, 0, 0, 0};
69
71static constexpr LMBD_INLINE uint32_t fromAngleHue(uint16_t angleDegrees)
72{
73 uint8_t r = colorRotation[(angleDegrees + 120) % 360];
74 uint8_t g = colorRotation[angleDegrees % 360];
75 uint8_t b = colorRotation[(angleDegrees + 240) % 360];
76 return fromRGB(r, g, b);
77}
78
88template<typename UIntTy = uint8_t>
89static constexpr uint32_t blend(uint32_t leftColor, uint32_t rightColor, UIntTy blendIndex)
90{
91 static_assert(std::is_same_v<UIntTy, uint8_t> || std::is_same_v<UIntTy, uint16_t>, "u8 or u16 allowed only");
92 constexpr UIntTy blendmax = (std::is_same_v<UIntTy, uint16_t> ? UINT16_MAX : UINT8_MAX);
93
94 ToRGB left_rgb(leftColor);
95 ToRGB right_rgb(rightColor);
96 // left + (right - left) * (blendIndex / maxBlend)
97 // Optimized to
98 // (left * (maxBlend - blendIndex) + right * blendIndex) / maxBlend
99 return fromRGB((static_cast<uint32_t>(left_rgb.r) * (blendmax - blendIndex) +
100 static_cast<uint32_t>(right_rgb.r) * blendIndex) /
101 blendmax,
102 (static_cast<uint32_t>(left_rgb.g) * (blendmax - blendIndex) +
103 static_cast<uint32_t>(right_rgb.g) * blendIndex) /
104 blendmax,
105 (static_cast<uint32_t>(left_rgb.b) * (blendmax - blendIndex) +
106 static_cast<uint32_t>(right_rgb.b) * blendIndex) /
107 blendmax);
108}
109
121template<bool isVideoMode = false> static uint32_t fade(uint32_t inputColor, uint8_t fadeAmount)
122{
123 uint32_t res;
124 ToRGB input_rgb(inputColor);
125
126 if (isVideoMode)
127 {
128 res = fromRGB(scale8_video(input_rgb.r, fadeAmount),
129 scale8_video(input_rgb.g, fadeAmount),
130 scale8_video(input_rgb.b, fadeAmount));
131 }
132 else
133 {
134 res = fromRGB(scale8(input_rgb.r, fadeAmount), scale8(input_rgb.g, fadeAmount), scale8(input_rgb.b, fadeAmount));
135 }
136 return res;
137}
138
140template<bool isFast = false> uint32_t add(uint32_t c1, uint32_t c2)
141{
142 ToRGB input1_rgb(c1);
143 ToRGB input2_rgb(c2);
144
145 if (isFast)
146 {
147 return fromRGB(
148 qadd8(input1_rgb.r, input2_rgb.r), qadd8(input1_rgb.g, input2_rgb.g), qadd8(input1_rgb.b, input2_rgb.b));
149 }
150 else
151 {
152 uint32_t r = input1_rgb.r + input2_rgb.r;
153 uint32_t g = input1_rgb.g + input2_rgb.g;
154 uint32_t b = input1_rgb.b + input2_rgb.b;
155 uint16_t max = r;
156 if (g > max)
157 max = g;
158 if (b > max)
159 max = b;
160 if (max < 256)
161 {
162 return fromRGB(r, g, b);
163 }
164 else
165 {
166 return fromRGB(r * 255 / max, g * 255 / max, b * 255 / max);
167 }
168 }
169}
170
171namespace __internal {
172
173static constexpr uint8_t hicolor_256_to_32[] = {
174 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3,
175 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6,
176 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9,
177 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12,
178 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16,
179 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
180 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,
181 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25,
182 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29,
183 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31};
184
185static constexpr uint8_t hicolor_256_to_64[] = {
186 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6,
187 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12,
188 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19,
189 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 25,
190 26, 26, 26, 26, 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 32, 32,
191 32, 32, 33, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38,
192 39, 39, 39, 39, 40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 44, 45, 45,
193 45, 45, 46, 46, 46, 46, 47, 47, 47, 47, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51,
194 52, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 56, 56, 56, 56, 57, 57, 57, 57, 58, 58,
195 58, 58, 59, 59, 59, 59, 60, 60, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, 63, 63, 63, 63};
196
197static constexpr uint8_t hicolor_32_to_256[] = {0, 8, 16, 24, 33, 41, 49, 57, 66, 74, 82,
198 90, 99, 107, 115, 123, 132, 140, 148, 156, 165, 173,
199 181, 189, 198, 206, 214, 222, 231, 239, 247, 255};
200
201static constexpr uint8_t hicolor_64_to_256[] = {
202 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 65, 69, 73, 77, 81, 85,
203 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138, 142, 146, 150, 154, 158, 162, 166, 170, 174,
204 178, 182, 186, 190, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255};
205
206} // namespace __internal
207
208static constexpr uint16_t get_compressed_16b_color(uint32_t color)
209{
210 ToRGB rgb(color);
211 uint16_t out = __internal::hicolor_256_to_32[rgb.r] | __internal::hicolor_256_to_64[rgb.g] << 5 |
212 __internal::hicolor_256_to_32[rgb.b] << 11;
213 return out;
214}
215static constexpr uint32_t get_decompressed_32b_color(uint16_t color)
216{
217 return fromRGB(__internal::hicolor_32_to_256[color & 0x1f],
218 __internal::hicolor_64_to_256[(color & 0x7ff) >> 5],
219 __internal::hicolor_32_to_256[color >> 11]);
220}
221
222} // namespace lampda::modes::colors
223
224#endif
Contains shorthand macro definitions.
Tools to manipulate colors and their representation.
Definition: gamma.hpp:10
static uint32_t fade(uint32_t inputColor, uint8_t fadeAmount)
fade the color toward black
Definition: utils.hpp:121
static constexpr uint8_t colorRotation[360]
precompiled table for Hue
Definition: utils.hpp:51
static constexpr LMBD_INLINE uint32_t fromGrey(uint32_t w)
Return color (w, w, w) as a single uint32_t integer.
Definition: utils.hpp:48
static constexpr uint32_t blend(uint32_t leftColor, uint32_t rightColor, UIntTy blendIndex)
blend to two colors
Definition: utils.hpp:89
static constexpr LMBD_INLINE uint32_t fromAngleHue(uint16_t angleDegrees)
Given a 360 degrees angle, return a corresponding color as an integer.
Definition: utils.hpp:71
static constexpr LMBD_INLINE uint32_t fromRGB(uint8_t r, uint8_t g, uint8_t b)
Return color (r, g, b) as a single uint32_t integer.
Definition: utils.hpp:24
uint32_t add(uint32_t c1, uint32_t c2)
Add two colors together.
Definition: utils.hpp:140
static constexpr N max(const N a, const N b)
Maximum of two numbers.
Definition: utils.h:37
Exposes (r, g, b) as uint8_t in struct from a single uint32_t color.
Definition: utils.hpp:33
uint8_t b
blue
Definition: utils.hpp:44
constexpr LMBD_INLINE ToRGB(uint32_t color)
convert color bytes to rgb struct
Definition: utils.hpp:35
uint8_t r
red
Definition: utils.hpp:42
uint8_t g
green
Definition: utils.hpp:43