roo_display
API Documentation for roo_display
Loading...
Searching...
No Matches
color_modes.h
Go to the documentation of this file.
1#pragma once
2
3#include <inttypes.h>
4
8#include "roo_io/memory/load.h"
9
10namespace roo_display {
11
12/// ColorMode template contract.
13///
14/// A color mode `T` must provide:
15/// ```
16/// static const int8_t bits_per_pixel;
17/// Color toArgbColor(storage_type in) const;
18/// storage_type fromArgbColor(Color color) const;
19/// TransparencyMode transparency() const;
20/// ```
21///
22/// Meaning and expectations:
23/// - `bits_per_pixel`: how many bits encode a single pixel in this mode.
24/// - `toArgbColor(in)`: convert a raw pixel value to ARGB8888. If
25/// `bits_per_pixel < 8`, the value is stored in the low-order bits of `in`.
26/// - `fromArgbColor(color)`: convert ARGB8888 to a raw pixel value. If
27/// `bits_per_pixel < 8`, the return value must be in the low-order bits.
28/// - `transparency()`: indicates the alpha capabilities of the mode (opaque,
29/// binary, or gradual). Used as a rendering optimization hint.
30///
31/// For optimized blending, consider specializing `RawFullByteBlender` or
32/// `RawSubByteBlender`.
33
34/// 32-bit ARGB color mode.
35class Argb8888 {
36 public:
37 static const int8_t bits_per_pixel = 32;
38
39 inline constexpr Color toArgbColor(uint32_t in) const { return Color(in); }
40
41 inline constexpr uint32_t fromArgbColor(Color color) const {
42 return color.asArgb();
43 }
44
45 constexpr TransparencyMode transparency() const {
47 }
48};
49
50/// 32-bit RGBA color mode.
51class Rgba8888 {
52 public:
53 static const int8_t bits_per_pixel = 32;
54
55 inline constexpr Color toArgbColor(uint32_t in) const {
56 return Color(in >> 8 | (in & 0xFF) << 24);
57 }
58
59 inline constexpr uint32_t fromArgbColor(Color color) const {
60 return color.asArgb() << 8 | color.asArgb() >> 24;
61 }
62
63 constexpr TransparencyMode transparency() const {
65 }
66};
67
68namespace internal {
69
70inline static constexpr uint32_t TruncTo4bit(uint8_t c) {
71 return (c - (c >> 5)) >> 4;
72}
73
74inline static constexpr uint32_t TruncTo5bit(uint8_t c) {
75 return (c - (c >> 6)) >> 3;
76}
77
78inline static constexpr uint32_t TruncTo6bit(uint8_t c) {
79 return (c - (c >> 7)) >> 2;
80}
81
82} // namespace internal
83
84/// 24-bit RGB color mode (opaque).
85class Rgb888 {
86 public:
87 static const int8_t bits_per_pixel = 24;
88
89 inline constexpr Color toArgbColor(uint32_t in) const {
90 return Color(in | 0xFF000000);
91 }
92
93 inline constexpr uint32_t fromArgbColor(Color color) const {
94 return color.asArgb() & 0x00FFFFFF;
95 }
96
97 constexpr TransparencyMode transparency() const {
99 }
100};
101
102/// 24-bit ARGB 6-6-6-6 color mode.
103class Argb6666 {
104 public:
105 static const int8_t bits_per_pixel = 24;
106
107 inline constexpr Color toArgbColor(uint32_t in) const {
108 // uint32_t a = ((in >> 16) & 0xFC) | (in >> 22);
109 // uint32_t r = ((in >> 10) & 0xFC) | ((in >> 16) & 0x03);
110 // uint32_t g = ((in >> 4) & 0xFC) | ((in >> 10) & 0x03);
111 // uint32_t b = ((in << 2) & 0xFC) | ((in >> 4) & 0x03);
112 // return Color(a(in) << 24 | r(in) << 16 | g(in) << 8 | b(in));
113 return Color(((in >> 16) & 0xFC) | (in >> 22),
114 ((in >> 10) & 0xFC) | ((in >> 16) & 0x03),
115 ((in >> 4) & 0xFC) | ((in >> 10) & 0x03),
116 ((in << 2) & 0xFC) | ((in >> 4) & 0x03));
117 }
118
119 inline constexpr uint32_t fromArgbColor(Color color) const {
120 // uint32_t argb = color.asArgb();
121 // return ((color.asArgb() >> 8) & 0xFC0000LL) |
122 // ((color.asArgb() >> 6) & 0x03F000LL) |
123 // ((color.asArgb() >> 4) & 0x000FC0LL) |
124 // ((color.asArgb() >> 2) & 0x00003FLL);
125 return internal::TruncTo6bit(color.a()) << 18 |
126 internal::TruncTo6bit(color.r()) << 12 |
127 internal::TruncTo6bit(color.g()) << 6 |
129 }
130
131 constexpr TransparencyMode transparency() const {
133 }
134};
135
136/// 16-bit ARGB 4-4-4-4 color mode.
137class Argb4444 {
138 public:
139 static const int8_t bits_per_pixel = 16;
140
141 inline constexpr Color toArgbColor(uint16_t in) const {
142 // uint32_t a = ((in >> 8) & 0xF0) | (in >> 12);
143 // uint32_t r = ((in >> 4) & 0xF0) | ((in >> 8) & 0x0F);
144 // uint32_t g = ((in >> 0) & 0xF0) | ((in >> 4) & 0x0F);
145 // uint32_t b = ((in << 4) & 0xF0) | ((in >> 0) & 0x0F);
146 return Color(((in >> 8) & 0xF0) | (in >> 12),
147 ((in >> 4) & 0xF0) | ((in >> 8) & 0x0F),
148 ((in >> 0) & 0xF0) | ((in >> 4) & 0x0F),
149 ((in << 4) & 0xF0) | ((in >> 0) & 0x0F));
150 }
151
152 inline constexpr uint16_t fromArgbColor(Color color) const {
153 // uint32_t argb = color.asArgb();
154 // return ((color.asArgb() >> 16) & 0xF000) |
155 // ((color.asArgb() >> 12) & 0x0F00) |
156 // ((color.asArgb() >> 8) & 0x00F0) | ((color.asArgb() >> 4) &
157 // 0x000F);
158 return internal::TruncTo4bit(color.a()) << 12 |
159 internal::TruncTo4bit(color.r()) << 8 |
160 internal::TruncTo4bit(color.g()) << 4 |
162 }
163
164 constexpr TransparencyMode transparency() const {
166 }
167};
168
169/// 16-bit RGB565 color mode (opaque).
170class Rgb565 {
171 public:
172 static const int8_t bits_per_pixel = 16;
173
174 inline constexpr Color toArgbColor(uint16_t in) const
175 __attribute__((always_inline)) {
176 // uint32_t r = ((in >> 8) & 0xF8) | (in >> 13);
177 // uint32_t g = ((in >> 3) & 0xFC) | ((in >> 9) & 0x03);
178 // uint32_t b = ((in << 3) & 0xF8) | ((in >> 2) & 0x07);
179 return Color(((in >> 8) & 0xF8) | (in >> 13),
180 ((in >> 3) & 0xFC) | ((in >> 9) & 0x03),
181 ((in << 3) & 0xF8) | ((in >> 2) & 0x07));
182 }
183
184 inline constexpr uint16_t fromArgbColor(Color color) const
185 __attribute__((always_inline)) {
186 // uint32_t argb = color.asArgb();
187 // return ((color.asArgb() >> 8) & 0xF800) |
188 // ((color.asArgb() >> 5) & 0x07E0) |
189 // ((color.asArgb() >> 3) & 0x1F);
190 return internal::TruncTo5bit(color.r()) << 11 |
191 internal::TruncTo6bit(color.g()) << 5 |
193 }
194
195 constexpr TransparencyMode transparency() const {
197 }
198};
199
200template <roo_io::ByteOrder byte_order>
202 inline void operator()(roo::byte* dst, Color src, const Rgb565& mode) const {
204 Color bg = io.load(dst, mode);
205 io.store(AlphaBlendOverOpaque(bg, src), dst, mode);
206 }
207};
208
209// template <>
210// struct RawColorInterpolator<Rgb565> {
211// inline Color operator()(uint16_t c1, uint16_t c2, uint16_t fraction,
212// const Rgb565& mode) const {
213// return InterpolateOpaqueColors(mode.toArgbColor(c1),
214// mode.toArgbColor(c2), fraction);
215// }
216// };
217
218namespace internal {
220 return c == t ? c ^ 0x40 : c;
221}
222} // namespace internal
223
224/// RGB565 with a reserved value representing transparency.
226 public:
227 static const int8_t bits_per_pixel = 16;
228
231
232 inline constexpr Color toArgbColor(uint16_t in) const {
233 // if (in == transparency_) return Color(0);
234 // uint32_t r = ((in >> 8) & 0xF8) | (in >> 13);
235 // uint32_t g = ((in >> 3) & 0xFC) | ((in >> 9) & 0x03);
236 // uint32_t b = ((in << 3) & 0xF8) | ((in >> 2) & 0x07);
237 // return Color(0xFF000000 | r << 16 | g << 8 | b);
238 return in == transparency_ ? Color(0)
239 : Color(((in >> 8) & 0xF8) | (in >> 13),
240 ((in >> 3) & 0xFC) | ((in >> 9) & 0x03),
241 ((in << 3) & 0xF8) | ((in >> 2) & 0x07));
242 }
243
244 inline constexpr uint16_t fromArgbColor(Color color) const {
245 return color.a() <= 127 ? transparency_
247 internal::TruncTo5bit(color.r()) << 11 |
248 internal::TruncTo6bit(color.g()) << 5 |
250 transparency_);
251 }
252
253 constexpr TransparencyMode transparency() const {
255 }
256
257 uint16_t raw_transparency_color() const { return transparency_; }
258
259 private:
260 uint16_t transparency_;
261};
262
263template <roo_io::ByteOrder byte_order>
265 byte_order> {
266 inline void operator()(roo::byte* dst, Color src,
267 const Rgb565WithTransparency& mode) const {
268 uint16_t bg_raw = roo_io::LoadU16<byte_order>(dst);
270 if (bg_raw == mode.raw_transparency_color()) {
271 io.store(src, dst, mode);
272 } else {
273 io.store(AlphaBlendOverOpaque(io.load(dst, mode), src), dst, mode);
274 }
275 }
276};
277
278// 256 shades of gray.
280 public:
281 static const int8_t bits_per_pixel = 8;
282
283 inline constexpr Color toArgbColor(uint8_t in) const {
284 return Color(0xFF000000 | in * 0x010101);
285 }
286
287 inline constexpr uint8_t fromArgbColor(Color color) const {
288 // Using fast approximate formula;
289 // See https://stackoverflow.com/questions/596216
290 return (((int16_t)color.r() * 3) + ((int16_t)color.g() * 4) + color.b()) >>
291 3;
292 }
293
294 constexpr TransparencyMode transparency() const {
296 }
297};
298
299template <roo_io::ByteOrder byte_order>
301 inline void operator()(roo::byte* dst, Color src,
302 const Grayscale8& mode) const {
303 uint8_t bg = static_cast<uint8_t>(*dst);
304 uint8_t raw = mode.fromArgbColor(src);
305 uint16_t alpha = src.a();
306 *dst = static_cast<roo::byte>(
307 internal::__div_255_rounded(alpha * raw + (255 - alpha) * bg));
308 }
309};
310
311template <roo_io::ByteOrder byte_order>
313 byte_order> {
314 inline void operator()(roo::byte* dst, Color src,
315 const Grayscale8& mode) const {
316 uint8_t bg = static_cast<uint8_t>(*dst);
317 uint8_t raw = mode.fromArgbColor(src);
318 uint16_t alpha = src.a();
319 *dst = static_cast<roo::byte>(
320 internal::__div_255_rounded(alpha * raw + (255 - alpha) * bg));
321 }
322};
323
324template <>
327 const Grayscale8& mode) const {
328 return mode.toArgbColor(
329 ((uint16_t)c1 * (256 - fraction) + (uint16_t)c2 * fraction) / 256);
330 }
331};
332
333// 256 shades of gray + 8-bit alpha.
335 public:
336 static const int8_t bits_per_pixel = 16;
337
338 inline constexpr Color toArgbColor(uint16_t in) const {
339 return Color(in << 24 | (in >> 8) * 0x010101);
340 }
341
342 inline constexpr uint16_t fromArgbColor(Color color) const {
343 // Using fast approximate formula;
344 // See https://stackoverflow.com/questions/596216
345 return color.a() >> 24 |
346 ((((int16_t)color.r() * 3) + ((int16_t)color.g() * 4) + color.b()) >>
347 3) << 8;
348 }
349
350 constexpr TransparencyMode transparency() const {
352 }
353};
354
355// 16 shades of gray.
357 public:
358 static const int8_t bits_per_pixel = 4;
359
360 inline constexpr Color toArgbColor(uint8_t in) const {
361 return Color(0xFF000000 | in * 0x111111);
362 }
363
364 inline constexpr uint8_t fromArgbColor(Color color) const {
365 // Using fast approximate formula;
366 // See https://stackoverflow.com/questions/596216
367 return ((((uint16_t)color.r()) * 3) + (((uint16_t)color.g()) * 4) +
368 (uint16_t)color.b()) >>
369 7;
370 }
371
372 constexpr TransparencyMode transparency() const {
374 }
375};
376
377template <>
379 inline uint8_t operator()(uint8_t bg, Color color,
380 const Grayscale4& mode) const {
382 uint16_t alpha = color.a();
383 return internal::__div_255_rounded(alpha * raw + (255 - alpha) * bg);
384 }
385};
386
387template <>
389 inline uint8_t operator()(uint8_t bg, Color color,
390 const Grayscale4& mode) const {
392 uint16_t alpha = color.a();
393 return internal::__div_255_rounded(alpha * raw + (255 - alpha) * bg);
394 }
395};
396
397template <>
400 const Grayscale4& mode) const {
401 return Grayscale8().toArgbColor(
402 ((uint16_t)c1 * (256 - fraction) + (uint16_t)c2 * fraction) * 17 / 256);
403 }
404};
405
406// Semi-transparent monochrome with 256 transparency levels.
407class Alpha8 {
408 public:
409 constexpr Alpha8(Color color) : color_(color) {}
410
411 static const int8_t bits_per_pixel = 8;
412
413 inline constexpr Color toArgbColor(uint8_t in) const {
414 return Color((in << 24) | (color_.asArgb() & 0x00FFFFFF));
415 }
416
417 inline constexpr uint8_t fromArgbColor(Color color) const {
418 return color.a();
419 }
420
421 constexpr Color color() const { return color_; }
422
423 constexpr TransparencyMode transparency() const {
425 }
426
427 private:
428 Color color_;
429};
430
431template <roo_io::ByteOrder byte_order>
433 inline void operator()(roo::byte* dst, Color src, const Alpha8& mode) const {
434 uint8_t bg = static_cast<uint8_t>(*dst);
435 uint16_t front_alpha = src.a();
436 if (front_alpha == 0xFF || bg == 0xFF) {
437 *dst = static_cast<roo::byte>(0xFF);
438 return;
439 }
440 uint16_t tmp = bg * front_alpha;
441 *dst = static_cast<roo::byte>(bg + front_alpha -
443 }
444};
445
446template <>
449 const Alpha8& mode) const {
450 return mode.toArgbColor(
451 ((uint16_t)c1 * (256 - fraction) + (uint16_t)c2 * fraction) / 256);
452 }
453};
454
455// Semi-transparent monochrome with 16 transparency levels. Good default
456// for anti-aliased monochrome bitmaps.
457class Alpha4 {
458 public:
459 constexpr Alpha4(Color color)
460 : color_(0xFF000000 | (color.asArgb() & 0x00FFFFFF)) {}
461
462 static const int8_t bits_per_pixel = 4;
463
464 inline constexpr Color toArgbColor(uint8_t in) const {
465 return Color(((in | in << 4) << 24) | (color_.asArgb() & 0x00FFFFFF));
466 }
467
468 inline constexpr uint8_t fromArgbColor(Color color) const {
469 // return color.a() >> 4;
470 return internal::TruncTo4bit(color.a());
471 }
472
473 constexpr Color color() const { return color_; }
474 void setColor(Color color) { color_ = color; }
475
476 constexpr TransparencyMode transparency() const {
478 }
479
480 private:
481 Color color_;
482};
483
484template <>
486 inline uint8_t operator()(uint8_t bg, Color color, const Alpha4& mode) const {
488 if (front_alpha == 0xFF || bg == 0xF) return 0xF;
489 bg |= (bg << 4);
490 uint16_t tmp = bg * front_alpha;
493 }
494};
495
496template <>
499 const Alpha4& mode) const {
500 return Alpha8(mode.color())
502 ((uint16_t)c1 * (256 - fraction) + (uint16_t)c2 * fraction) * 17 /
503 256);
504 }
505};
506
507// Binary color, wich specified 'foreground' and 'background' values.
508// Both can be (semi) transparent. Useful for bit masks.
510 public:
511 constexpr Monochrome(Color fg, Color bg = Color(0x00000000))
512 : fg_(fg), bg_(bg) {}
513
514 static const int8_t bits_per_pixel = 1;
515
516 inline constexpr Color toArgbColor(uint8_t in) const {
517 return in == 0 ? bg_ : fg_;
518 }
519
520 inline constexpr uint8_t fromArgbColor(Color color) const {
521 return (color == bg_ || color.a() == 0) ? 0 : 1;
522 }
523
524 constexpr Color fg() const { return fg_; }
525 void setFg(Color fg) { fg_ = fg; }
526
527 constexpr Color bg() const { return bg_; }
528 void setBg(Color bg) { bg_ = bg; }
529
530 constexpr TransparencyMode transparency() const {
531 return bg().a() == 0xFF ? (fg().a() == 0xFF ? TransparencyMode::kNone
532 : fg().a() == 0x00 ? TransparencyMode::kCrude
534 : bg().a() == 0x00 ? (fg().a() == 0x00 || fg().a() == 0xFF
538 }
539
540 constexpr bool hasTransparency() const {
541 return bg().a() != 0xFF || fg().a() != 0xFF;
542 }
543
544 private:
545 Color fg_;
546 Color bg_;
547};
548
549template <>
551 inline uint8_t operator()(uint8_t bg, Color color,
552 const Monochrome& mode) const {
553 return mode.fg().a() == 0 ? bg : mode.fromArgbColor(mode.fg());
554 }
555};
556
557} // namespace roo_display
constexpr uint8_t fromArgbColor(Color color) const
void setColor(Color color)
constexpr TransparencyMode transparency() const
constexpr Alpha4(Color color)
constexpr Color color() const
static const int8_t bits_per_pixel
constexpr Color toArgbColor(uint8_t in) const
constexpr uint8_t fromArgbColor(Color color) const
static const int8_t bits_per_pixel
constexpr Color toArgbColor(uint8_t in) const
constexpr Alpha8(Color color)
constexpr TransparencyMode transparency() const
constexpr Color color() const
16-bit ARGB 4-4-4-4 color mode.
static const int8_t bits_per_pixel
constexpr Color toArgbColor(uint16_t in) const
constexpr TransparencyMode transparency() const
constexpr uint16_t fromArgbColor(Color color) const
24-bit ARGB 6-6-6-6 color mode.
constexpr TransparencyMode transparency() const
constexpr Color toArgbColor(uint32_t in) const
static const int8_t bits_per_pixel
constexpr uint32_t fromArgbColor(Color color) const
ColorMode template contract.
Definition color_modes.h:35
static const int8_t bits_per_pixel
Definition color_modes.h:37
constexpr uint32_t fromArgbColor(Color color) const
Definition color_modes.h:41
constexpr Color toArgbColor(uint32_t in) const
Definition color_modes.h:39
constexpr TransparencyMode transparency() const
Definition color_modes.h:45
ARGB8888 color stored as a 32-bit unsigned integer.
Definition color.h:16
constexpr uint8_t a() const
Alpha channel.
Definition color.h:36
constexpr uint32_t asArgb() const
Return packed ARGB value.
Definition color.h:33
constexpr Color toArgbColor(uint16_t in) const
constexpr TransparencyMode transparency() const
static const int8_t bits_per_pixel
constexpr uint16_t fromArgbColor(Color color) const
constexpr TransparencyMode transparency() const
static const int8_t bits_per_pixel
constexpr Color toArgbColor(uint8_t in) const
constexpr uint8_t fromArgbColor(Color color) const
constexpr uint8_t fromArgbColor(Color color) const
constexpr TransparencyMode transparency() const
constexpr Color toArgbColor(uint8_t in) const
static const int8_t bits_per_pixel
constexpr uint8_t fromArgbColor(Color color) const
constexpr Color toArgbColor(uint8_t in) const
constexpr Color fg() const
constexpr TransparencyMode transparency() const
constexpr Monochrome(Color fg, Color bg=Color(0x00000000))
constexpr bool hasTransparency() const
constexpr Color bg() const
static const int8_t bits_per_pixel
RGB565 with a reserved value representing transparency.
constexpr uint16_t fromArgbColor(Color color) const
constexpr Color toArgbColor(uint16_t in) const
constexpr Rgb565WithTransparency(uint16_t transparent_background_rgb565)
constexpr TransparencyMode transparency() const
16-bit RGB565 color mode (opaque).
static const int8_t bits_per_pixel
constexpr Color toArgbColor(uint16_t in) const __attribute__((always_inline))
constexpr uint16_t fromArgbColor(Color color) const __attribute__((always_inline))
constexpr TransparencyMode transparency() const
24-bit RGB color mode (opaque).
Definition color_modes.h:85
constexpr Color toArgbColor(uint32_t in) const
Definition color_modes.h:89
constexpr uint32_t fromArgbColor(Color color) const
Definition color_modes.h:93
constexpr TransparencyMode transparency() const
Definition color_modes.h:97
static const int8_t bits_per_pixel
Definition color_modes.h:87
32-bit RGBA color mode.
Definition color_modes.h:51
constexpr TransparencyMode transparency() const
Definition color_modes.h:63
constexpr Color toArgbColor(uint32_t in) const
Definition color_modes.h:55
static const int8_t bits_per_pixel
Definition color_modes.h:53
constexpr uint32_t fromArgbColor(Color color) const
Definition color_modes.h:59
constexpr uint8_t __div_255_rounded(uint16_t arg)
Definition blending.h:127
static constexpr uint32_t TruncTo4bit(uint8_t c)
Definition color_modes.h:70
static constexpr uint32_t TruncTo5bit(uint8_t c)
Definition color_modes.h:74
static constexpr uint32_t TruncTo6bit(uint8_t c)
Definition color_modes.h:78
constexpr uint16_t Resolve565Transparency(uint16_t c, uint16_t t)
Defines 140 opaque HTML named colors.
BlendingMode
Porter-Duff style blending modes.
Definition blending.h:17
@ kSourceOverOpaque
Similar to kSourceOver, but assumes that the destination is opaque.
@ kSourceOver
Source is placed (alpha-blended) over the destination. This is the default blending mode.
TransparencyMode
Transparency information for a stream or color mode.
Definition blending.h:103
@ kNone
All colors are fully opaque.
@ kCrude
Colors are either fully opaque or fully transparent.
@ kFull
Colors may include partial transparency (alpha channel).
Color AlphaBlendOverOpaque(Color bgc, Color fgc)
Definition blending.h:465
Color operator()(uint8_t c1, uint8_t c2, uint16_t fraction, const Alpha4 &mode) const
Color operator()(uint8_t c1, uint8_t c2, uint16_t fraction, const Alpha8 &mode) const
Color operator()(uint8_t c1, uint8_t c2, uint16_t fraction, const Grayscale4 &mode) const
Color operator()(uint8_t c1, uint8_t c2, uint16_t fraction, const Grayscale8 &mode) const
Default raw color interpolator (specialized in color_modes.h).
void operator()(roo::byte *dst, Color src, const Alpha8 &mode) const
void operator()(roo::byte *dst, Color src, const Grayscale8 &mode) const
void operator()(roo::byte *dst, Color src, const Grayscale8 &mode) const
void operator()(roo::byte *dst, Color src, const Rgb565WithTransparency &mode) const
void operator()(roo::byte *dst, Color src, const Rgb565 &mode) const
uint8_t operator()(uint8_t bg, Color color, const Alpha4 &mode) const
uint8_t operator()(uint8_t bg, Color color, const Grayscale4 &mode) const
uint8_t operator()(uint8_t bg, Color color, const Grayscale4 &mode) const
uint8_t operator()(uint8_t bg, Color color, const Monochrome &mode) const