2018-01-15 00:20:23 +01:00
|
|
|
/*
|
|
|
|
* Color conversion methods
|
|
|
|
*/
|
|
|
|
void colorCTtoRGB(uint16_t mired, uint8_t* rgb) //white spectrum to rgb
|
|
|
|
{
|
2018-02-28 00:27:10 +01:00
|
|
|
//this is only an approximation using WS2812B with gamma correction enabled
|
|
|
|
if (mired > 475)
|
|
|
|
{
|
|
|
|
rgb[0]=255;rgb[1]=199;rgb[2]=92;//500
|
|
|
|
} else if (mired > 425)
|
|
|
|
{
|
|
|
|
rgb[0]=255;rgb[1]=213;rgb[2]=118;//450
|
|
|
|
} else if (mired > 375)
|
|
|
|
{
|
|
|
|
rgb[0]=255;rgb[1]=216;rgb[2]=118;//400
|
|
|
|
} else if (mired > 325)
|
|
|
|
{
|
|
|
|
rgb[0]=255;rgb[1]=234;rgb[2]=140;//350
|
|
|
|
} else if (mired > 275)
|
|
|
|
{
|
|
|
|
rgb[0]=255;rgb[1]=243;rgb[2]=160;//300
|
|
|
|
} else if (mired > 225)
|
|
|
|
{
|
|
|
|
rgb[0]=250;rgb[1]=255;rgb[2]=188;//250
|
|
|
|
} else if (mired > 175)
|
|
|
|
{
|
|
|
|
rgb[0]=247;rgb[1]=255;rgb[2]=215;//200
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
rgb[0]=237;rgb[1]=255;rgb[2]=239;//150
|
|
|
|
}
|
2018-01-15 00:20:23 +01:00
|
|
|
}
|
|
|
|
|
2018-02-28 00:27:10 +01:00
|
|
|
void colorHStoRGB(uint16_t hue, uint8_t sat, uint8_t* rgb) //hue, sat to rgb
|
2018-01-15 00:20:23 +01:00
|
|
|
{
|
2018-02-28 00:27:10 +01:00
|
|
|
float h = ((float)hue)/65535.0;
|
|
|
|
float s = ((float)sat)/255.0;
|
|
|
|
uint8_t i = floor(h*6);
|
|
|
|
float f = h * 6-i;
|
|
|
|
float p = 255 * (1-s);
|
|
|
|
float q = 255 * (1-f*s);
|
|
|
|
float t = 255 * (1-(1-f)*s);
|
|
|
|
switch (i%6) {
|
|
|
|
case 0: rgb[0]=255,rgb[1]=t,rgb[2]=p;break;
|
|
|
|
case 1: rgb[0]=q,rgb[1]=255,rgb[2]=p;break;
|
|
|
|
case 2: rgb[0]=p,rgb[1]=255,rgb[2]=t;break;
|
|
|
|
case 3: rgb[0]=p,rgb[1]=q,rgb[2]=255;break;
|
|
|
|
case 4: rgb[0]=t,rgb[1]=p,rgb[2]=255;break;
|
|
|
|
case 5: rgb[0]=255,rgb[1]=p,rgb[2]=q;
|
|
|
|
}
|
2018-01-15 00:20:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void colorXYtoRGB(float x, float y, uint8_t* rgb) //coordinates to rgb (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy)
|
|
|
|
{
|
|
|
|
float z = 1.0f - x - y;
|
|
|
|
float X = (1.0f / y) * x;
|
|
|
|
float Z = (1.0f / y) * z;
|
2018-02-28 00:27:10 +01:00
|
|
|
float r = (int)255*(X * 1.656492f - 0.354851f - Z * 0.255038f);
|
|
|
|
float g = (int)255*(-X * 0.707196f + 1.655397f + Z * 0.036152f);
|
|
|
|
float b = (int)255*(X * 0.051713f - 0.121364f + Z * 1.011530f);
|
|
|
|
if (r > b && r > g && r > 1.0f) {
|
|
|
|
// red is too big
|
|
|
|
g = g / r;
|
|
|
|
b = b / r;
|
|
|
|
r = 1.0f;
|
|
|
|
} else if (g > b && g > r && g > 1.0f) {
|
|
|
|
// green is too big
|
|
|
|
r = r / g;
|
|
|
|
b = b / g;
|
|
|
|
g = 1.0f;
|
|
|
|
} else if (b > r && b > g && b > 1.0f) {
|
|
|
|
// blue is too big
|
|
|
|
r = r / b;
|
|
|
|
g = g / b;
|
|
|
|
b = 1.0f;
|
|
|
|
}
|
|
|
|
// Apply gamma correction
|
|
|
|
r = r <= 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * pow(r, (1.0f / 2.4f)) - 0.055f;
|
|
|
|
g = g <= 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * pow(g, (1.0f / 2.4f)) - 0.055f;
|
|
|
|
b = b <= 0.0031308f ? 12.92f * b : (1.0f + 0.055f) * pow(b, (1.0f / 2.4f)) - 0.055f;
|
|
|
|
|
|
|
|
if (r > b && r > g) {
|
|
|
|
// red is biggest
|
|
|
|
if (r > 1.0f) {
|
|
|
|
g = g / r;
|
|
|
|
b = b / r;
|
|
|
|
r = 1.0f;
|
|
|
|
}
|
2018-03-06 23:47:08 +01:00
|
|
|
} else if (g > b && g > r) {
|
2018-02-28 00:27:10 +01:00
|
|
|
// green is biggest
|
|
|
|
if (g > 1.0f) {
|
|
|
|
r = r / g;
|
|
|
|
b = b / g;
|
|
|
|
g = 1.0f;
|
|
|
|
}
|
2018-03-06 23:47:08 +01:00
|
|
|
} else if (b > r && b > g) {
|
2018-02-28 00:27:10 +01:00
|
|
|
// blue is biggest
|
|
|
|
if (b > 1.0f) {
|
|
|
|
r = r / b;
|
|
|
|
g = g / b;
|
|
|
|
b = 1.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rgb[0] = 255.0*r;
|
|
|
|
rgb[1] = 255.0*g;
|
|
|
|
rgb[2] = 255.0*b;
|
2018-01-15 00:20:23 +01:00
|
|
|
}
|
|
|
|
|
2018-02-28 00:27:10 +01:00
|
|
|
void colorRGBtoXY(uint8_t* rgb, float* xy) //rgb to coordinates (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy)
|
|
|
|
{
|
|
|
|
float X = rgb[0] * 0.664511f + rgb[1] * 0.154324f + rgb[2] * 0.162028f;
|
|
|
|
float Y = rgb[0] * 0.283881f + rgb[1] * 0.668433f + rgb[2] * 0.047685f;
|
|
|
|
float Z = rgb[0] * 0.000088f + rgb[1] * 0.072310f + rgb[2] * 0.986039f;
|
|
|
|
xy[0] = X / (X + Y + Z);
|
|
|
|
xy[1] = Y / (X + Y + Z);
|
|
|
|
}
|
2018-01-15 00:20:23 +01:00
|
|
|
|
2018-03-06 23:47:08 +01:00
|
|
|
/*//For some reason min and max are not declared here
|
|
|
|
|
|
|
|
float minf (float v, float w)
|
|
|
|
{
|
|
|
|
if (w > v) return v;
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
float maxf (float v, float w)
|
|
|
|
{
|
|
|
|
if (w > v) return w;
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
void colorRGBtoRGBW(uint8_t* rgb, uint8_t* wht) //rgb to rgbw, untested and currently unused
|
|
|
|
{
|
|
|
|
*wht = (float)minf(rgb[0],minf(rgb[1],rgb[2]))*0.95;
|
|
|
|
rgb[0]-=wht;
|
|
|
|
rgb[1]-=wht;
|
|
|
|
rgb[2]-=wht;
|
|
|
|
}*/
|
|
|
|
|