/* Part of the GARLAND MODULE Copyright (C) 2020 by Dmitry Blinov Inspired by https://github.com/Vasil-Pahomov/ArWs2812 (currently https://github.com/Vasil-Pahomov/Liana) */ #pragma once #if GARLAND_SUPPORT #include #include "color.h" class Palette { public: Palette(const char* name, std::vector&& colors) : _name(name), _numColors(colors.size()), _colors(std::move(colors)), _cache(256) { } const char* name() const { return _name; } /** * Get the interpolated color from the palette. * The argument is a floating number between 0 and 1 * Used to smoothly traverse through palette. */ Color getPalColor(float i) const { int i0 = (int)(i * _numColors) % (_numColors); int i1 = (int)(i * _numColors + 1) % (_numColors); // decimal part is used to interpolate between the two colors float t0 = i * _numColors - trunc(i * _numColors); return _colors[i0].interpolate(_colors[i1], t0); } Color getCachedPalColor(byte i) { if (!_cache[i].empty()) return _cache[i]; Color col = getPalColor((float)i / 256); if (col.empty()) col = 1; _cache[i] = col; return col; } /** * Get the interpolated color between two random neighbour colors. */ Color getRndNeighborInterpColor() const { int i0 = secureRandom(_numColors); int i1 = (i0 + 1) % (_numColors); float t0 = (float)(secureRandom(256)) / 256; return _colors[i0].interpolate(_colors[i1], t0); } /** * Get the interpolated color between two random colors. */ Color getRndInterpColor() const { int i0 = secureRandom(_numColors); int i1 = secureRandom(_numColors); float t0 = (float)(secureRandom(256)) / 256; return _colors[i0].interpolate(_colors[i1], t0); } Color getContrastColor(const Color& prevColor) const { int tries = 0; int bestDiff = 0; Color bestColor; // 220 is magic number. Low values give "true" on closer colors, while higher can cause infinite loop while trying to find different color // let's try to find contras enough color but no more than 10 tries while (bestDiff <= 220 && tries++ < 10) { Color newColor = getRndInterpColor(); int diff = prevColor.howCloseTo(newColor); if (bestDiff < diff) { bestDiff = diff; bestColor = newColor; } } return bestColor; } private: const char* _name; const int _numColors; std::vector _colors; std::vector _cache; }; #endif // GARLAND_SUPPORT