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

  1. /*
  2. Part of the GARLAND MODULE
  3. Copyright (C) 2020 by Dmitry Blinov <dblinov76 at gmail dot com>
  4. Inspired by https://github.com/Vasil-Pahomov/ArWs2812 (currently https://github.com/Vasil-Pahomov/Liana)
  5. */
  6. #pragma once
  7. #if GARLAND_SUPPORT
  8. #include <vector>
  9. #include "color.h"
  10. class Palette {
  11. public:
  12. Palette(const char* name, std::vector<Color>&& colors) : _name(name), _numColors(colors.size()), _colors(std::move(colors)), _cache(256) {
  13. }
  14. const char* name() const { return _name; }
  15. /**
  16. * Get the interpolated color from the palette.
  17. * The argument is a floating number between 0 and 1
  18. * Used to smoothly traverse through palette.
  19. */
  20. Color getPalColor(float i) const {
  21. int i0 = (int)(i * _numColors) % (_numColors);
  22. int i1 = (int)(i * _numColors + 1) % (_numColors);
  23. // decimal part is used to interpolate between the two colors
  24. float t0 = i * _numColors - trunc(i * _numColors);
  25. return _colors[i0].interpolate(_colors[i1], t0);
  26. }
  27. Color getCachedPalColor(byte i) {
  28. if (!_cache[i].empty())
  29. return _cache[i];
  30. Color col = getPalColor((float)i / 256);
  31. if (col.empty())
  32. col = 1;
  33. _cache[i] = col;
  34. return col;
  35. }
  36. /**
  37. * Get the interpolated color between two random neighbour colors.
  38. */
  39. Color getRndNeighborInterpColor() const {
  40. int i0 = secureRandom(_numColors);
  41. int i1 = (i0 + 1) % (_numColors);
  42. float t0 = (float)(secureRandom(256)) / 256;
  43. return _colors[i0].interpolate(_colors[i1], t0);
  44. }
  45. /**
  46. * Get the interpolated color between two random colors.
  47. */
  48. Color getRndInterpColor() const {
  49. int i0 = secureRandom(_numColors);
  50. int i1 = secureRandom(_numColors);
  51. float t0 = (float)(secureRandom(256)) / 256;
  52. return _colors[i0].interpolate(_colors[i1], t0);
  53. }
  54. Color getContrastColor(const Color& prevColor) const {
  55. int tries = 0;
  56. int bestDiff = 0;
  57. Color bestColor;
  58. // 220 is magic number. Low values give "true" on closer colors, while higher can cause infinite loop while trying to find different color
  59. // let's try to find contras enough color but no more than 10 tries
  60. while (bestDiff <= 220 && tries++ < 10) {
  61. Color newColor = getRndInterpColor();
  62. int diff = prevColor.howCloseTo(newColor);
  63. if (bestDiff < diff) {
  64. bestDiff = diff;
  65. bestColor = newColor;
  66. }
  67. }
  68. return bestColor;
  69. }
  70. private:
  71. const char* _name;
  72. const int _numColors;
  73. std::vector<Color> _colors;
  74. std::vector<Color> _cache;
  75. };
  76. #endif // GARLAND_SUPPORT