Rgb color enhancements (#391)

* Rgb48Color

* Rgb16Color

* Discord readme
This commit is contained in:
Michael Miller
2020-12-26 09:54:21 -08:00
committed by GitHub
parent f33d78d3dc
commit de32dd9cc8
15 changed files with 940 additions and 134 deletions

View File

@@ -12,6 +12,7 @@ Please read this best practices link before connecting your NeoPixels, it will s
For quick questions and support:
* [Try the new Github Discussions](https://github.com/Makuna/NeoPixelBus/discussions)
* [Discord NeoPixelBus Invitation](https://discord.gg/c6FrysvZyV) or if you are already a member of [Discord Server NeoPixelBus](https://discord.com/channels/789177382221119519/789177382221119521)
* Or jump on Gitter
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Makuna/NeoPixelBus?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)

View File

@@ -10,6 +10,8 @@ NeoPixelBus KEYWORD1
NeoPixelSegmentBus KEYWORD1
RgbwColor KEYWORD1
RgbColor KEYWORD1
Rgb16Color KEYWORD1
Rgb48Color KEYWORD1
HslColor KEYWORD1
HsbColor KEYWORD1
HtmlColor KEYWORD1

View File

@@ -51,9 +51,13 @@ License along with NeoPixel. If not, see
#include "internal/NeoSettings.h"
#include "internal/RgbColor.h"
#include "internal/Rgb16Color.h"
#include "internal/Rgb48Color.h"
#include "internal/HslColor.h"
#include "internal/HsbColor.h"
#include "internal/HtmlColor.h"
#include "internal/RgbwColor.h"
#include "internal/SegmentDigit.h"

View File

@@ -25,18 +25,13 @@ License along with NeoPixel. If not, see
-------------------------------------------------------------------------*/
#include "RgbColor.h"
#include "Rgb48Color.h"
#include "HsbColor.h"
HsbColor::HsbColor(const RgbColor& color)
void HsbColor::_RgbToHsb(float r, float g, float b, HsbColor* 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 min = (r < g&& r < b) ? r : (g < b) ? g : b;
float d = max - min;
@@ -62,7 +57,27 @@ HsbColor::HsbColor(const RgbColor& color)
}
H = h;
S = s;
B = v;
color->H = h;
color->S = s;
color->B = v;
}
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;
_RgbToHsb(r, g, b, this);
}
HsbColor::HsbColor(const Rgb48Color& color)
{
// convert colors to float between (0.0 - 1.0)
float r = color.R / 65535.0f;
float g = color.G / 65535.0f;
float b = color.B / 65535.0f;
_RgbToHsb(r, g, b, this);
}

View File

@@ -48,6 +48,11 @@ struct HsbColor
// ------------------------------------------------------------------------
HsbColor(const RgbColor& color);
// ------------------------------------------------------------------------
// Construct a HsbColor using Rgb48Color
// ------------------------------------------------------------------------
HsbColor(const Rgb48Color& 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
@@ -109,5 +114,8 @@ struct HsbColor
float H;
float S;
float B;
private:
static void _RgbToHsb(float r, float g, float b, HsbColor* color);
};

View File

@@ -26,16 +26,11 @@ License along with NeoPixel. If not, see
-------------------------------------------------------------------------*/
#include "RgbColor.h"
#include "Rgb48Color.h"
#include "HslColor.h"
HslColor::HslColor(const RgbColor& color)
void HslColor::_RgbToHsl(float r, float g, float b, HslColor* 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;
@@ -66,7 +61,27 @@ HslColor::HslColor(const RgbColor& color)
h /= 6.0f;
}
H = h;
S = s;
L = l;
color->H = h;
color->S = s;
color->L = l;
}
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;
_RgbToHsl(r, g, b, this);
}
HslColor::HslColor(const Rgb48Color& color)
{
// convert colors to float between (0.0 - 1.0)
float r = color.R / 65535.0f;
float g = color.G / 65535.0f;
float b = color.B / 65535.0f;
_RgbToHsl(r, g, b, this);
}

View File

