154 lines
3.7 KiB
C++
154 lines
3.7 KiB
C++
#ifndef ESP32DISPLAYTEST_RGB_H
|
|
#define ESP32DISPLAYTEST_RGB_H
|
|
|
|
//#include "HSL.h"
|
|
#include <cstdint>
|
|
#include <cstddef>
|
|
#include <cassert>
|
|
#include <vector>
|
|
#include <Print.h>
|
|
|
|
|
|
class RGB {
|
|
static constexpr uint8_t hex_char_to_num(char ch) {
|
|
assert(
|
|
(ch >= '0' && ch <= '9') ||
|
|
(ch >= 'a' && ch <= 'f') ||
|
|
(ch >= 'A' && ch <= 'F')
|
|
);
|
|
if (ch >= '0' && ch <= '9') return ch - '0';
|
|
if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
|
|
if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
|
|
return -1;
|
|
}
|
|
|
|
static constexpr size_t const_strlen(const char *str) {
|
|
size_t len = 0;
|
|
while (*(str + len) != '\0') len++;
|
|
return len;
|
|
}
|
|
|
|
static constexpr uint32_t alpha_blend(uint8_t top, uint8_t bottom, uint8_t alpha) {
|
|
return ((uint32_t)top) * ((uint32_t)alpha) + ((uint32_t)bottom) * (255 - (uint32_t)alpha);
|
|
}
|
|
|
|
static constexpr uint32_t hex_str_to_num(const char *hex) {
|
|
size_t len = const_strlen(hex);
|
|
assert(len >= 6);
|
|
if (hex[0] == '0' && (hex[1] == 'x' || hex[1] == 'X')) {
|
|
assert(len == 8);
|
|
hex += 2;
|
|
} else {
|
|
assert(len == 6);
|
|
}
|
|
uint32_t res = 0;
|
|
for (size_t i = 0; i < 6; ++i) {
|
|
res = (res << 4) | hex_char_to_num(hex[i]);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static constexpr uint32_t hex_str_to_num(const char *hex, size_t len) {
|
|
assert(len >= 6);
|
|
if (hex[0] == '0' && (hex[1] == 'x' || hex[1] == 'X')) {
|
|
assert(len == 8);
|
|
hex += 2;
|
|
} else {
|
|
assert(len == 6);
|
|
}
|
|
uint32_t res = 0;
|
|
for (size_t i = 0; i < 6; ++i) {
|
|
res = (res << 4) | hex_char_to_num(hex[i]);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
explicit constexpr RGB(uint32_t num) : red(static_cast<uint8_t>((num >> 16) & 0xFF)),
|
|
green(static_cast<uint8_t>((num >> 8) & 0xFF)),
|
|
blue(static_cast<uint8_t>((num) & 0xFF)) {
|
|
}
|
|
|
|
public:
|
|
/*const*/ uint8_t red = 0;
|
|
/*const*/ uint8_t green = 0;
|
|
/*const*/ uint8_t blue = 0;
|
|
|
|
constexpr RGB() : red(0), green(0), blue(0) {}
|
|
|
|
constexpr RGB(const RGB &other) = default;
|
|
|
|
constexpr RGB(uint8_t r, uint8_t g, uint8_t b) : red(r), green(g), blue(b) {
|
|
}
|
|
|
|
explicit constexpr RGB(const char *hex) : RGB(hex_str_to_num(hex)) {
|
|
}
|
|
|
|
explicit constexpr RGB(const char *hex, size_t len) : RGB(hex_str_to_num(hex, len)) {
|
|
}
|
|
|
|
constexpr uint16_t
|
|
|
|
to_565() const {
|
|
uint8_t r = this->red >> 3;
|
|
uint8_t g = this->green >> 2;
|
|
uint8_t b = this->blue >> 3;
|
|
return (r << 11)
|
|
| (g << 5)
|
|
| b;
|
|
}
|
|
|
|
constexpr RGB alpha_blend_over(const RGB &other, uint8_t alpha) const {
|
|
uint32_t r = alpha_blend(this->red, other.red, alpha);
|
|
uint32_t g = alpha_blend(this->green, other.green, alpha);
|
|
uint32_t b = alpha_blend(this->blue, other.blue, alpha);
|
|
return {static_cast<uint8_t>(r / 255), static_cast<uint8_t>(g / 255), static_cast<uint8_t>(b / 255)};
|
|
}
|
|
|
|
constexpr uint16_t alpha_blend_over_to565(const RGB &other, uint8_t alpha) const {
|
|
uint8_t r = alpha_blend(this->red, other.red, alpha) * 31 / 255 / 255;
|
|
uint8_t g = alpha_blend(this->green, other.green, alpha) * 31 / 255 / 255;
|
|
uint8_t b = alpha_blend(this->blue, other.blue, alpha) * 31 / 255 / 255;
|
|
assert(r <= 31);
|
|
assert(g <= 63);
|
|
assert(b <= 31);
|
|
return (r << 11)
|
|
| (g << 5)
|
|
| b;
|
|
}
|
|
|
|
static RGB blend(const std::vector<RGB> &colors) {
|
|
if (colors.empty()) {
|
|
return {0, 0, 0};
|
|
}
|
|
uint64_t r = 0;
|
|
uint64_t g = 0;
|
|
uint64_t b = 0;
|
|
for (const auto &c : colors) {
|
|
r += c.red;
|
|
g += c.green;
|
|
b += c.blue;
|
|
}
|
|
r /= colors.size();
|
|
g /= colors.size();
|
|
b /= colors.size();
|
|
return {static_cast<uint8_t>(r), static_cast<uint8_t>(g), static_cast<uint8_t>(b)};
|
|
}
|
|
|
|
size_t printTo(Print &p) const {
|
|
return p.printf("RGB(%d,%d,%d)", red, green, blue);
|
|
}
|
|
|
|
};
|
|
|
|
constexpr RGB operator "" _rgb(const char *lit) {
|
|
return RGB(lit);
|
|
}
|
|
|
|
constexpr RGB operator "" _rgb(const char *lit, size_t len) {
|
|
return RGB(lit, len);
|
|
}
|
|
|
|
#endif //ESP32DISPLAYTEST_RGB_H
|