|
|
- /*
- Part of the GARLAND MODULE
- Copyright (C) 2020 by Dmitry Blinov <dblinov76 at gmail dot com>
-
- Inspired by https://github.com/Vasil-Pahomov/ArWs2812 (currently https://github.com/Vasil-Pahomov/Liana)
- */
-
- #pragma once
-
- #if GARLAND_SUPPORT
-
- #include <vector>
-
- #include "color.h"
-
- class Palette {
- public:
- Palette(const char* name, std::vector<Color>&& 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<Color> _colors;
- std::vector<Color> _cache;
- };
-
- #endif // GARLAND_SUPPORT
|