@@ -49,6 +49,11 @@ struct HslColor
// ------------------------------------------------------------------------
HslColor(const RgbColor& color);
// ------------------------------------------------------------------------
// Construct a HslColor using Rgb48Color
// ------------------------------------------------------------------------
HslColor(const Rgb48Color& 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
@@ -109,5 +114,9 @@ struct HslColor
float H;
float S;
float L;
private:
static void _RgbToHsl(float r, float g, float b, HslColor* color);
};

272
src/internal/Rgb16Color.h Normal file
View File

@@ -0,0 +1,272 @@
/*-------------------------------------------------------------------------
Rgb16Color provides a color object that stores in only 16 bits, aka 565 format
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
<http://www.gnu.org/licenses/>.
-------------------------------------------------------------------------*/
#pragma once
#include <Arduino.h>
#include "NeoSettings.h"
#include "RgbColorBase.h"
// ------------------------------------------------------------------------
// Rgb16Color represents a color object that is represented by Red, Green, Blue
// component values stored in a single 16 bit value using 565 model.
// It contains helpful color routines to manipulate the color.
// ------------------------------------------------------------------------
struct Rgb16Color : RgbColorBase
{
typedef NeoRgbCurrentSettings SettingsObject;
// ------------------------------------------------------------------------
// Construct a Rgb16Color using R, G, B values (0-255)
// ------------------------------------------------------------------------
Rgb16Color(uint8_t r, uint8_t g, uint8_t b)
{
setR(r);
setG(g);
setB(b);
};
// ------------------------------------------------------------------------
// Construct a Rgb16Color using a single brightness value (0-255)
// This works well for creating gray tone colors
// (0) = black, (255) = white, (128) = gray
// ------------------------------------------------------------------------
Rgb16Color(uint8_t brightness)
{
setR(brightness);
setG(brightness);
setB(brightness);
};
// ------------------------------------------------------------------------
// Construct a Rgb16Color using HtmlColor
// ------------------------------------------------------------------------
Rgb16Color(const HtmlColor& color)
{
RgbColor converted = color;
setR(converted.R);
setG(converted.G);
setB(converted.B);
};
// ------------------------------------------------------------------------
// Construct a Rgb16Color using HslColor
// ------------------------------------------------------------------------
Rgb16Color(const HslColor& color)
{
RgbColor converted = color;
setR(converted.R);
setG(converted.G);
setB(converted.B);
};
// ------------------------------------------------------------------------
// Construct a Rgb16Color using HsbColor
// ------------------------------------------------------------------------
Rgb16Color(const HsbColor& color)
{
RgbColor converted = color;
setR(converted.R);
setG(converted.G);
setB(converted.B);
};
// ------------------------------------------------------------------------
// Construct a Rgb16Color that will have its values set in latter operations
// CAUTION: The _c members are not initialized and may not be consistent
// ------------------------------------------------------------------------
Rgb16Color()
{
};
// ------------------------------------------------------------------------
// properties
// ------------------------------------------------------------------------
void setR(uint8_t r)
{
_c &= 0x07ff;
_c |= ((r & 0xf8) << 8);
};
uint8_t getR() const
{
return (_c & 0xf800) >> 8;
};
void setG(uint8_t g)
{
_c &= 0xf81f;
_c |= ((g & 0xfe) << 3);
};
uint8_t getG() const
{
return (_c & 0x07e0) >> 3;
};
void setB(uint8_t b)
{
_c &= 0xffe0;
_c |= ((b & 0xf8) >> 3);
};
uint8_t getB() const
{
return (_c & 0x001f) << 3;
};
// ------------------------------------------------------------------------
// Comparison operators
// ------------------------------------------------------------------------
bool operator==(const Rgb16Color& other) const
{
return (_c == other._c);
};
bool operator!=(const Rgb16Color& other) const
{
return !(*this == other);
};
// ------------------------------------------------------------------------
// CalculateBrightness will calculate the overall brightness
// NOTE: This is a simple linear brightness
// ------------------------------------------------------------------------
uint8_t CalculateBrightness() const
{
RgbColor converted = *this;
return converted.CalculateBrightness();
};
// ------------------------------------------------------------------------
// 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
// ------------------------------------------------------------------------
Rgb16Color Dim(uint8_t ratio) const
{
RgbColor converted = *this;
RgbColor result = converted.Dim(ratio);
return Rgb16Color(result.R, result.G, result.B);
};
// ------------------------------------------------------------------------
// 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
// ------------------------------------------------------------------------
Rgb16Color Brighten(uint8_t ratio) const
{
RgbColor converted = *this;
RgbColor result = converted.Brighten(ratio);
return Rgb16Color(result.R, result.G, result.B);
};
// ------------------------------------------------------------------------
// 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)
{
RgbColor converted = *this;
converted.Darken(delta);
setR(converted.R);
setG(converted.G);
setB(converted.B);
};
// ------------------------------------------------------------------------
// 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)
{
RgbColor converted = *this;
converted.Lighten(delta);
setR(converted.R);
setG(converted.G);
setB(converted.B);
};
// ------------------------------------------------------------------------
// LinearBlend between two colors by the amount defined by progress variable
// left - the color to start the blend at
// right - the color to end the blend at
// 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 Rgb16Color LinearBlend(const Rgb16Color& left, const Rgb16Color& right, float progress)
{
RgbColor result = RgbColor::LinearBlend(left, right, progress);
return Rgb16Color(result.R, result.G, result.B);
};
// ------------------------------------------------------------------------
// BilinearBlend between four colors by the amount defined by 2d variable
// c00 - upper left quadrant color
// c01 - upper right quadrant color
// c10 - lower left quadrant color
// c11 - lower right quadrant color
// 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 Rgb16Color BilinearBlend(const Rgb16Color& c00,
const Rgb16Color& c01,
const Rgb16Color& c10,
const Rgb16Color& c11,
float x,
float y)
{
RgbColor result = RgbColor::BilinearBlend(c00, c01, c10, c11, x, y);
return Rgb16Color(result.R, result.G, result.B);
};
uint32_t CalcTotalTenthMilliAmpere(const SettingsObject& settings)
{
auto total = 0;
total += getR() * settings.RedTenthMilliAmpere / 255;
total += getG() * settings.GreenTenthMilliAmpere / 255;
total += getB() * settings.BlueTenthMilliAmpere / 255;
return total;
};
protected:
uint16_t _c;
};

