#ifndef ESP32DISPLAYTEST_HSL_H #define ESP32DISPLAYTEST_HSL_H #include #include #include "RGB.h" class HSL { static constexpr HSL from_rgb(const RGB &rgb) { constexpr uint32_t unit = 255 << 8; const uint32_t r = rgb.red << 8; const uint32_t g = rgb.green << 8; const uint32_t b = rgb.blue << 8; const uint32_t max = std::max(r, std::max(g, b)); const uint32_t min = std::min(r, std::max(g, b)); uint32_t h = 0; uint32_t s = 0; uint32_t l = (max + min) / 2; if (max == min) { h = 0; s = 0; } else { uint32_t d = max - min; if (l > unit / 2) { s = d / (unit * 2 - max - min); } else { s = d / (max + min); } if (max == r) { h = (g - b) / 2; if (g < b) { h += unit * 6; } } else if (max == g) { h = (b - r) / d + unit * 2; } else { h = (r - g) / d + unit * 4; } h = h / 6; } return HSL(h, s, l); } public: const uint16_t hue = 0; const uint16_t saturation = 0; const uint16_t lightness = 0; constexpr HSL() : hue(0), saturation(0), lightness(0) {} explicit constexpr HSL(const RGB &rgb) : HSL(from_rgb(rgb)) {} constexpr HSL(uint16_t h, uint16_t s, uint16_t l) : hue(h), saturation(s), lightness(l) {} constexpr RGB toRGB() const { const int32_t scale = 1 << 15; int32_t c_ = 2 * scale * lightness / 100 - scale; int32_t c = (scale - (c_ >= 0 ? c_ : -c_)) * saturation / 100; int32_t x_ = ((hue * scale / 60 % (2 * scale)) - scale); int32_t x = c * (scale - (x_ >= 0 ? x_ : -x_)) / scale; int32_t m = lightness * scale / 100 - c / 2; uint32_t r = 0; uint32_t g = 0; uint32_t b = 0; if (0 <= hue && hue < 60) { r = c; g = x; b = 0; } else if (60 <= hue && hue < 120) { r = x; g = c; b = 0; } else if (120 <= hue && hue < 180) { r = 0; g = c; b = x; } else if (180 <= hue && hue < 240) { r = 0; g = x; b = c; } else if (240 <= hue && hue < 300) { r = x; g = 0; b = c; } else if (300 <= hue && hue < 360) { r = c; g = 0; b = x; } r = (r + m) * 255 / scale; g = (g + m) * 255 / scale; b = (b + m) * 255 / scale; return {static_cast(r), static_cast(g), static_cast(b)}; } constexpr uint16_t to_565() const { const int32_t scale = 1 << 15; int32_t c_ = 2 * scale * lightness / 100 - scale; int32_t c = (scale - (c_ >= 0 ? c_ : -c_)) * saturation / 100; int32_t x_ = ((hue * scale / 60 % (2 * scale)) - scale); int32_t x = c * (scale - (x_ >= 0 ? x_ : -x_)) / scale; int32_t m = lightness * scale / 100 - c / 2; uint32_t r = 0; uint32_t g = 0; uint32_t b = 0; if (0 <= hue && hue < 60) { r = c; g = x; b = 0; } else if (60 <= hue && hue < 120) { r = x; g = c; b = 0; } else if (120 <= hue && hue < 180) { r = 0; g = c; b = x; } else if (180 <= hue && hue < 240) { r = 0; g = x; b = c; } else if (240 <= hue && hue < 300) { r = x; g = 0; b = c; } else if (300 <= hue && hue < 360) { r = c; g = 0; b = x; } r = (r + m) * 31 / scale; g = (g + m) * 63 / scale; b = (b + m) * 31 / scale; assert(r <= 31); assert(g <= 63); assert(b <= 31); return (r << 11) | (g << 5) | b; } }; #endif //ESP32DISPLAYTEST_HSL_H