Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

95 lines
2.7 KiB

/*
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