170
src/internal/Rgb48Color.cpp Normal file
View File

@@ -0,0 +1,170 @@
/*-------------------------------------------------------------------------
Rgb48Color 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
<http://www.gnu.org/licenses/>.
-------------------------------------------------------------------------*/
#include "Rgb48Color.h"
#include "RgbColor.h"
#include "HslColor.h"
#include "HsbColor.h"
#include "HtmlColor.h"
Rgb48Color::Rgb48Color(const HtmlColor& color)
{
uint32_t temp = color.Color;
B = (temp & 0xff);
temp = temp >> 8;
G = (temp & 0xff);
temp = temp >> 8;
R = (temp & 0xff);
};
Rgb48Color::Rgb48Color(const HslColor& color)
{
float r;
float g;
float b;
_HslToRgb(color, &r, &g, &b);
R = (uint16_t)(r * Max);
G = (uint16_t)(g * Max);
B = (uint16_t)(b * Max);
}
Rgb48Color::Rgb48Color(const HsbColor& color)
{
float r;
float g;
float b;
_HsbToRgb(color, &r, &g, &b);
R = (uint16_t)(r * Max);
G = (uint16_t)(g * Max);
B = (uint16_t)(b * Max);
}
uint16_t Rgb48Color::CalculateBrightness() const
{
return (uint16_t)(((uint32_t)R + (uint32_t)G + (uint32_t)B) / 3);
}
Rgb48Color Rgb48Color::Dim(uint16_t ratio) const
{
// specifically avoids float math
return Rgb48Color(_elementDim(R, ratio), _elementDim(G, ratio), _elementDim(B, ratio));
}
Rgb48Color Rgb48Color::Brighten(uint16_t ratio) const
{
// specifically avoids float math
return Rgb48Color(_elementBrighten(R, ratio), _elementBrighten(G, ratio), _elementBrighten(B, ratio));
}
void Rgb48Color::Darken(uint16_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 Rgb48Color::Lighten(uint16_t delta)
{
if (R < Max - delta)
{
R += delta;
}
else
{
R = Max;
}
if (G < Max - delta)
{
G += delta;
}
else
{
G = Max;
}
if (B < Max - delta)
{
B += delta;
}
else
{
B = Max;
}
}
Rgb48Color Rgb48Color::LinearBlend(const Rgb48Color& left, const Rgb48Color& right, float progress)
{
return Rgb48Color( left.R + ((right.R - left.R) * progress),
left.G + ((right.G - left.G) * progress),
left.B + ((right.B - left.B) * progress));
}
Rgb48Color Rgb48Color::BilinearBlend(const Rgb48Color& c00,
const Rgb48Color& c01,
const Rgb48Color& c10,
const Rgb48Color& 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 Rgb48Color(
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);
}

210
src/internal/Rgb48Color.h Normal file
View File

@@ -0,0 +1,210 @@
/*-------------------------------------------------------------------------
Rgb48Color provides a color object that contains 16bit color elements
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
<http://www.gnu.org/licenses/>.
-------------------------------------------------------------------------*/
#pragma once
#include <Arduino.h>
#include "NeoSettings.h"
#include "RgbColorBase.h"
#include "RgbColor.h"
// ------------------------------------------------------------------------
// Rgb48Color represents a color object that is represented by Red, Green, Blue
// component values. It contains helpful color routines to manipulate the
// color.
// ------------------------------------------------------------------------
struct Rgb48Color : RgbColorBase
{
typedef NeoRgbCurrentSettings SettingsObject;
// ------------------------------------------------------------------------
// Construct a Rgb48Color using R, G, B values (0-65535)
// ------------------------------------------------------------------------
Rgb48Color(uint16_t r, uint16_t g, uint16_t b) :
R(r), G(g), B(b)
{
};
// ------------------------------------------------------------------------
// Construct a Rgb48Color using a single brightness value (0-65535)
// This works well for creating gray tone colors
// (0) = black, (65535) = white, (32768) = gray
// ------------------------------------------------------------------------
Rgb48Color(uint16_t brightness) :
R(brightness), G(brightness), B(brightness)
{
};
// ------------------------------------------------------------------------
// Construct a Rgb48Color using RgbColor
// ------------------------------------------------------------------------
Rgb48Color(const RgbColor& color)
{
R = (color.R == 0) ? 0 : (color.R << 8 | 0xff);
G = (color.G == 0) ? 0 : (color.G << 8 | 0xff);
B = (color.B == 0) ? 0 : (color.B << 8 | 0xff);
}
// ------------------------------------------------------------------------
// Construct a Rgb48Color using HtmlColor
// ------------------------------------------------------------------------
Rgb48Color(const HtmlColor& color);
// ------------------------------------------------------------------------
// Construct a Rgb48Color using HslColor
// ------------------------------------------------------------------------
Rgb48Color(const HslColor& color);
// ------------------------------------------------------------------------
// Construct a Rgb48Color using HsbColor
// ------------------------------------------------------------------------
Rgb48Color(const HsbColor& color);
// ------------------------------------------------------------------------
// Construct a Rgb48Color that will have its values set in latter operations
// CAUTION: The R,G,B members are not initialized and may not be consistent
// ------------------------------------------------------------------------
Rgb48Color()
{
};
// ------------------------------------------------------------------------
// Comparison operators
// ------------------------------------------------------------------------
bool operator==(const Rgb48Color& other) const
{
return (R == other.R && G == other.G && B == other.B);
};
bool operator!=(const Rgb48Color& other) const
{
return !(*this == other);
};
// ------------------------------------------------------------------------
// CalculateBrightness will calculate the overall brightness
// NOTE: This is a simple linear brightness
// ------------------------------------------------------------------------
uint16_t CalculateBrightness() const;
// ------------------------------------------------------------------------
// Dim will return a new color that is blended to black with the given ratio
// ratio - (0-65535) where 65535 will return the original color and 0 will return black
//
// NOTE: This is a simple linear blend
// ------------------------------------------------------------------------
Rgb48Color Dim(uint16_t ratio) const;
// ------------------------------------------------------------------------
// Brighten will return a new color that is blended to white with the given ratio
// ratio - (0-65535) where 65535 will return the original color and 0 will return white
//
// NOTE: This is a simple linear blend
// ------------------------------------------------------------------------
Rgb48Color Brighten(uint16_t ratio) const;
// ------------------------------------------------------------------------
// Darken will adjust the color by the given delta toward black
// NOTE: This is a simple linear change
// delta - (0-65535) the amount to dim the color
// ------------------------------------------------------------------------
void Darken(uint16_t delta);
// ------------------------------------------------------------------------
// Lighten will adjust the color by the given delta toward white
// NOTE: This is a simple linear change
// delta - (0-65535) the amount to lighten the color
// ------------------------------------------------------------------------
void Lighten(uint16_t delta);
// ------------------------------------------------------------------------
// LinearBlend between two colors by the amount defined by progress variable
// left - the color to start the blend at
// right - the color to end the blend at
// 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 Rgb48Color LinearBlend(const Rgb48Color& left, const Rgb48Color& right, float progress);
// ------------------------------------------------------------------------
// BilinearBlend between four colors by the amount defined by 2d variable
// c00 - upper left quadrant color
// c01 - upper right quadrant color
// c10 - lower left quadrant color
// c11 - lower right quadrant color
// 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 Rgb48Color BilinearBlend(const Rgb48Color& c00,
const Rgb48Color& c01,
const Rgb48Color& c10,
const Rgb48Color& c11,
float x,
float y);
uint32_t CalcTotalTenthMilliAmpere(const SettingsObject& settings)
{
auto total = 0;
total += R * settings.RedTenthMilliAmpere / Max;
total += G * settings.GreenTenthMilliAmpere / Max;
total += B * settings.BlueTenthMilliAmpere / Max;
return total;
}
// ------------------------------------------------------------------------
// Red, Green, Blue color members (0-65535) where
// (0,0,0) is black and (65535,65535,65535) is white
// ------------------------------------------------------------------------
uint16_t R;
uint16_t G;
uint16_t B;
const static uint16_t Max = 65535;
private:
inline static uint16_t _elementDim(uint16_t value, uint16_t ratio)
{
return (static_cast<uint32_t>(value) * (static_cast<uint32_t>(ratio) + 1)) >> 8;
}
inline static uint16_t _elementBrighten(uint16_t value, uint16_t ratio)
{
uint32_t element = ((static_cast<uint32_t>(value) + 1) << 8) / (static_cast<uint32_t>(ratio) + 1);
if (element > Max)
{
element = Max;
}
else
{
element -= 1;
}
return element;
}
};

