diff --git a/src/internal/HsbColor.cpp b/src/internal/HsbColor.cpp
deleted file mode 100644
index e47912f..0000000
--- a/src/internal/HsbColor.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*-------------------------------------------------------------------------
-HsbColor provides a color object that can be directly consumed by NeoPixelBus
-
-Written by Michael C. Miller.
-
-I invest time and resources providing this open source code,
-please support me by dontating (see https://github.com/Makuna/NeoPixelBus)
-
--------------------------------------------------------------------------
-This file is part of the Makuna/NeoPixelBus library.
-
-NeoPixelBus is free software: you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as
-published by the Free Software Foundation, either version 3 of
-the License, or (at your option) any later version.
-
-NeoPixelBus is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with NeoPixel. If not, see
-.
--------------------------------------------------------------------------*/
-
-#include "RgbColor.h"
-#include "HsbColor.h"
-
-
-HsbColor::HsbColor(const RgbColor& color)
-{
- // convert colors to float between (0.0 - 1.0)
- float r = color.R / 255.0f;
- float g = color.G / 255.0f;
- float b = color.B / 255.0f;
-
- float max = (r > g && r > b) ? r : (g > b) ? g : b;
- float min = (r < g && r < b) ? r : (g < b) ? g : b;
-
- float d = max - min;
-
- float h = 0.0;
- float v = max;
- float s = (v == 0.0f) ? 0 : (d / v);
-
- if (d != 0.0f)
- {
- if (r == max)
- {
- h = (g - b) / d + (g < b ? 6.0f : 0.0f);
- }
- else if (g == max)
- {
- h = (b - r) / d + 2.0f;
- }
- else
- {
- h = (r - g) / d + 4.0f;
- }
- h /= 6.0f;
- }
-
-
- H = h;
- S = s;
- B = v;
-}
diff --git a/src/internal/HsbColor.h b/src/internal/HsbColor.h
index 4d0bdfa..c8869d2 100644
--- a/src/internal/HsbColor.h
+++ b/src/internal/HsbColor.h
@@ -1,4 +1,3 @@
-
/*-------------------------------------------------------------------------
HsbColor provides a color object that can be directly consumed by NeoPixelBus
@@ -26,35 +25,34 @@ License along with NeoPixel. If not, see
-------------------------------------------------------------------------*/
#pragma once
-#include
+struct RgbColor;
// ------------------------------------------------------------------------
// HsbColor represents a color object that is represented by Hue, Saturation, Brightness
-// component values. It contains helpful color routines to manipulate the
+// component values. It contains helpful color routines to manipulate the
// color.
// ------------------------------------------------------------------------
struct HsbColor
{
+ // ------------------------------------------------------------------------
+ // Construct a HsbColor that will have its values set in latter operations
+ // ------------------------------------------------------------------------
+ constexpr HsbColor();
+
// ------------------------------------------------------------------------
// Construct a HsbColor using H, S, B values (0.0 - 1.0)
// ------------------------------------------------------------------------
- HsbColor(float h, float s, float b) :
- H(h), S(s), B(b)
- {
- };
+ constexpr HsbColor(float h, float s, float b);
+
+ // ------------------------------------------------------------------------
+ // Construct a HsbColor using HsbColor
+ // ------------------------------------------------------------------------
+ constexpr HsbColor(const HsbColor& color);
// ------------------------------------------------------------------------
// Construct a HsbColor using RgbColor
// ------------------------------------------------------------------------
- HsbColor(const RgbColor& color);
-
- // ------------------------------------------------------------------------
- // Construct a HsbColor that will have its values set in latter operations
- // CAUTION: The H,S,B members are not initialized and may not be consistent
- // ------------------------------------------------------------------------
- HsbColor()
- {
- };
+ constexpr HsbColor(const RgbColor& color);
// ------------------------------------------------------------------------
// LinearBlend between two colors by the amount defined by progress variable
@@ -63,14 +61,10 @@ struct HsbColor
// progress - (0.0 - 1.0) value where 0.0 will return left and 1.0 will return right
// and a value between will blend the color weighted linearly between them
// ------------------------------------------------------------------------
- template static HsbColor LinearBlend(const HsbColor& left,
+ template
+ static constexpr HsbColor LinearBlend(const HsbColor& left,
const HsbColor& right,
- float progress)
- {
- return HsbColor(T_NEOHUEBLEND::HueBlend(left.H, right.H, progress),
- left.S + ((right.S - left.S) * progress),
- left.B + ((right.B - left.B) * progress));
- }
+ float progress);
// ------------------------------------------------------------------------
// BilinearBlend between four colors by the amount defined by 2d variable
@@ -81,33 +75,107 @@ struct HsbColor
// x - unit value (0.0 - 1.0) that defines the blend progress in horizontal space
// y - unit value (0.0 - 1.0) that defines the blend progress in vertical space
// ------------------------------------------------------------------------
- template static HsbColor BilinearBlend(const HsbColor& c00,
+ template
+ static constexpr HsbColor BilinearBlend(const HsbColor& c00,
const HsbColor& c01,
const HsbColor& c10,
const HsbColor& c11,
float x,
- float y)
- {
- float v00 = (1.0f - x) * (1.0f - y);
- float v10 = x * (1.0f - y);
- float v01 = (1.0f - x) * y;
- float v11 = x * y;
-
- return HsbColor(
- T_NEOHUEBLEND::HueBlend(
- T_NEOHUEBLEND::HueBlend(c00.H, c10.H, x),
- T_NEOHUEBLEND::HueBlend(c01.H, c11.H, x),
- y),
- c00.S * v00 + c10.S * v10 + c01.S * v01 + c11.S * v11,
- c00.B * v00 + c10.B * v10 + c01.B * v01 + c11.B * v11);
- };
+ float y);
// ------------------------------------------------------------------------
- // Hue, Saturation, Brightness color members
+ // Hue, Saturation, Brightness color members
// ------------------------------------------------------------------------
- float H;
- float S;
- float B;
+ float H{};
+ float S{};
+ float B{};
+
+private:
+ static constexpr HsbColor convertToHsbColor(const RgbColor& color);
};
+#include "RgbColor.h"
+
+constexpr HsbColor::HsbColor() = default;
+
+constexpr HsbColor::HsbColor(float h, float s, float b) :
+ H{h}, S{s}, B{b}
+{
+}
+
+constexpr HsbColor::HsbColor(const HsbColor& color) = default;
+
+constexpr HsbColor::HsbColor(const RgbColor& color) :
+ HsbColor{convertToHsbColor(color)}
+{
+}
+
+//template
+//static constexpr HsbColor HsbColor::LinearBlend(const HsbColor& left,
+// const HsbColor& right,
+// float progress)
+//{
+// return HsbColor(T_NEOHUEBLEND::HueBlend(left.H, right.H, progress),
+// left.S + ((right.S - left.S) * progress),
+// left.B + ((right.B - left.B) * progress));
+//}
+
+//template
+//static constexpr HsbColor HsbColor::BilinearBlend(const HsbColor& c00,
+// const HsbColor& c01,
+// const HsbColor& c10,
+// const HsbColor& c11,
+// float x,
+// float y)
+//{
+// float v00 = (1.0f - x) * (1.0f - y);
+// float v10 = x * (1.0f - y);
+// float v01 = (1.0f - x) * y;
+// float v11 = x * y;
+
+// return HsbColor(
+// T_NEOHUEBLEND::HueBlend(
+// T_NEOHUEBLEND::HueBlend(c00.H, c10.H, x),
+// T_NEOHUEBLEND::HueBlend(c01.H, c11.H, x),
+// y),
+// c00.S * v00 + c10.S * v10 + c01.S * v01 + c11.S * v11,
+// c00.B * v00 + c10.B * v10 + c01.B * v01 + c11.B * v11);
+//}
+
+constexpr HsbColor HsbColor::convertToHsbColor(const RgbColor& color)
+{
+ // convert colors to float between (0.0 - 1.0)
+ float r = color.R / 255.0f;
+ float g = color.G / 255.0f;
+ float b = color.B / 255.0f;
+
+ float max = (r > g && r > b) ? r : (g > b) ? g : b;
+ float min = (r < g && r < b) ? r : (g < b) ? g : b;
+
+ float d = max - min;
+
+ HsbColor hsb{};
+ hsb.H = 0.f;
+ hsb.B = max;
+ hsb.S = (hsb.B == 0.0f) ? 0 : (d / hsb.B);
+
+ if (d != 0.0f)
+ {
+ if (r == max)
+ {
+ hsb.H = (g - b) / d + (g < b ? 6.0f : 0.0f);
+ }
+ else if (g == max)
+ {
+ hsb.H = (b - r) / d + 2.0f;
+ }
+ else
+ {
+ hsb.H = (r - g) / d + 4.0f;
+ }
+ hsb.H /= 6.0f;
+ }
+
+ return hsb;
+}
diff --git a/src/internal/HslColor.cpp b/src/internal/HslColor.cpp
deleted file mode 100644
index ce9b238..0000000
--- a/src/internal/HslColor.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/*-------------------------------------------------------------------------
-HslColor provides a color object that can be directly consumed by NeoPixelBus
-
-
-Written by Michael C. Miller.
-
-I invest time and resources providing this open source code,
-please support me by dontating (see https://github.com/Makuna/NeoPixelBus)
-
--------------------------------------------------------------------------
-This file is part of the Makuna/NeoPixelBus library.
-
-NeoPixelBus is free software: you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as
-published by the Free Software Foundation, either version 3 of
-the License, or (at your option) any later version.
-
-NeoPixelBus is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with NeoPixel. If not, see
-.
--------------------------------------------------------------------------*/
-
-#include "RgbColor.h"
-#include "HslColor.h"
-
-
-HslColor::HslColor(const RgbColor& color)
-{
- // convert colors to float between (0.0 - 1.0)
- float r = color.R / 255.0f;
- float g = color.G / 255.0f;
- float b = color.B / 255.0f;
-
- float max = (r > g && r > b) ? r : (g > b) ? g : b;
- float min = (r < g && r < b) ? r : (g < b) ? g : b;
-
- float h, s, l;
- l = (max + min) / 2.0f;
-
- if (max == min)
- {
- h = s = 0.0f;
- }
- else
- {
- float d = max - min;
- s = (l > 0.5f) ? d / (2.0f - (max + min)) : d / (max + min);
-
- if (r > g && r > b)
- {
- h = (g - b) / d + (g < b ? 6.0f : 0.0f);
- }
- else if (g > b)
- {
- h = (b - r) / d + 2.0f;
- }
- else
- {
- h = (r - g) / d + 4.0f;
- }
- h /= 6.0f;
- }
-
- H = h;
- S = s;
- L = l;
-}
diff --git a/src/internal/HslColor.h b/src/internal/HslColor.h
index f6988bd..05272e1 100644
--- a/src/internal/HslColor.h
+++ b/src/internal/HslColor.h
@@ -25,37 +25,35 @@ License along with NeoPixel. If not, see
-------------------------------------------------------------------------*/
#pragma once
-#include
+struct RgbColor;
// ------------------------------------------------------------------------
// HslColor represents a color object that is represented by Hue, Saturation, Lightness
-// component values. It contains helpful color routines to manipulate the
+// component values. It contains helpful color routines to manipulate the
// color.
// ------------------------------------------------------------------------
struct HslColor
{
+ // ------------------------------------------------------------------------
+ // Construct a HslColor that will have its values set in latter operations
+ // ------------------------------------------------------------------------
+ constexpr HslColor();
// ------------------------------------------------------------------------
// Construct a HslColor using H, S, L values (0.0 - 1.0)
// L should be limited to between (0.0 - 0.5)
// ------------------------------------------------------------------------
- HslColor(float h, float s, float l) :
- H(h), S(s), L(l)
- {
- };
+ constexpr HslColor(float h, float s, float l);
+
+ // ------------------------------------------------------------------------
+ // Construct a HslColor using HslColor
+ // ------------------------------------------------------------------------
+ constexpr HslColor(const HslColor& color);
// ------------------------------------------------------------------------
// Construct a HslColor using RgbColor
// ------------------------------------------------------------------------
- HslColor(const RgbColor& color);
-
- // ------------------------------------------------------------------------
- // Construct a HslColor that will have its values set in latter operations
- // CAUTION: The H,S,L members are not initialized and may not be consistent
- // ------------------------------------------------------------------------
- HslColor()
- {
- };
+ constexpr HslColor(const RgbColor& color);
// ------------------------------------------------------------------------
// LinearBlend between two colors by the amount defined by progress variable
@@ -64,14 +62,10 @@ struct HslColor
// progress - (0.0 - 1.0) value where 0.0 will return left and 1.0 will return right
// and a value between will blend the color weighted linearly between them
// ------------------------------------------------------------------------
- template static HslColor LinearBlend(const HslColor& left,
+ template
+ static constexpr HslColor LinearBlend(const HslColor& left,
const HslColor& right,
- float progress)
- {
- return HslColor(T_NEOHUEBLEND::HueBlend(left.H, right.H, progress),
- left.S + ((right.S - left.S) * progress),
- left.L + ((right.L - left.L) * progress));
- };
+ float progress);
// ------------------------------------------------------------------------
// BilinearBlend between four colors by the amount defined by 2d variable
@@ -82,32 +76,110 @@ struct HslColor
// x - unit value (0.0 - 1.0) that defines the blend progress in horizontal space
// y - unit value (0.0 - 1.0) that defines the blend progress in vertical space
// ------------------------------------------------------------------------
- template static HslColor BilinearBlend(const HslColor& c00,
+ template
+ static constexpr HslColor BilinearBlend(const HslColor& c00,
const HslColor& c01,
const HslColor& c10,
const HslColor& c11,
float x,
- float y)
- {
- float v00 = (1.0f - x) * (1.0f - y);
- float v10 = x * (1.0f - y);
- float v01 = (1.0f - x) * y;
- float v11 = x * y;
-
- return HslColor(
- T_NEOHUEBLEND::HueBlend(
- T_NEOHUEBLEND::HueBlend(c00.H, c10.H, x),
- T_NEOHUEBLEND::HueBlend(c01.H, c11.H, x),
- y),
- c00.S * v00 + c10.S * v10 + c01.S * v01 + c11.S * v11,
- c00.L * v00 + c10.L * v10 + c01.L * v01 + c11.L * v11);
- };
+ float y);
// ------------------------------------------------------------------------
- // Hue, Saturation, Lightness color members
+ // Hue, Saturation, Lightness color members
// ------------------------------------------------------------------------
- float H;
- float S;
- float L;
+ float H{};
+ float S{};
+ float L{};
+
+private:
+ static constexpr HslColor convertToHslColor(const RgbColor& color);
};
+#include "RgbColor.h"
+
+constexpr HslColor::HslColor() = default;
+
+constexpr HslColor::HslColor(float h, float s, float l) :
+ H{h}, S{s}, L{l}
+{
+}
+
+constexpr HslColor::HslColor(const HslColor& color) = default;
+
+constexpr HslColor::HslColor(const RgbColor& color) :
+ HslColor{convertToHslColor(color)}
+{
+}
+
+//template
+//static constexpr HslColor HslColor::LinearBlend(const HslColor& left,
+// const HslColor& right,
+// float progress)
+//{
+// return HslColor(T_NEOHUEBLEND::HueBlend(left.H, right.H, progress),
+// left.S + ((right.S - left.S) * progress),
+// left.L + ((right.L - left.L) * progress));
+//};
+
+//template
+//static constexpr HslColor HslColor::BilinearBlend(const HslColor& c00,
+// const HslColor& c01,
+// const HslColor& c10,
+// const HslColor& c11,
+// float x,
+// float y)
+//{
+// float v00 = (1.0f - x) * (1.0f - y);
+// float v10 = x * (1.0f - y);
+// float v01 = (1.0f - x) * y;
+// float v11 = x * y;
+
+// return HslColor(
+// T_NEOHUEBLEND::HueBlend(
+// T_NEOHUEBLEND::HueBlend(c00.H, c10.H, x),
+// T_NEOHUEBLEND::HueBlend(c01.H, c11.H, x),
+// y),
+// c00.S * v00 + c10.S * v10 + c01.S * v01 + c11.S * v11,
+// c00.L * v00 + c10.L * v10 + c01.L * v01 + c11.L * v11);
+//}
+
+constexpr HslColor HslColor::convertToHslColor(const RgbColor& color)
+{
+ // convert colors to float between (0.0 - 1.0)
+ float r = color.R / 255.0f;
+ float g = color.G / 255.0f;
+ float b = color.B / 255.0f;
+
+ float max = (r > g && r > b) ? r : (g > b) ? g : b;
+ float min = (r < g && r < b) ? r : (g < b) ? g : b;
+
+ HslColor hsl;
+
+ hsl.L = (max + min) / 2.0f;
+
+ if (max == min)
+ {
+ hsl.H = hsl.S = 0.0f;
+ }
+ else
+ {
+ float d = max - min;
+ hsl.S = (hsl.L > 0.5f) ? d / (2.0f - (max + min)) : d / (max + min);
+
+ if (r > g && r > b)
+ {
+ hsl.H = (g - b) / d + (g < b ? 6.0f : 0.0f);
+ }
+ else if (g > b)
+ {
+ hsl.H = (b - r) / d + 2.0f;
+ }
+ else
+ {
+ hsl.H = (r - g) / d + 4.0f;
+ }
+ hsl.H /= 6.0f;
+ }
+
+ return hsl;
+}
diff --git a/src/internal/RgbColor.cpp b/src/internal/RgbColor.cpp
deleted file mode 100644
index 39371db..0000000
--- a/src/internal/RgbColor.cpp
+++ /dev/null
@@ -1,249 +0,0 @@
-/*-------------------------------------------------------------------------
-RgbColor provides a color object that can be directly consumed by NeoPixelBus
-
-Written by Michael C. Miller.
-
-I invest time and resources providing this open source code,
-please support me by dontating (see https://github.com/Makuna/NeoPixelBus)
-
--------------------------------------------------------------------------
-This file is part of the Makuna/NeoPixelBus library.
-
-NeoPixelBus is free software: you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as
-published by the Free Software Foundation, either version 3 of
-the License, or (at your option) any later version.
-
-NeoPixelBus is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with NeoPixel. If not, see
-.
--------------------------------------------------------------------------*/
-
-#include "RgbColor.h"
-#include "HslColor.h"
-#include "HsbColor.h"
-
-static float _CalcColor(float p, float q, float t)
-{
- if (t < 0.0f)
- t += 1.0f;
- if (t > 1.0f)
- t -= 1.0f;
-
- if (t < 1.0f / 6.0f)
- return p + (q - p) * 6.0f * t;
-
- if (t < 0.5f)
- return q;
-
- if (t < 2.0f / 3.0f)
- return p + ((q - p) * (2.0f / 3.0f - t) * 6.0f);
-
- return p;
-}
-
-RgbColor::RgbColor(const HslColor& color)
-{
- float r;
- float g;
- float b;
-
- float h = color.H;
- float s = color.S;
- float l = color.L;
-
-
- if (color.S == 0.0f || color.L == 0.0f)
- {
- r = g = b = l; // achromatic or black
- }
- else
- {
- float q = l < 0.5f ? l * (1.0f + s) : l + s - (l * s);
- float p = 2.0f * l - q;
- r = _CalcColor(p, q, h + 1.0f / 3.0f);
- g = _CalcColor(p, q, h);
- b = _CalcColor(p, q, h - 1.0f / 3.0f);
- }
-
- R = (uint8_t)(r * 255.0f);
- G = (uint8_t)(g * 255.0f);
- B = (uint8_t)(b * 255.0f);
-}
-
-RgbColor::RgbColor(const HsbColor& color)
-{
- float r;
- float g;
- float b;
-
- float h = color.H;
- float s = color.S;
- float v = color.B;
-
- if (color.S == 0.0f)
- {
- r = g = b = v; // achromatic or black
- }
- else
- {
- if (h < 0.0f)
- {
- h += 1.0f;
- }
- else if (h >= 1.0f)
- {
- h -= 1.0f;
- }
- h *= 6.0f;
- int i = (int)h;
- float f = h - i;
- float q = v * (1.0f - s * f);
- float p = v * (1.0f - s);
- float t = v * (1.0f - s * (1.0f - f));
- switch (i)
- {
- case 0:
- r = v;
- g = t;
- b = p;
- break;
- case 1:
- r = q;
- g = v;
- b = p;
- break;
- case 2:
- r = p;
- g = v;
- b = t;
- break;
- case 3:
- r = p;
- g = q;
- b = v;
- break;
- case 4:
- r = t;
- g = p;
- b = v;
- break;
- default:
- r = v;
- g = p;
- b = q;
- break;
- }
- }
-
- R = (uint8_t)(r * 255.0f);
- G = (uint8_t)(g * 255.0f);
- B = (uint8_t)(b * 255.0f);
-}
-
-uint8_t RgbColor::CalculateBrightness() const
-{
- return (uint8_t)(((uint16_t)R + (uint16_t)G + (uint16_t)B) / 3);
-}
-
-RgbColor RgbColor::Dim(uint8_t ratio) const
-{
- // specifically avoids float math
- return RgbColor(_elementDim(R, ratio), _elementDim(G, ratio), _elementDim(B, ratio));
-}
-
-RgbColor RgbColor::Brighten(uint8_t ratio) const
-{
- // specifically avoids float math
- return RgbColor(_elementBrighten(R, ratio), _elementBrighten(G, ratio), _elementBrighten(B, ratio));
-}
-
-void RgbColor::Darken(uint8_t delta)
-{
- if (R > delta)
- {
- R -= delta;
- }
- else
- {
- R = 0;
- }
-
- if (G > delta)
- {
- G -= delta;
- }
- else
- {
- G = 0;
- }
-
- if (B > delta)
- {
- B -= delta;
- }
- else
- {
- B = 0;
- }
-}
-
-void RgbColor::Lighten(uint8_t delta)
-{
- if (R < 255 - delta)
- {
- R += delta;
- }
- else
- {
- R = 255;
- }
-
- if (G < 255 - delta)
- {
- G += delta;
- }
- else
- {
- G = 255;
- }
-
- if (B < 255 - delta)
- {
- B += delta;
- }
- else
- {
- B = 255;
- }
-}
-
-RgbColor RgbColor::LinearBlend(const RgbColor& left, const RgbColor& right, float progress)
-{
- return RgbColor( left.R + ((right.R - left.R) * progress),
- left.G + ((right.G - left.G) * progress),
- left.B + ((right.B - left.B) * progress));
-}
-
-RgbColor RgbColor::BilinearBlend(const RgbColor& c00,
- const RgbColor& c01,
- const RgbColor& c10,
- const RgbColor& c11,
- float x,
- float y)
-{
- float v00 = (1.0f - x) * (1.0f - y);
- float v10 = x * (1.0f - y);
- float v01 = (1.0f - x) * y;
- float v11 = x * y;
-
- return RgbColor(
- c00.R * v00 + c10.R * v10 + c01.R * v01 + c11.R * v11,
- c00.G * v00 + c10.G * v10 + c01.G * v01 + c11.G * v11,
- c00.B * v00 + c10.B * v10 + c01.B * v01 + c11.B * v11);
-}
diff --git a/src/internal/RgbColor.h b/src/internal/RgbColor.h
index 55b5618..c6eba0c 100644
--- a/src/internal/RgbColor.h
+++ b/src/internal/RgbColor.h
@@ -25,7 +25,8 @@ License along with NeoPixel. If not, see
-------------------------------------------------------------------------*/
#pragma once
-#include
+#include
+
#include "NeoSettings.h"
struct HslColor;
@@ -33,97 +34,87 @@ struct HsbColor;
// ------------------------------------------------------------------------
// RgbColor represents a color object that is represented by Red, Green, Blue
-// component values. It contains helpful color routines to manipulate the
+// component values. It contains helpful color routines to manipulate the
// color.
// ------------------------------------------------------------------------
struct RgbColor
{
- typedef NeoRgbCurrentSettings SettingsObject;
+ using SettingsObject = NeoRgbCurrentSettings;
+
+ // ------------------------------------------------------------------------
+ // Construct a RgbColor that will have its values set in latter operations
+ // ------------------------------------------------------------------------
+ constexpr RgbColor();
// ------------------------------------------------------------------------
// Construct a RgbColor using R, G, B values (0-255)
// ------------------------------------------------------------------------
- RgbColor(uint8_t r, uint8_t g, uint8_t b) :
- R(r), G(g), B(b)
- {
- };
+ constexpr RgbColor(uint8_t r, uint8_t g, uint8_t b);
// ------------------------------------------------------------------------
// Construct a RgbColor using a single brightness value (0-255)
// This works well for creating gray tone colors
// (0) = black, (255) = white, (128) = gray
// ------------------------------------------------------------------------
- RgbColor(uint8_t brightness) :
- R(brightness), G(brightness), B(brightness)
- {
- };
+ constexpr RgbColor(uint8_t brightness);
// ------------------------------------------------------------------------
// Construct a RgbColor using HslColor
// ------------------------------------------------------------------------
- RgbColor(const HslColor& color);
+ constexpr RgbColor(const RgbColor& color);
+
+ // ------------------------------------------------------------------------
+ // Construct a RgbColor using HslColor
+ // ------------------------------------------------------------------------
+ constexpr RgbColor(const HslColor& color);
// ------------------------------------------------------------------------
// Construct a RgbColor using HsbColor
// ------------------------------------------------------------------------
- RgbColor(const HsbColor& color);
-
- // ------------------------------------------------------------------------
- // Construct a RgbColor that will have its values set in latter operations
- // CAUTION: The R,G,B members are not initialized and may not be consistent
- // ------------------------------------------------------------------------
- RgbColor()
- {
- };
+ constexpr RgbColor(const HsbColor& color);
// ------------------------------------------------------------------------
// Comparison operators
// ------------------------------------------------------------------------
- bool operator==(const RgbColor& other) const
- {
- return (R == other.R && G == other.G && B == other.B);
- };
+ constexpr bool operator==(const RgbColor& other) const;
- bool operator!=(const RgbColor& other) const
- {
- return !(*this == other);
- };
+ constexpr bool operator!=(const RgbColor& other) const;
// ------------------------------------------------------------------------
// CalculateBrightness will calculate the overall brightness
// NOTE: This is a simple linear brightness
// ------------------------------------------------------------------------
- uint8_t CalculateBrightness() const;
+ constexpr uint8_t CalculateBrightness() const;
// ------------------------------------------------------------------------
// Dim will return a new color that is blended to black with the given ratio
// ratio - (0-255) where 255 will return the original color and 0 will return black
- //
+ //
// NOTE: This is a simple linear blend
// ------------------------------------------------------------------------
- RgbColor Dim(uint8_t ratio) const;
+ constexpr RgbColor Dim(uint8_t ratio) const;
// ------------------------------------------------------------------------
// Brighten will return a new color that is blended to white with the given ratio
// ratio - (0-255) where 255 will return the original color and 0 will return white
- //
+ //
// NOTE: This is a simple linear blend
// ------------------------------------------------------------------------
- RgbColor Brighten(uint8_t ratio) const;
+ constexpr RgbColor Brighten(uint8_t ratio) const;
// ------------------------------------------------------------------------
// Darken will adjust the color by the given delta toward black
// NOTE: This is a simple linear change
// delta - (0-255) the amount to dim the color
// ------------------------------------------------------------------------
- void Darken(uint8_t delta);
+ constexpr void Darken(uint8_t delta);
// ------------------------------------------------------------------------
// Lighten will adjust the color by the given delta toward white
// NOTE: This is a simple linear change
// delta - (0-255) the amount to lighten the color
// ------------------------------------------------------------------------
- void Lighten(uint8_t delta);
+ constexpr void Lighten(uint8_t delta);
// ------------------------------------------------------------------------
// LinearBlend between two colors by the amount defined by progress variable
@@ -132,8 +123,8 @@ struct RgbColor
// progress - (0.0 - 1.0) value where 0 will return left and 1.0 will return right
// and a value between will blend the color weighted linearly between them
// ------------------------------------------------------------------------
- static RgbColor LinearBlend(const RgbColor& left, const RgbColor& right, float progress);
-
+ static constexpr RgbColor LinearBlend(const RgbColor& left, const RgbColor& right, float progress);
+
// ------------------------------------------------------------------------
// BilinearBlend between four colors by the amount defined by 2d variable
// c00 - upper left quadrant color
@@ -143,51 +134,310 @@ struct RgbColor
// x - unit value (0.0 - 1.0) that defines the blend progress in horizontal space
// y - unit value (0.0 - 1.0) that defines the blend progress in vertical space
// ------------------------------------------------------------------------
- static RgbColor BilinearBlend(const RgbColor& c00,
- const RgbColor& c01,
- const RgbColor& c10,
- const RgbColor& c11,
- float x,
+ static constexpr RgbColor BilinearBlend(const RgbColor& c00,
+ const RgbColor& c01,
+ const RgbColor& c10,
+ const RgbColor& c11,
+ float x,
float y);
- uint32_t CalcTotalTenthMilliAmpere(const SettingsObject& settings)
- {
- auto total = 0;
-
- total += R * settings.RedTenthMilliAmpere / 255;
- total += G * settings.GreenTenthMilliAmpere / 255;
- total += B * settings.BlueTenthMilliAmpere / 255;
-
- return total;
- }
+ constexpr uint32_t CalcTotalTenthMilliAmpere(const SettingsObject& settings) const;
// ------------------------------------------------------------------------
- // Red, Green, Blue color members (0-255) where
+ // Red, Green, Blue color members (0-255) where
// (0,0,0) is black and (255,255,255) is white
// ------------------------------------------------------------------------
- uint8_t R;
- uint8_t G;
- uint8_t B;
+ uint8_t R{};
+ uint8_t G{};
+ uint8_t B{};
private:
- inline static uint8_t _elementDim(uint8_t value, uint8_t ratio)
- {
- return (static_cast(value) * (static_cast(ratio) + 1)) >> 8;
- }
-
- inline static uint8_t _elementBrighten(uint8_t value, uint8_t ratio)
- {
- uint16_t element = ((static_cast(value) + 1) << 8) / (static_cast(ratio) + 1);
-
- if (element > 255)
- {
- element = 255;
- }
- else
- {
- element -= 1;
- }
- return element;
- }
+ inline static constexpr uint8_t _elementDim(uint8_t value, uint8_t ratio);
+ inline static constexpr uint8_t _elementBrighten(uint8_t value, uint8_t ratio);
+ inline static constexpr float _CalcColor(float p, float q, float t);
+ inline static constexpr RgbColor convertToRgbColor(const HslColor& color);
+ inline static constexpr RgbColor convertToRgbColor(const HsbColor& color);
};
+#include "HslColor.h"
+#include "HsbColor.h"
+
+constexpr RgbColor::RgbColor() = default;
+
+constexpr RgbColor::RgbColor(uint8_t r, uint8_t g, uint8_t b) :
+ R{r}, G{g}, B{b}
+{
+}
+
+constexpr RgbColor::RgbColor(uint8_t brightness) :
+ R{brightness}, G{brightness}, B{brightness}
+{
+}
+
+constexpr RgbColor::RgbColor(const RgbColor& color) = default;
+
+constexpr RgbColor::RgbColor(const HslColor& color) :
+ RgbColor{convertToRgbColor(color)}
+{
+}
+
+constexpr RgbColor::RgbColor(const HsbColor& color) :
+ RgbColor{convertToRgbColor(color)}
+{
+}
+
+constexpr bool RgbColor::operator==(const RgbColor& other) const
+{
+ return (R == other.R && G == other.G && B == other.B);
+};
+
+constexpr bool RgbColor::operator!=(const RgbColor& other) const
+{
+ return !(*this == other);
+};
+
+constexpr uint8_t RgbColor::CalculateBrightness() const
+{
+ return (uint8_t)(((uint16_t)R + (uint16_t)G + (uint16_t)B) / 3);
+}
+
+constexpr RgbColor RgbColor::Dim(uint8_t ratio) const
+{
+ // specifically avoids float math
+ return RgbColor(_elementDim(R, ratio), _elementDim(G, ratio), _elementDim(B, ratio));
+}
+
+constexpr RgbColor RgbColor::Brighten(uint8_t ratio) const
+{
+ // specifically avoids float math
+ return RgbColor(_elementBrighten(R, ratio), _elementBrighten(G, ratio), _elementBrighten(B, ratio));
+}
+
+constexpr void RgbColor::Darken(uint8_t delta)
+{
+ if (R > delta)
+ {
+ R -= delta;
+ }
+ else
+ {
+ R = 0;
+ }
+
+ if (G > delta)
+ {
+ G -= delta;
+ }
+ else
+ {
+ G = 0;
+ }
+
+ if (B > delta)
+ {
+ B -= delta;
+ }
+ else
+ {
+ B = 0;
+ }
+}
+
+constexpr void RgbColor::Lighten(uint8_t delta)
+{
+ if (R < 255 - delta)
+ {
+ R += delta;
+ }
+ else
+ {
+ R = 255;
+ }
+
+ if (G < 255 - delta)
+ {
+ G += delta;
+ }
+ else
+ {
+ G = 255;
+ }
+
+ if (B < 255 - delta)
+ {
+ B += delta;
+ }
+ else
+ {
+ B = 255;
+ }
+}
+
+constexpr RgbColor RgbColor::LinearBlend(const RgbColor& left, const RgbColor& right, float progress)
+{
+ return RgbColor( left.R + ((right.R - left.R) * progress),
+ left.G + ((right.G - left.G) * progress),
+ left.B + ((right.B - left.B) * progress));
+}
+
+constexpr RgbColor RgbColor::BilinearBlend(const RgbColor& c00,
+ const RgbColor& c01,
+ const RgbColor& c10,
+ const RgbColor& c11,
+ float x,
+ float y)
+{
+ float v00 = (1.0f - x) * (1.0f - y);
+ float v10 = x * (1.0f - y);
+ float v01 = (1.0f - x) * y;
+ float v11 = x * y;
+
+ return RgbColor(
+ c00.R * v00 + c10.R * v10 + c01.R * v01 + c11.R * v11,
+ c00.G * v00 + c10.G * v10 + c01.G * v01 + c11.G * v11,
+ c00.B * v00 + c10.B * v10 + c01.B * v01 + c11.B * v11);
+}
+
+constexpr uint32_t RgbColor::CalcTotalTenthMilliAmpere(const SettingsObject& settings) const
+{
+ auto total = 0;
+
+ total += R * settings.RedTenthMilliAmpere / 255;
+ total += G * settings.GreenTenthMilliAmpere / 255;
+ total += B * settings.BlueTenthMilliAmpere / 255;
+
+ return total;
+}
+
+constexpr uint8_t RgbColor::_elementDim(uint8_t value, uint8_t ratio)
+{
+ return (static_cast(value) * (static_cast(ratio) + 1)) >> 8;
+}
+
+constexpr uint8_t RgbColor::_elementBrighten(uint8_t value, uint8_t ratio)
+{
+ uint16_t element = ((static_cast(value) + 1) << 8) / (static_cast(ratio) + 1);
+
+ if (element > 255)
+ {
+ element = 255;
+ }
+ else
+ {
+ element -= 1;
+ }
+ return element;
+}
+
+constexpr float RgbColor::_CalcColor(float p, float q, float t)
+{
+ if (t < 0.0f)
+ t += 1.0f;
+ if (t > 1.0f)
+ t -= 1.0f;
+
+ if (t < 1.0f / 6.0f)
+ return p + (q - p) * 6.0f * t;
+
+ if (t < 0.5f)
+ return q;
+
+ if (t < 2.0f / 3.0f)
+ return p + ((q - p) * (2.0f / 3.0f - t) * 6.0f);
+
+ return p;
+}
+
+constexpr RgbColor RgbColor::convertToRgbColor(const HslColor& color)
+{
+ float r{};
+ float g{};
+ float b{};
+
+ float h = color.H;
+ float s = color.S;
+ float l = color.L;
+
+ if (color.S == 0.0f || color.L == 0.0f)
+ {
+ r = g = b = l; // achromatic or black
+ }
+ else
+ {
+ float q = l < 0.5f ? l * (1.0f + s) : l + s - (l * s);
+ float p = 2.0f * l - q;
+ r = _CalcColor(p, q, h + 1.0f / 3.0f);
+ g = _CalcColor(p, q, h);
+ b = _CalcColor(p, q, h - 1.0f / 3.0f);
+ }
+
+ return RgbColor{(uint8_t)(r * 255.0f), (uint8_t)(g * 255.0f), (uint8_t)(b * 255.0f)};
+}
+
+constexpr RgbColor RgbColor::convertToRgbColor(const HsbColor& color)
+{
+ float r{};
+ float g{};
+ float b{};
+
+ float h = color.H;
+ float s = color.S;
+ float v = color.B;
+
+ if (color.S == 0.0f)
+ {
+ r = g = b = v; // achromatic or black
+ }
+ else
+ {
+ if (h < 0.0f)
+ {
+ h += 1.0f;
+ }
+ else if (h >= 1.0f)
+ {
+ h -= 1.0f;
+ }
+ h *= 6.0f;
+ int i = (int)h;
+ float f = h - i;
+ float q = v * (1.0f - s * f);
+ float p = v * (1.0f - s);
+ float t = v * (1.0f - s * (1.0f - f));
+ switch (i)
+ {
+ case 0:
+ r = v;
+ g = t;
+ b = p;
+ break;
+ case 1:
+ r = q;
+ g = v;
+ b = p;
+ break;
+ case 2:
+ r = p;
+ g = v;
+ b = t;
+ break;
+ case 3:
+ r = p;
+ g = q;
+ b = v;
+ break;
+ case 4:
+ r = t;
+ g = p;
+ b = v;
+ break;
+ default:
+ r = v;
+ g = p;
+ b = q;
+ break;
+ }
+ }
+
+ return RgbColor{(uint8_t)(r * 255.0f), (uint8_t)(g * 255.0f), (uint8_t)(b * 255.0f)};
+}
diff --git a/src/internal/RgbwColor.cpp b/src/internal/RgbwColor.cpp
deleted file mode 100644
index 81d89ed..0000000
--- a/src/internal/RgbwColor.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/*-------------------------------------------------------------------------
-RgbwColor provides a color object that can be directly consumed by NeoPixelBus
-
-Written by Michael C. Miller.
-
-I invest time and resources providing this open source code,
-please support me by dontating (see https://github.com/Makuna/NeoPixelBus)
-
--------------------------------------------------------------------------
-This file is part of the Makuna/NeoPixelBus library.
-
-NeoPixelBus is free software: you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as
-published by the Free Software Foundation, either version 3 of
-the License, or (at your option) any later version.
-
-NeoPixelBus is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with NeoPixel. If not, see
-.
--------------------------------------------------------------------------*/
-
-#include "RgbColor.h"
-#include "HslColor.h"
-#include "HsbColor.h"
-#include "RgbwColor.h"
-
-RgbwColor::RgbwColor(const HslColor& color)
-{
- RgbColor rgbColor(color);
- *this = rgbColor;
-}
-
-RgbwColor::RgbwColor(const HsbColor& color)
-{
- RgbColor rgbColor(color);
- *this = rgbColor;
-}
-
-uint8_t RgbwColor::CalculateBrightness() const
-{
- uint8_t colorB = (uint8_t)(((uint16_t)R + (uint16_t)G + (uint16_t)B) / 3);
- if (W > colorB)
- {
- return W;
- }
- else
- {
- return colorB;
- }
-}
-
-RgbwColor RgbwColor::Dim(uint8_t ratio) const
-{
- // specifically avoids float math
- return RgbwColor(_elementDim(R, ratio), _elementDim(G, ratio), _elementDim(B, ratio), _elementDim(W, ratio));
-}
-
-RgbwColor RgbwColor::Brighten(uint8_t ratio) const
-{
- // specifically avoids float math
- return RgbwColor(_elementBrighten(R, ratio), _elementBrighten(G, ratio), _elementBrighten(B, ratio), _elementBrighten(W, ratio));
-}
-
-void RgbwColor::Darken(uint8_t delta)
-{
- if (R > delta)
- {
- R -= delta;
- }
- else
- {
- R = 0;
- }
-
- if (G > delta)
- {
- G -= delta;
- }
- else
- {
- G = 0;
- }
-
- if (B > delta)
- {
- B -= delta;
- }
- else
- {
- B = 0;
- }
-
- if (W > delta)
- {
- W -= delta;
- }
- else
- {
- W = 0;
- }
-}
-
-void RgbwColor::Lighten(uint8_t delta)
-{
- if (IsColorLess())
- {
- if (W < 255 - delta)
- {
- W += delta;
- }
- else
- {
- W = 255;
- }
- }
- else
- {
- if (R < 255 - delta)
- {
- R += delta;
- }
- else
- {
- R = 255;
- }
-
- if (G < 255 - delta)
- {
- G += delta;
- }
- else
- {
- G = 255;
- }
-
- if (B < 255 - delta)
- {
- B += delta;
- }
- else
- {
- B = 255;
- }
- }
-}
-
-RgbwColor RgbwColor::LinearBlend(const RgbwColor& left, const RgbwColor& right, float progress)
-{
- return RgbwColor( left.R + ((right.R - left.R) * progress),
- left.G + ((right.G - left.G) * progress),
- left.B + ((right.B - left.B) * progress),
- left.W + ((right.W - left.W) * progress) );
-}
-
-RgbwColor RgbwColor::BilinearBlend(const RgbwColor& c00,
- const RgbwColor& c01,
- const RgbwColor& c10,
- const RgbwColor& c11,
- float x,
- float y)
-{
- float v00 = (1.0f - x) * (1.0f - y);
- float v10 = x * (1.0f - y);
- float v01 = (1.0f - x) * y;
- float v11 = x * y;
-
- return RgbwColor(
- c00.R * v00 + c10.R * v10 + c01.R * v01 + c11.R * v11,
- c00.G * v00 + c10.G * v10 + c01.G * v01 + c11.G * v11,
- c00.B * v00 + c10.B * v10 + c01.B * v01 + c11.B * v11,
- c00.W * v00 + c10.W * v10 + c01.W * v01 + c11.W * v11 );
-}
diff --git a/src/internal/RgbwColor.h b/src/internal/RgbwColor.h
index e282223..478b316 100644
--- a/src/internal/RgbwColor.h
+++ b/src/internal/RgbwColor.h
@@ -25,7 +25,9 @@ License along with NeoPixel. If not, see
-------------------------------------------------------------------------*/
#pragma once
-#include
+#include
+
+#include "NeoSettings.h"
struct RgbColor;
struct HslColor;
@@ -38,90 +40,68 @@ struct HsbColor;
// ------------------------------------------------------------------------
struct RgbwColor
{
- typedef NeoRgbwCurrentSettings SettingsObject;
+ using SettingsObject = NeoRgbwCurrentSettings;
+
+ // ------------------------------------------------------------------------
+ // Construct a RgbwColor that will have its values set in latter operations
+ // ------------------------------------------------------------------------
+ constexpr RgbwColor();
// ------------------------------------------------------------------------
// Construct a RgbwColor using R, G, B, W values (0-255)
// ------------------------------------------------------------------------
- RgbwColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) :
- R(r), G(g), B(b), W(w)
- {
- };
+ constexpr RgbwColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0);
// ------------------------------------------------------------------------
// Construct a RgbColor using a single brightness value (0-255)
// This works well for creating gray tone colors
// (0) = black, (255) = white, (128) = gray
// ------------------------------------------------------------------------
- RgbwColor(uint8_t brightness) :
- R(0), G(0), B(0), W(brightness)
- {
- };
+ constexpr RgbwColor(uint8_t brightness);
+
+ // ------------------------------------------------------------------------
+ // Construct a RgbwColor using RgbwColor
+ // ------------------------------------------------------------------------
+ constexpr RgbwColor(const RgbwColor& color);
// ------------------------------------------------------------------------
// Construct a RgbwColor using RgbColor
// ------------------------------------------------------------------------
- RgbwColor(const RgbColor& color) :
- R(color.R),
- G(color.G),
- B(color.B),
- W(0)
- {
- };
+ constexpr RgbwColor(const RgbColor& color);
// ------------------------------------------------------------------------
// Construct a RgbwColor using HslColor
// ------------------------------------------------------------------------
- RgbwColor(const HslColor& color);
+ constexpr RgbwColor(const HslColor& color);
// ------------------------------------------------------------------------
// Construct a RgbwColor using HsbColor
// ------------------------------------------------------------------------
- RgbwColor(const HsbColor& color);
-
- // ------------------------------------------------------------------------
- // Construct a RgbwColor that will have its values set in latter operations
- // CAUTION: The R,G,B, W members are not initialized and may not be consistent
- // ------------------------------------------------------------------------
- RgbwColor()
- {
- };
+ constexpr RgbwColor(const HsbColor& color);
// ------------------------------------------------------------------------
// Comparison operators
// ------------------------------------------------------------------------
- bool operator==(const RgbwColor& other) const
- {
- return (R == other.R && G == other.G && B == other.B && W == other.W);
- };
+ constexpr bool operator==(const RgbwColor& other) const;
- bool operator!=(const RgbwColor& other) const
- {
- return !(*this == other);
- };
+ constexpr bool operator!=(const RgbwColor& other) const;
// ------------------------------------------------------------------------
// Returns if the color is grey, all values are equal other than white
// ------------------------------------------------------------------------
- bool IsMonotone() const
- {
- return (R == B && R == G);
- };
+ constexpr bool IsMonotone() const;
// ------------------------------------------------------------------------
// Returns if the color components are all zero, the white component maybe
// anything
// ------------------------------------------------------------------------
- bool IsColorLess() const
- {
- return (R == 0 && B == 0 && G == 0);
- };
+ constexpr bool IsColorLess() const;
// ------------------------------------------------------------------------
// CalculateBrightness will calculate the overall brightness
// NOTE: This is a simple linear brightness
// ------------------------------------------------------------------------
- uint8_t CalculateBrightness() const;
+ constexpr uint8_t CalculateBrightness() const;
// ------------------------------------------------------------------------
// Dim will return a new color that is blended to black with the given ratio
@@ -129,7 +109,7 @@ struct RgbwColor
//
// NOTE: This is a simple linear blend
// ------------------------------------------------------------------------
- RgbwColor Dim(uint8_t ratio) const;
+ constexpr RgbwColor Dim(uint8_t ratio) const;
// ------------------------------------------------------------------------
// Brighten will return a new color that is blended to white with the given ratio
@@ -137,21 +117,21 @@ struct RgbwColor
//
// NOTE: This is a simple linear blend
// ------------------------------------------------------------------------
- RgbwColor Brighten(uint8_t ratio) const;
+ constexpr RgbwColor Brighten(uint8_t ratio) const;
// ------------------------------------------------------------------------
// Darken will adjust the color by the given delta toward black
// NOTE: This is a simple linear change
// delta - (0-255) the amount to dim the color
// ------------------------------------------------------------------------
- void Darken(uint8_t delta);
+ constexpr void Darken(uint8_t delta);
// ------------------------------------------------------------------------
// Lighten will adjust the color by the given delta toward white
// NOTE: This is a simple linear change
// delta - (0-255) the amount to lighten the color
// ------------------------------------------------------------------------
- void Lighten(uint8_t delta);
+ constexpr void Lighten(uint8_t delta);
// ------------------------------------------------------------------------
// LinearBlend between two colors by the amount defined by progress variable
@@ -160,8 +140,8 @@ struct RgbwColor
// progress - (0.0 - 1.0) value where 0 will return left and 1.0 will return right
// and a value between will blend the color weighted linearly between them
// ------------------------------------------------------------------------
- static RgbwColor LinearBlend(const RgbwColor& left, const RgbwColor& right, float progress);
-
+ static constexpr RgbwColor LinearBlend(const RgbwColor& left, const RgbwColor& right, float progress);
+
// ------------------------------------------------------------------------
// BilinearBlend between four colors by the amount defined by 2d variable
// c00 - upper left quadrant color
@@ -171,54 +151,249 @@ struct RgbwColor
// x - unit value (0.0 - 1.0) that defines the blend progress in horizontal space
// y - unit value (0.0 - 1.0) that defines the blend progress in vertical space
// ------------------------------------------------------------------------
- static RgbwColor BilinearBlend(const RgbwColor& c00,
+ static constexpr RgbwColor BilinearBlend(const RgbwColor& c00,
const RgbwColor& c01,
const RgbwColor& c10,
const RgbwColor& c11,
float x,
float y);
- uint16_t CalcTotalTenthMilliAmpere(const SettingsObject& settings)
- {
- auto total = 0;
-
- total += R * settings.RedTenthMilliAmpere / 255;
- total += G * settings.GreenTenthMilliAmpere / 255;
- total += B * settings.BlueTenthMilliAmpere / 255;
- total += W * settings.WhiteCurrent / 255;
-
- return total;
- }
+ constexpr uint16_t CalcTotalTenthMilliAmpere(const SettingsObject& settings) const;
// ------------------------------------------------------------------------
// Red, Green, Blue, White color members (0-255) where
// (0,0,0,0) is black and (255,255,255, 0) and (0,0,0,255) is white
// Note (255,255,255,255) is extreme bright white
// ------------------------------------------------------------------------
- uint8_t R;
- uint8_t G;
- uint8_t B;
- uint8_t W;
+ uint8_t R{};
+ uint8_t G{};
+ uint8_t B{};
+ uint8_t W{};
private:
- inline static uint8_t _elementDim(uint8_t value, uint8_t ratio)
+ inline static constexpr uint8_t _elementDim(uint8_t value, uint8_t ratio);
+ inline static constexpr uint8_t _elementBrighten(uint8_t value, uint8_t ratio);
+};
+
+#include "RgbColor.h"
+#include "HslColor.h"
+#include "HsbColor.h"
+
+constexpr RgbwColor::RgbwColor() = default;
+
+constexpr RgbwColor::RgbwColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w) :
+ R{r}, G{g}, B{b}, W{w}
+{
+}
+
+constexpr RgbwColor::RgbwColor(uint8_t brightness) :
+ R{}, G{}, B{}, W{brightness}
+{
+}
+
+constexpr RgbwColor::RgbwColor(const RgbwColor& color) = default;
+
+constexpr RgbwColor::RgbwColor(const RgbColor& color) :
+ R{color.R},
+ G{color.G},
+ B{color.B},
+ W{}
+{
+}
+
+constexpr RgbwColor::RgbwColor(const HslColor& color) :
+ RgbwColor{RgbColor{color}}
+{
+}
+
+constexpr RgbwColor::RgbwColor(const HsbColor& color) :
+ RgbwColor{RgbColor{color}}
+{
+}
+
+constexpr bool RgbwColor::operator==(const RgbwColor& other) const
+{
+ return (R == other.R && G == other.G && B == other.B && W == other.W);
+}
+
+constexpr bool RgbwColor::operator!=(const RgbwColor& other) const
+{
+ return !(*this == other);
+}
+
+constexpr bool RgbwColor::IsMonotone() const
+{
+ return (R == B && R == G);
+}
+
+constexpr bool RgbwColor::IsColorLess() const
+{
+ return (R == 0 && B == 0 && G == 0);
+}
+
+constexpr uint8_t RgbwColor::CalculateBrightness() const
+{
+ uint8_t colorB = (uint8_t)(((uint16_t)R + (uint16_t)G + (uint16_t)B) / 3);
+ if (W > colorB)
{
- return (static_cast(value) * (static_cast(ratio) + 1)) >> 8;
+ return W;
+ }
+ else
+ {
+ return colorB;
+ }
+}
+
+constexpr RgbwColor RgbwColor::Dim(uint8_t ratio) const
+{
+ // specifically avoids float math
+ return RgbwColor{_elementDim(R, ratio), _elementDim(G, ratio), _elementDim(B, ratio), _elementDim(W, ratio)};
+}
+
+constexpr RgbwColor RgbwColor::Brighten(uint8_t ratio) const
+{
+ // specifically avoids float math
+ return RgbwColor{_elementBrighten(R, ratio), _elementBrighten(G, ratio), _elementBrighten(B, ratio), _elementBrighten(W, ratio)};
+}
+
+constexpr void RgbwColor::Darken(uint8_t delta)
+{
+ if (R > delta)
+ {
+ R -= delta;
+ }
+ else
+ {
+ R = 0;
}
- inline static uint8_t _elementBrighten(uint8_t value, uint8_t ratio)
+ if (G > delta)
{
- uint16_t element = ((static_cast(value) + 1) << 8) / (static_cast(ratio) + 1);
+ G -= delta;
+ }
+ else
+ {
+ G = 0;
+ }
- if (element > 255)
+ if (B > delta)
+ {
+ B -= delta;
+ }
+ else
+ {
+ B = 0;
+ }
+
+ if (W > delta)
+ {
+ W -= delta;
+ }
+ else
+ {
+ W = 0;
+ }
+}
+
+constexpr void RgbwColor::Lighten(uint8_t delta)
+{
+ if (IsColorLess())
+ {
+ if (W < 255 - delta)
{
- element = 255;
+ W += delta;
}
else
{
- element -= 1;
+ W = 255;
}
- return element;
}
-};
+ else
+ {
+ if (R < 255 - delta)
+ {
+ R += delta;
+ }
+ else
+ {
+ R = 255;
+ }
+ if (G < 255 - delta)
+ {
+ G += delta;
+ }
+ else
+ {
+ G = 255;
+ }
+
+ if (B < 255 - delta)
+ {
+ B += delta;
+ }
+ else
+ {
+ B = 255;
+ }
+ }
+}
+
+constexpr RgbwColor RgbwColor::LinearBlend(const RgbwColor& left, const RgbwColor& right, float progress)
+{
+ return RgbwColor( left.R + ((right.R - left.R) * progress),
+ left.G + ((right.G - left.G) * progress),
+ left.B + ((right.B - left.B) * progress),
+ left.W + ((right.W - left.W) * progress) );
+}
+
+constexpr RgbwColor RgbwColor::BilinearBlend(const RgbwColor& c00,
+ const RgbwColor& c01,
+ const RgbwColor& c10,
+ const RgbwColor& c11,
+ float x,
+ float y)
+{
+ float v00 = (1.0f - x) * (1.0f - y);
+ float v10 = x * (1.0f - y);
+ float v01 = (1.0f - x) * y;
+ float v11 = x * y;
+
+ return RgbwColor(
+ c00.R * v00 + c10.R * v10 + c01.R * v01 + c11.R * v11,
+ c00.G * v00 + c10.G * v10 + c01.G * v01 + c11.G * v11,
+ c00.B * v00 + c10.B * v10 + c01.B * v01 + c11.B * v11,
+ c00.W * v00 + c10.W * v10 + c01.W * v01 + c11.W * v11 );
+}
+
+constexpr uint16_t RgbwColor::CalcTotalTenthMilliAmpere(const SettingsObject& settings) const
+{
+ auto total = 0;
+
+ total += R * settings.RedTenthMilliAmpere / 255;
+ total += G * settings.GreenTenthMilliAmpere / 255;
+ total += B * settings.BlueTenthMilliAmpere / 255;
+ total += W * settings.WhiteCurrent / 255;
+
+ return total;
+}
+
+constexpr uint8_t RgbwColor::_elementDim(uint8_t value, uint8_t ratio)
+{
+ return (static_cast(value) * (static_cast(ratio) + 1)) >> 8;
+}
+
+constexpr uint8_t RgbwColor::_elementBrighten(uint8_t value, uint8_t ratio)
+{
+ uint16_t element = ((static_cast(value) + 1) << 8) / (static_cast(ratio) + 1);
+
+ if (element > 255)
+ {
+ element = 255;
+ }
+ else
+ {
+ element -= 1;
+ }
+ return element;
+}