From a696afaeb87e18e29c3fd911a1ce6226ad6b78b2 Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Tue, 26 Oct 2021 20:35:45 +0200 Subject: [PATCH] Color mangling macros. Removed legacy Auto White caclulation. --- wled00/FX.cpp | 8 ++-- wled00/FX_fcn.cpp | 73 ++++++++++++++++------------------- wled00/bus_manager.h | 59 +++++++++++++--------------- wled00/colors.cpp | 73 +++++++++++++++-------------------- wled00/data/settings_leds.htm | 2 +- wled00/dmx.cpp | 8 ++-- wled00/fcn_declare.h | 1 - wled00/html_settings.h | 2 +- wled00/json.cpp | 10 ++--- wled00/lx_parser.cpp | 2 +- wled00/set.cpp | 2 +- wled00/wled.h | 6 +++ 12 files changed, 115 insertions(+), 131 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 677f1160..a2b6a959 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -1150,10 +1150,10 @@ uint16_t WS2812FX::mode_fire_flicker(void) { uint32_t it = now / cycleTime; if (SEGENV.step == it) return FRAMETIME; - byte w = (SEGCOLOR(0) >> 24) & 0xFF; - byte r = (SEGCOLOR(0) >> 16) & 0xFF; - byte g = (SEGCOLOR(0) >> 8) & 0xFF; - byte b = (SEGCOLOR(0) & 0xFF); + byte w = (SEGCOLOR(0) >> 24); + byte r = (SEGCOLOR(0) >> 16); + byte g = (SEGCOLOR(0) >> 8); + byte b = (SEGCOLOR(0) ); byte lum = (SEGMENT.palette == 0) ? MAX(w, MAX(r, MAX(g, b))) : 255; lum /= (((256-SEGMENT.intensity)/16)+1); for(uint16_t i = 0; i < SEGLEN; i++) { diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 8f21ac09..345ba64d 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -165,11 +165,7 @@ void WS2812FX::service() { } void WS2812FX::setPixelColor(uint16_t n, uint32_t c) { - uint8_t w = (c >> 24); - uint8_t r = (c >> 16); - uint8_t g = (c >> 8); - uint8_t b = c ; - setPixelColor(n, r, g, b, w); + setPixelColor(n, R(c), G(c), B(c), W(c)); } //used to map from segment index to physical pixel, taking into account grouping, offsets, reverse and mirroring @@ -218,7 +214,7 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) b = scale8(b, _bri_t); w = scale8(w, _bri_t); } - uint32_t col = ((w << 24) | (r << 16) | (g << 8) | (b)); + uint32_t col = RGBW32(r, g, b, w); /* Set all the pixels in the group */ for (uint16_t j = 0; j < SEGMENT.grouping; j++) { @@ -243,8 +239,7 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) } } else { //live data, etc. if (i < customMappingSize) i = customMappingTable[i]; - uint32_t col = ((w << 24) | (r << 16) | (g << 8) | (b)); - busses.setPixelColor(i, col); + busses.setPixelColor(i, RGBW32(r, g, b, w)); } } @@ -297,7 +292,7 @@ void WS2812FX::estimateCurrentAndLimitBri() { uint32_t busPowerSum = 0; for (uint16_t i = 0; i < len; i++) { //sum up the usage of each LED uint32_t c = bus->getPixelColor(i); - byte r = c >> 16, g = c >> 8, b = c, w = c >> 24; + byte r = R(c), g = G(c), b = B(c), w = W(c); if(useWackyWS2815PowerModel) { //ignore white component on WS2815 power calculation busPowerSum += (MAX(MAX(r,g),b)) * 3; @@ -433,7 +428,7 @@ bool WS2812FX::setEffectConfig(uint8_t m, uint8_t s, uint8_t in, uint8_t p) { } void WS2812FX::setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w) { - setColor(slot, ((uint32_t)w << 24) |((uint32_t)r << 16) | ((uint32_t)g << 8) | b); + setColor(slot, RGBW32(r, g, b, w)); } void WS2812FX::setColor(uint8_t slot, uint32_t c) { @@ -758,22 +753,22 @@ uint32_t WS2812FX::color_blend(uint32_t color1, uint32_t color2, uint16_t blend, if(blend == blendmax) return color2; uint8_t shift = b16 ? 16 : 8; - uint32_t w1 = (color1 >> 24) & 0xFF; - uint32_t r1 = (color1 >> 16) & 0xFF; - uint32_t g1 = (color1 >> 8) & 0xFF; - uint32_t b1 = color1 & 0xFF; + uint32_t w1 = W(color1); + uint32_t r1 = R(color1); + uint32_t g1 = G(color1); + uint32_t b1 = B(color1); - uint32_t w2 = (color2 >> 24) & 0xFF; - uint32_t r2 = (color2 >> 16) & 0xFF; - uint32_t g2 = (color2 >> 8) & 0xFF; - uint32_t b2 = color2 & 0xFF; + uint32_t w2 = W(color2); + uint32_t r2 = R(color2); + uint32_t g2 = G(color2); + uint32_t b2 = B(color2); uint32_t w3 = ((w2 * blend) + (w1 * (blendmax - blend))) >> shift; uint32_t r3 = ((r2 * blend) + (r1 * (blendmax - blend))) >> shift; uint32_t g3 = ((g2 * blend) + (g1 * (blendmax - blend))) >> shift; uint32_t b3 = ((b2 * blend) + (b1 * (blendmax - blend))) >> shift; - return ((w3 << 24) | (r3 << 16) | (g3 << 8) | (b3)); + return RGBW32(r3, g3, b3, w3); } /* @@ -801,17 +796,17 @@ void WS2812FX::fade_out(uint8_t rate) { float mappedRate = float(rate) +1.1; uint32_t color = SEGCOLOR(1); // target color - int w2 = (color >> 24) & 0xff; - int r2 = (color >> 16) & 0xff; - int g2 = (color >> 8) & 0xff; - int b2 = color & 0xff; + int w2 = W(color); + int r2 = R(color); + int g2 = G(color); + int b2 = B(color); for(uint16_t i = 0; i < SEGLEN; i++) { color = getPixelColor(i); - int w1 = (color >> 24) & 0xff; - int r1 = (color >> 16) & 0xff; - int g1 = (color >> 8) & 0xff; - int b1 = color & 0xff; + int w1 = W(color); + int r1 = R(color); + int g1 = G(color); + int b1 = B(color); int wdelta = (w2 - w1) / mappedRate; int rdelta = (r2 - r1) / mappedRate; @@ -845,9 +840,9 @@ void WS2812FX::blur(uint8_t blur_amount) cur += carryover; if(i > 0) { uint32_t c = getPixelColor(i-1); - uint8_t r = (c >> 16 & 0xFF); - uint8_t g = (c >> 8 & 0xFF); - uint8_t b = (c & 0xFF); + uint8_t r = R(c); + uint8_t g = G(c); + uint8_t b = B(c); setPixelColor(i-1, qadd8(r, part.red), qadd8(g, part.green), qadd8(b, part.blue)); } setPixelColor(i,cur.red, cur.green, cur.blue); @@ -930,16 +925,16 @@ uint8_t WS2812FX::get_random_wheel_index(uint8_t pos) { uint32_t WS2812FX::crgb_to_col(CRGB fastled) { - return (((uint32_t)fastled.red << 16) | ((uint32_t)fastled.green << 8) | fastled.blue); + return RGBW32(fastled.red, fastled.green, fastled.blue, 0); } CRGB WS2812FX::col_to_crgb(uint32_t color) { CRGB fastled_col; - fastled_col.red = (color >> 16 & 0xFF); - fastled_col.green = (color >> 8 & 0xFF); - fastled_col.blue = (color & 0xFF); + fastled_col.red = R(color); + fastled_col.green = G(color); + fastled_col.blue = B(color); return fastled_col; } @@ -1159,15 +1154,15 @@ uint8_t WS2812FX::gamma8(uint8_t b) uint32_t WS2812FX::gamma32(uint32_t color) { if (!gammaCorrectCol) return color; - uint8_t w = (color >> 24); - uint8_t r = (color >> 16); - uint8_t g = (color >> 8); - uint8_t b = color; + uint8_t w = W(color); + uint8_t r = R(color); + uint8_t g = G(color); + uint8_t b = B(color); w = gammaT[w]; r = gammaT[r]; g = gammaT[g]; b = gammaT[b]; - return ((w << 24) | (r << 16) | (g << 8) | (b)); + return RGBW32(r, g, b, w); } WS2812FX* WS2812FX::instance = nullptr; \ No newline at end of file diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 172bb55e..dd7f1ba1 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -32,6 +32,13 @@ void colorRGBtoRGBW(byte* rgb); #define SET_BIT(var,bit) ((var)|=(uint16_t)(0x0001<<(bit))) #define UNSET_BIT(var,bit) ((var)&=(~(uint16_t)(0x0001<<(bit)))) +//color mangling macros +#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b)))) +#define R(c) (byte((c) >> 16)) +#define G(c) (byte((c) >> 8)) +#define B(c) (byte(c)) +#define W(c) (byte((c) >> 24)) + //temporary struct for passing bus configuration to bus struct BusConfig { uint8_t type = TYPE_WS2812_RGB; @@ -120,24 +127,15 @@ class Bus { switch (_autoWhiteMode) { case RGBW_MODE_MANUAL_ONLY: break; - case RGBW_MODE_LEGACY: - byte rgb[4]; - rgb[0] = c >> 16; - rgb[1] = c >> 8; - rgb[2] = c ; - rgb[3] = c >> 24; - colorRGBtoRGBW(rgb); - c = ((rgb[3] << 24) | (rgb[0] << 16) | (rgb[1] << 8) | (rgb[2])); - break; default: //white value is set to lowest RGB channel, thank you to @Def3nder! - uint8_t r = c >> 16; - uint8_t g = c >> 8; - uint8_t b = c ; - uint8_t w = c >> 24; + uint8_t r = R(c); + uint8_t g = G(c); + uint8_t b = B(c); + uint8_t w = W(c); if (_autoWhiteMode == RGBW_MODE_AUTO_BRIGHTER || w == 0) w = r < g ? (r < b ? r : b) : (g < b ? g : b); if (_autoWhiteMode == RGBW_MODE_AUTO_ACCURATE) { r -= w; g -= w; b -= w; } - c = ((w << 24) | (r << 16) | (g << 8) | (b)); + c = RGBW32(r, g, b, w); break; } return c; @@ -294,10 +292,10 @@ class BusPwm : public Bus { if (pix != 0 || !_valid) return; //only react to first pixel c = colorBalanceFromKelvin(2000+(cct<<5), c); // color correction from CCT (w remains unchanged) if (getAutoWhiteMode() != RGBW_MODE_MANUAL_ONLY) c = autoWhiteCalc(c); - uint8_t r = c >> 16; - uint8_t g = c >> 8; - uint8_t b = c ; - uint8_t w = c >> 24; + uint8_t r = R(c); + uint8_t g = G(c); + uint8_t b = B(c); + uint8_t w = W(c); switch (_type) { case TYPE_ANALOG_1CH: //one channel (white), relies on auto white calculation @@ -324,10 +322,10 @@ class BusPwm : public Bus { void setPixelColor(uint16_t pix, uint32_t c) { if (pix != 0 || !_valid) return; //only react to first pixel if (getAutoWhiteMode() != RGBW_MODE_MANUAL_ONLY) c = autoWhiteCalc(c); - uint8_t r = c >> 16; - uint8_t g = c >> 8; - uint8_t b = c ; - uint8_t w = c >> 24; + uint8_t r = R(c); + uint8_t g = G(c); + uint8_t b = B(c); + uint8_t w = W(c); switch (_type) { case TYPE_ANALOG_1CH: //one channel (white), use highest RGBW value @@ -343,7 +341,7 @@ class BusPwm : public Bus { //does no index check uint32_t getPixelColor(uint16_t pix) { if (!_valid) return 0; - return ((_data[3] << 24) | (_data[0] << 16) | (_data[1] << 8) | (_data[2])); + return RGBW32(_data[0], _data[1], _data[2], _data[3]); } void show() { @@ -442,10 +440,10 @@ class BusNetwork : public Bus { if (!_valid || pix >= _len) return; if (getAutoWhiteMode() != RGBW_MODE_MANUAL_ONLY) c = autoWhiteCalc(c); uint16_t offset = pix * _UDPchannels; - _data[offset] = 0xFF & (c >> 16); - _data[offset+1] = 0xFF & (c >> 8); - _data[offset+2] = 0xFF & (c ); - if (_rgbw) _data[offset+3] = 0xFF & (c >> 24); + _data[offset] = R(c); + _data[offset+1] = G(c); + _data[offset+2] = B(c); + if (_rgbw) _data[offset+3] = W(c); } void setPixelColor(uint16_t pix, uint32_t c, uint8_t cct) { @@ -456,12 +454,7 @@ class BusNetwork : public Bus { uint32_t getPixelColor(uint16_t pix) { if (!_valid || pix >= _len) return 0; uint16_t offset = pix * _UDPchannels; - return ( - (_rgbw ? (_data[offset+3] << 24) : 0) - | (_data[offset] << 16) - | (_data[offset+1] << 8) - | (_data[offset+2] ) - ); + return RGBW32(_data[offset], _data[offset+1], _data[offset+2], _rgbw ? (_data[offset+3] << 24) : 0); } void show() { diff --git a/wled00/colors.cpp b/wled00/colors.cpp index ab35f01d..0377a198 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -6,36 +6,25 @@ void colorFromUint32(uint32_t in, bool secondary) { - if (secondary) { - colSec[3] = in >> 24 & 0xFF; - colSec[0] = in >> 16 & 0xFF; - colSec[1] = in >> 8 & 0xFF; - colSec[2] = in & 0xFF; - } else { - col[3] = in >> 24 & 0xFF; - col[0] = in >> 16 & 0xFF; - col[1] = in >> 8 & 0xFF; - col[2] = in & 0xFF; - } + byte *_col = secondary ? colSec : col; + _col[0] = R(in); + _col[1] = G(in); + _col[2] = B(in); + _col[3] = W(in); } //load a color without affecting the white channel void colorFromUint24(uint32_t in, bool secondary) { - if (secondary) { - colSec[0] = in >> 16 & 0xFF; - colSec[1] = in >> 8 & 0xFF; - colSec[2] = in & 0xFF; - } else { - col[0] = in >> 16 & 0xFF; - col[1] = in >> 8 & 0xFF; - col[2] = in & 0xFF; - } + byte *_col = secondary ? colSec : col; + _col[0] = R(in); + _col[1] = G(in); + _col[2] = B(in); } //store color components in uint32_t uint32_t colorFromRgbw(byte* rgbw) { - return (rgbw[0] << 16) + (rgbw[1] << 8) + rgbw[2] + (rgbw[3] << 24); + return RGBW32(rgbw[0], rgbw[1], rgbw[2], rgbw[3]); } //relatively change white brightness, minumum A=5 @@ -195,10 +184,10 @@ void colorFromDecOrHexString(byte* rgb, char* in) c = strtoul(in, NULL, 10); } - rgb[3] = (c >> 24) & 0xFF; - rgb[0] = (c >> 16) & 0xFF; - rgb[1] = (c >> 8) & 0xFF; - rgb[2] = c & 0xFF; + rgb[0] = R(c); + rgb[1] = G(c); + rgb[2] = B(c); + rgb[3] = W(c); } //contrary to the colorFromDecOrHexString() function, this uses the more standard RRGGBB / RRGGBBWW order @@ -210,14 +199,14 @@ bool colorFromHexString(byte* rgb, const char* in) { uint32_t c = strtoul(in, NULL, 16); if (inputSize == 6) { - rgb[0] = (c >> 16) & 0xFF; - rgb[1] = (c >> 8) & 0xFF; - rgb[2] = c & 0xFF; + rgb[0] = (c >> 16); + rgb[1] = (c >> 8); + rgb[2] = c ; } else { - rgb[0] = (c >> 24) & 0xFF; - rgb[1] = (c >> 16) & 0xFF; - rgb[2] = (c >> 8) & 0xFF; - rgb[3] = c & 0xFF; + rgb[0] = (c >> 24); + rgb[1] = (c >> 16); + rgb[2] = (c >> 8); + rgb[3] = c ; } return true; } @@ -234,15 +223,16 @@ float maxf (float v, float w) return v; } +/* uint32_t colorRGBtoRGBW(uint32_t c) { byte rgb[4]; - rgb[0] = c >> 16; - rgb[1] = c >> 8; - rgb[2] = c ; - rgb[3] = c >> 24; + rgb[0] = R(c); + rgb[1] = G(c); + rgb[2] = B(c); + rgb[3] = W(c); colorRGBtoRGBW(rgb); - return ((rgb[3] << 24) | (rgb[0] << 16) | (rgb[1] << 8) | (rgb[2])); + return RGBW32(rgb[0], rgb[1], rgb[2], rgb[3]); } void colorRGBtoRGBW(byte* rgb) //rgb to rgbw (http://codewelt.com/rgbw). (RGBW_MODE_LEGACY) @@ -253,6 +243,7 @@ void colorRGBtoRGBW(byte* rgb) //rgb to rgbw (http://codewelt.com/rgbw). (RGBW_M float sat = 100.0f * ((high - low) / high);; // maximum saturation is 100 (corrected from 255) rgb[3] = (byte)((255.0f - sat) / 255.0f * (rgb[0] + rgb[1] + rgb[2]) / 3); } +*/ // adjust RGB values based on color temperature in K (range [2800-10200]) (https://en.wikipedia.org/wiki/Color_balance) void colorBalanceFromKelvin(uint16_t kelvin, byte *rgb) @@ -268,9 +259,9 @@ uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb) { byte rgbw[4] = {0,0,0,0}; colorKtoRGB(kelvin, rgbw); // convert Kelvin to RGB - rgbw[0] = ((uint16_t) rgbw[0] * ((rgb>>16) & 0xFF)) / 255; // correct R - rgbw[1] = ((uint16_t) rgbw[1] * ((rgb>> 8) & 0xFF)) / 255; // correct G - rgbw[2] = ((uint16_t) rgbw[2] * ((rgb ) & 0xFF)) / 255; // correct B - rgbw[3] = ((rgb>>24) & 0xFF); + rgbw[0] = ((uint16_t) rgbw[0] * R(rgb)) / 255; // correct R + rgbw[1] = ((uint16_t) rgbw[1] * G(rgb)) / 255; // correct G + rgbw[2] = ((uint16_t) rgbw[2] * B(rgb)) / 255; // correct B + rgbw[3] = W(rgb); return colorFromRgbw(rgbw); } diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index f8a2c863..b3dc1985 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -335,7 +335,7 @@ ${i+1}:

Reversed:

Skip 1st LED:

Off Refresh:  
-

Auto-calculate white channel from RGB:
 
+

Auto-calculate white channel from RGB:
 
`; f.insertAdjacentHTML("beforeend", cn); } diff --git a/wled00/dmx.cpp b/wled00/dmx.cpp index 7fef5666..64e02ec1 100644 --- a/wled00/dmx.cpp +++ b/wled00/dmx.cpp @@ -21,10 +21,10 @@ void handleDMX() for (int i = DMXStartLED; i < ledCount; i++) { // uses the amount of LEDs as fixture count uint32_t in = strip.getPixelColor(i); // get the colors for the individual fixtures as suggested by Aircoookie in issue #462 - byte w = in >> 24 & 0xFF; - byte r = in >> 16 & 0xFF; - byte g = in >> 8 & 0xFF; - byte b = in & 0xFF; + byte w = W(in); + byte r = R(in); + byte g = G(in); + byte b = B(in); int DMXFixtureStart = DMXStart + (DMXGap * (i - DMXStartLED)); for (int j = 0; j < DMXChannels; j++) { diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 20e62b3a..3f4807f2 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -69,7 +69,6 @@ void colorRGBtoXY(byte* rgb, float* xy); // only defined if huesync disabled TOD void colorFromDecOrHexString(byte* rgb, char* in); bool colorFromHexString(byte* rgb, const char* in); -void colorRGBtoRGBW(byte* rgb); //rgb to rgbw (http://codewelt.com/rgbw). (RGBW_MODE_LEGACY) void colorBalanceFromKelvin(uint16_t kelvin, byte *rgb); uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb); diff --git a/wled00/html_settings.h b/wled00/html_settings.h index 951006ad..94213b50 100644 --- a/wled00/html_settings.h +++ b/wled00/html_settings.h @@ -77,7 +77,7 @@ onclick="B()">Back // Autogenerated from wled00/data/settings_leds.htm, do not edit!! const char PAGE_settings_leds[] PROGMEM = R"=====(LED Settings