View File

@@ -25,27 +25,17 @@ License along with NeoPixel. If not, see
-------------------------------------------------------------------------*/
#include "RgbColor.h"
#include "Rgb16Color.h"
#include "Rgb48Color.h"
#include "HslColor.h"
#include "HsbColor.h"
#include "HtmlColor.h"
static float _CalcColor(float p, float q, float t)
RgbColor::RgbColor(const Rgb16Color& color)
{
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;
R = color.getR();
G = color.getG();
B = color.getB();
}
RgbColor::RgbColor(const HtmlColor& color)
@@ -65,27 +55,11 @@ RgbColor::RgbColor(const HslColor& color)
float g;
float b;
float h = color.H;
float s = color.S;
float l = color.L;
_HslToRgb(color, &r, &g, &b);
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);
R = (uint8_t)(r * Max);
G = (uint8_t)(g * Max);
B = (uint8_t)(b * Max);
}
RgbColor::RgbColor(const HsbColor& color)
@@ -94,68 +68,11 @@ RgbColor::RgbColor(const HsbColor& color)
float g;
float b;
float h = color.H;
float s = color.S;
float v = color.B;
_HsbToRgb(color, &r, &g, &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);
R = (uint8_t)(r * Max);
G = (uint8_t)(g * Max);
B = (uint8_t)(b * Max);
}
uint8_t RgbColor::CalculateBrightness() const
@@ -207,31 +124,31 @@ void RgbColor::Darken(uint8_t delta)
void RgbColor::Lighten(uint8_t delta)
{
if (R < 255 - delta)
if (R < Max - delta)
{
R += delta;
}
else
{
R = 255;
R = Max;
}
if (G < 255 - delta)
if (G < Max - delta)
{
G += delta;
}
else
{
G = 255;
G = Max;
}
if (B < 255 - delta)
if (B < Max - delta)
{
B += delta;
}
else
{
B = 255;
B = Max;
}
}

View File

@@ -27,17 +27,15 @@ License along with NeoPixel. If not, see
#include <Arduino.h>
#include "NeoSettings.h"
#include "RgbColorBase.h"
struct HslColor;
struct HsbColor;
struct HtmlColor;
// ------------------------------------------------------------------------
// RgbColor represents a color object that is represented by Red, Green, Blue
// component values. It contains helpful color routines to manipulate the
// color.
// ------------------------------------------------------------------------
struct RgbColor
struct RgbColor : RgbColorBase
{
typedef NeoRgbCurrentSettings SettingsObject;
@@ -59,6 +57,11 @@ struct RgbColor
{
};
// ------------------------------------------------------------------------
// Construct a RgbColor using Rgb16Color
// ------------------------------------------------------------------------
RgbColor(const Rgb16Color& color);
// ------------------------------------------------------------------------
// Construct a RgbColor using HtmlColor
// ------------------------------------------------------------------------
@@ -74,6 +77,7 @@ struct RgbColor
// ------------------------------------------------------------------------
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
@@ -160,9 +164,9 @@ struct RgbColor
{
auto total = 0;
total += R * settings.RedTenthMilliAmpere / 255;
total += G * settings.GreenTenthMilliAmpere / 255;
total += B * settings.BlueTenthMilliAmpere / 255;
total += R * settings.RedTenthMilliAmpere / Max;
total += G * settings.GreenTenthMilliAmpere / Max;
total += B * settings.BlueTenthMilliAmpere / Max;
return total;
}
@@ -175,6 +179,8 @@ struct RgbColor
uint8_t G;
uint8_t B;
const static uint8_t Max = 255;
private:
inline static uint8_t _elementDim(uint8_t value, uint8_t ratio)
{
@@ -185,9 +191,9 @@ private:
{
uint16_t element = ((static_cast<uint16_t>(value) + 1) << 8) / (static_cast<uint16_t>(ratio) + 1);
if (element > 255)
if (element > Max)
{
element = 255;
element = Max;
}
else
{

View File

@@ -0,0 +1,134 @@
/*-------------------------------------------------------------------------
RgbColorBase provides a RGB color object common support
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
<http://www.gnu.org/licenses/>.
-------------------------------------------------------------------------*/
#include "RgbColorBase.h"
#include "RgbColor.h"
#include "Rgb48Color.h"
#include "HslColor.h"
#include "HsbColor.h"
#include "HtmlColor.h"
float RgbColorBase::_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;
}
void RgbColorBase::_HslToRgb(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);
}
}
void RgbColorBase::_HsbToRgb(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;
}
}
}

View File

@@ -0,0 +1,42 @@
/*-------------------------------------------------------------------------
RgbColorBase provides a RGB color object common support
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
<http://www.gnu.org/licenses/>.
-------------------------------------------------------------------------*/
#pragma once
struct HslColor;
struct HsbColor;
struct HtmlColor;
struct Rgb16Color;
struct RgbColorBase
{
protected:
static float _CalcColor(float p, float q, float t);
static void _HslToRgb(const HslColor& color, float* r, float* g, float* b);
static void _HsbToRgb(const HsbColor& color, float* r, float* g, float* b);
};

View File

@@ -25,6 +25,7 @@ License along with NeoPixel. If not, see
-------------------------------------------------------------------------*/
#include "RgbColor.h"
#include "Rgb48Color.h"
#include "HslColor.h"
#include "HsbColor.h"
#include "RgbwColor.h"