mirror of
https://github.com/wled/WLED.git
synced 2025-07-19 08:46:34 +00:00
Merge pull request #3904 from DedeHai/FX_fcn_improvements
added improvements to color scaling and blurring
This commit is contained in:
commit
d126611e87
12
wled00/FX.h
12
wled00/FX.h
@ -582,7 +582,7 @@ typedef struct Segment {
|
|||||||
#endif
|
#endif
|
||||||
uint32_t getPixelColor(int i);
|
uint32_t getPixelColor(int i);
|
||||||
// 1D support functions (some implement 2D as well)
|
// 1D support functions (some implement 2D as well)
|
||||||
void blur(uint8_t);
|
void blur(uint8_t, bool smear = false);
|
||||||
void fill(uint32_t c);
|
void fill(uint32_t c);
|
||||||
void fade_out(uint8_t r);
|
void fade_out(uint8_t r);
|
||||||
void fadeToBlackBy(uint8_t fadeBy);
|
void fadeToBlackBy(uint8_t fadeBy);
|
||||||
@ -610,7 +610,7 @@ typedef struct Segment {
|
|||||||
inline void setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w = 0, bool aa = true) { setPixelColorXY(x, y, RGBW32(r,g,b,w), aa); }
|
inline void setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w = 0, bool aa = true) { setPixelColorXY(x, y, RGBW32(r,g,b,w), aa); }
|
||||||
inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), aa); }
|
inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), aa); }
|
||||||
#endif
|
#endif
|
||||||
uint32_t getPixelColorXY(uint16_t x, uint16_t y);
|
uint32_t getPixelColorXY(int x, int y);
|
||||||
// 2D support functions
|
// 2D support functions
|
||||||
inline void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend) { setPixelColorXY(x, y, color_blend(getPixelColorXY(x,y), color, blend)); }
|
inline void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend) { setPixelColorXY(x, y, color_blend(getPixelColorXY(x,y), color, blend)); }
|
||||||
inline void blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), blend); }
|
inline void blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), blend); }
|
||||||
@ -619,8 +619,8 @@ typedef struct Segment {
|
|||||||
inline void addPixelColorXY(int x, int y, CRGB c, bool fast = false) { addPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), fast); }
|
inline void addPixelColorXY(int x, int y, CRGB c, bool fast = false) { addPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), fast); }
|
||||||
inline void fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { setPixelColorXY(x, y, color_fade(getPixelColorXY(x,y), fade, true)); }
|
inline void fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { setPixelColorXY(x, y, color_fade(getPixelColorXY(x,y), fade, true)); }
|
||||||
void box_blur(uint16_t i, bool vertical, fract8 blur_amount); // 1D box blur (with weight)
|
void box_blur(uint16_t i, bool vertical, fract8 blur_amount); // 1D box blur (with weight)
|
||||||
void blurRow(uint16_t row, fract8 blur_amount);
|
void blurRow(uint32_t row, fract8 blur_amount, bool smear = false);
|
||||||
void blurCol(uint16_t col, fract8 blur_amount);
|
void blurCol(uint32_t col, fract8 blur_amount, bool smear = false);
|
||||||
void moveX(int8_t delta, bool wrap = false);
|
void moveX(int8_t delta, bool wrap = false);
|
||||||
void moveY(int8_t delta, bool wrap = false);
|
void moveY(int8_t delta, bool wrap = false);
|
||||||
void move(uint8_t dir, uint8_t delta, bool wrap = false);
|
void move(uint8_t dir, uint8_t delta, bool wrap = false);
|
||||||
@ -655,8 +655,8 @@ typedef struct Segment {
|
|||||||
inline void addPixelColorXY(int x, int y, CRGB c, bool fast = false) { addPixelColor(x, RGBW32(c.r,c.g,c.b,0), fast); }
|
inline void addPixelColorXY(int x, int y, CRGB c, bool fast = false) { addPixelColor(x, RGBW32(c.r,c.g,c.b,0), fast); }
|
||||||
inline void fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { fadePixelColor(x, fade); }
|
inline void fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { fadePixelColor(x, fade); }
|
||||||
inline void box_blur(uint16_t i, bool vertical, fract8 blur_amount) {}
|
inline void box_blur(uint16_t i, bool vertical, fract8 blur_amount) {}
|
||||||
inline void blurRow(uint16_t row, fract8 blur_amount) {}
|
inline void blurRow(uint32_t row, fract8 blur_amount, bool smear = false) {}
|
||||||
inline void blurCol(uint16_t col, fract8 blur_amount) {}
|
inline void blurCol(uint32_t col, fract8 blur_amount, bool smear = false) {}
|
||||||
inline void moveX(int8_t delta, bool wrap = false) {}
|
inline void moveX(int8_t delta, bool wrap = false) {}
|
||||||
inline void moveY(int8_t delta, bool wrap = false) {}
|
inline void moveY(int8_t delta, bool wrap = false) {}
|
||||||
inline void move(uint8_t dir, uint8_t delta, bool wrap = false) {}
|
inline void move(uint8_t dir, uint8_t delta, bool wrap = false) {}
|
||||||
|
@ -175,11 +175,7 @@ void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
|
|||||||
|
|
||||||
uint8_t _bri_t = currentBri();
|
uint8_t _bri_t = currentBri();
|
||||||
if (_bri_t < 255) {
|
if (_bri_t < 255) {
|
||||||
byte r = scale8(R(col), _bri_t);
|
col = color_fade(col, _bri_t);
|
||||||
byte g = scale8(G(col), _bri_t);
|
|
||||||
byte b = scale8(B(col), _bri_t);
|
|
||||||
byte w = scale8(W(col), _bri_t);
|
|
||||||
col = RGBW32(r, g, b, w);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reverse ) x = virtualWidth() - x - 1;
|
if (reverse ) x = virtualWidth() - x - 1;
|
||||||
@ -265,7 +261,7 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// returns RGBW values of pixel
|
// returns RGBW values of pixel
|
||||||
uint32_t IRAM_ATTR Segment::getPixelColorXY(uint16_t x, uint16_t y) {
|
uint32_t IRAM_ATTR Segment::getPixelColorXY(int x, int y) {
|
||||||
if (!isActive()) return 0; // not active
|
if (!isActive()) return 0; // not active
|
||||||
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return 0; // if pixel would fall out of virtual segment just exit
|
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return 0; // if pixel would fall out of virtual segment just exit
|
||||||
if (reverse ) x = virtualWidth() - x - 1;
|
if (reverse ) x = virtualWidth() - x - 1;
|
||||||
@ -278,59 +274,71 @@ uint32_t IRAM_ATTR Segment::getPixelColorXY(uint16_t x, uint16_t y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// blurRow: perform a blur on a row of a rectangular matrix
|
// blurRow: perform a blur on a row of a rectangular matrix
|
||||||
void Segment::blurRow(uint16_t row, fract8 blur_amount) {
|
void Segment::blurRow(uint32_t row, fract8 blur_amount, bool smear){
|
||||||
if (!isActive() || blur_amount == 0) return; // not active
|
if (!isActive() || blur_amount == 0) return; // not active
|
||||||
const uint_fast16_t cols = virtualWidth();
|
const uint_fast16_t cols = virtualWidth();
|
||||||
const uint_fast16_t rows = virtualHeight();
|
const uint_fast16_t rows = virtualHeight();
|
||||||
|
|
||||||
if (row >= rows) return;
|
if (row >= rows) return;
|
||||||
// blur one row
|
// blur one row
|
||||||
uint8_t keep = 255 - blur_amount;
|
uint8_t keep = smear ? 255 : 255 - blur_amount;
|
||||||
uint8_t seep = blur_amount >> 1;
|
uint8_t seep = blur_amount >> 1;
|
||||||
CRGB carryover = CRGB::Black;
|
uint32_t carryover = BLACK;
|
||||||
|
uint32_t lastnew;
|
||||||
|
uint32_t last;
|
||||||
|
uint32_t curnew;
|
||||||
for (unsigned x = 0; x < cols; x++) {
|
for (unsigned x = 0; x < cols; x++) {
|
||||||
CRGB cur = getPixelColorXY(x, row);
|
uint32_t cur = getPixelColorXY(x, row);
|
||||||
CRGB before = cur; // remember color before blur
|
uint32_t part = color_fade(cur, seep);
|
||||||
CRGB part = cur;
|
curnew = color_fade(cur, keep);
|
||||||
part.nscale8(seep);
|
if (x > 0) {
|
||||||
cur.nscale8(keep);
|
if (carryover)
|
||||||
cur += carryover;
|
curnew = color_add(curnew, carryover, true);
|
||||||
if (x>0) {
|
uint32_t prev = color_add(lastnew, part, true);
|
||||||
CRGB prev = CRGB(getPixelColorXY(x-1, row)) + part;
|
if (last != prev) // optimization: only set pixel if color has changed
|
||||||
setPixelColorXY(x-1, row, prev);
|
setPixelColorXY(x - 1, row, prev);
|
||||||
}
|
}
|
||||||
if (before != cur) // optimization: only set pixel if color has changed
|
else // first pixel
|
||||||
setPixelColorXY(x, row, cur);
|
setPixelColorXY(x, row, curnew);
|
||||||
|
lastnew = curnew;
|
||||||
|
last = cur; // save original value for comparison on next iteration
|
||||||
carryover = part;
|
carryover = part;
|
||||||
}
|
}
|
||||||
|
setPixelColorXY(cols-1, row, curnew); // set last pixel
|
||||||
}
|
}
|
||||||
|
|
||||||
// blurCol: perform a blur on a column of a rectangular matrix
|
// blurCol: perform a blur on a column of a rectangular matrix
|
||||||
void Segment::blurCol(uint16_t col, fract8 blur_amount) {
|
void Segment::blurCol(uint32_t col, fract8 blur_amount, bool smear) {
|
||||||
if (!isActive() || blur_amount == 0) return; // not active
|
if (!isActive() || blur_amount == 0) return; // not active
|
||||||
const uint_fast16_t cols = virtualWidth();
|
const uint_fast16_t cols = virtualWidth();
|
||||||
const uint_fast16_t rows = virtualHeight();
|
const uint_fast16_t rows = virtualHeight();
|
||||||
|
|
||||||
if (col >= cols) return;
|
if (col >= cols) return;
|
||||||
// blur one column
|
// blur one column
|
||||||
uint8_t keep = 255 - blur_amount;
|
uint8_t keep = smear ? 255 : 255 - blur_amount;
|
||||||
uint8_t seep = blur_amount >> 1;
|
uint8_t seep = blur_amount >> 1;
|
||||||
CRGB carryover = CRGB::Black;
|
uint32_t carryover = BLACK;
|
||||||
|
uint32_t lastnew;
|
||||||
|
uint32_t last;
|
||||||
|
uint32_t curnew;
|
||||||
for (unsigned y = 0; y < rows; y++) {
|
for (unsigned y = 0; y < rows; y++) {
|
||||||
CRGB cur = getPixelColorXY(col, y);
|
uint32_t cur = getPixelColorXY(col, y);
|
||||||
CRGB part = cur;
|
uint32_t part = color_fade(cur, seep);
|
||||||
CRGB before = cur; // remember color before blur
|
curnew = color_fade(cur, keep);
|
||||||
part.nscale8(seep);
|
if (y > 0) {
|
||||||
cur.nscale8(keep);
|
if (carryover)
|
||||||
cur += carryover;
|
curnew = color_add(curnew, carryover, true);
|
||||||
if (y>0) {
|
uint32_t prev = color_add(lastnew, part, true);
|
||||||
CRGB prev = CRGB(getPixelColorXY(col, y-1)) + part;
|
if (last != prev) // optimization: only set pixel if color has changed
|
||||||
setPixelColorXY(col, y-1, prev);
|
setPixelColorXY(col, y - 1, prev);
|
||||||
}
|
}
|
||||||
if (before != cur) // optimization: only set pixel if color has changed
|
else // first pixel
|
||||||
setPixelColorXY(col, y, cur);
|
setPixelColorXY(col, y, curnew);
|
||||||
carryover = part;
|
lastnew = curnew;
|
||||||
|
last = cur; //save original value for comparison on next iteration
|
||||||
|
carryover = part;
|
||||||
}
|
}
|
||||||
|
setPixelColorXY(col, rows - 1, curnew);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1D Box blur (with added weight - blur_amount: [0=no blur, 255=max blur])
|
// 1D Box blur (with added weight - blur_amount: [0=no blur, 255=max blur])
|
||||||
|
@ -735,11 +735,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
|||||||
uint16_t len = length();
|
uint16_t len = length();
|
||||||
uint8_t _bri_t = currentBri();
|
uint8_t _bri_t = currentBri();
|
||||||
if (_bri_t < 255) {
|
if (_bri_t < 255) {
|
||||||
byte r = scale8(R(col), _bri_t);
|
col = color_fade(col, _bri_t);
|
||||||
byte g = scale8(G(col), _bri_t);
|
|
||||||
byte b = scale8(B(col), _bri_t);
|
|
||||||
byte w = scale8(W(col), _bri_t);
|
|
||||||
col = RGBW32(r, g, b, w);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// expand pixel (taking into account start, grouping, spacing [and offset])
|
// expand pixel (taking into account start, grouping, spacing [and offset])
|
||||||
@ -995,33 +991,43 @@ void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
|||||||
/*
|
/*
|
||||||
* blurs segment content, source: FastLED colorutils.cpp
|
* blurs segment content, source: FastLED colorutils.cpp
|
||||||
*/
|
*/
|
||||||
void Segment::blur(uint8_t blur_amount) {
|
void Segment::blur(uint8_t blur_amount, bool smear) {
|
||||||
if (!isActive() || blur_amount == 0) return; // optimization: 0 means "don't blur"
|
if (!isActive() || blur_amount == 0) return; // optimization: 0 means "don't blur"
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
if (is2D()) {
|
if (is2D()) {
|
||||||
// compatibility with 2D
|
// compatibility with 2D
|
||||||
const unsigned cols = virtualWidth();
|
const unsigned cols = virtualWidth();
|
||||||
const unsigned rows = virtualHeight();
|
const unsigned rows = virtualHeight();
|
||||||
for (unsigned i = 0; i < rows; i++) blurRow(i, blur_amount); // blur all rows
|
for (unsigned i = 0; i < rows; i++) blurRow(i, blur_amount, smear); // blur all rows
|
||||||
for (unsigned k = 0; k < cols; k++) blurCol(k, blur_amount); // blur all columns
|
for (unsigned k = 0; k < cols; k++) blurCol(k, blur_amount, smear); // blur all columns
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
uint8_t keep = 255 - blur_amount;
|
uint8_t keep = smear ? 255 : 255 - blur_amount;
|
||||||
uint8_t seep = blur_amount >> 1;
|
uint8_t seep = blur_amount >> 1;
|
||||||
uint32_t carryover = BLACK;
|
|
||||||
unsigned vlength = virtualLength();
|
unsigned vlength = virtualLength();
|
||||||
|
uint32_t carryover = BLACK;
|
||||||
|
uint32_t lastnew;
|
||||||
|
uint32_t last;
|
||||||
|
uint32_t curnew;
|
||||||
for (unsigned i = 0; i < vlength; i++) {
|
for (unsigned i = 0; i < vlength; i++) {
|
||||||
uint32_t cur = getPixelColor(i);
|
uint32_t cur = getPixelColor(i);
|
||||||
uint32_t part = color_fade(cur, seep);
|
uint32_t part = color_fade(cur, seep);
|
||||||
cur = color_add(color_fade(cur, keep), carryover, true);
|
curnew = color_fade(cur, keep);
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
uint32_t c = getPixelColor(i-1);
|
if (carryover)
|
||||||
setPixelColor(i-1, color_add(c, part, true));
|
curnew = color_add(curnew, carryover, true);
|
||||||
|
uint32_t prev = color_add(lastnew, part, true);
|
||||||
|
if (last != prev) // optimization: only set pixel if color has changed
|
||||||
|
setPixelColor(i - 1, prev);
|
||||||
}
|
}
|
||||||
setPixelColor(i, cur);
|
else // first pixel
|
||||||
|
setPixelColor(i, curnew);
|
||||||
|
lastnew = curnew;
|
||||||
|
last = cur; // save original value for comparison on next iteration
|
||||||
carryover = part;
|
carryover = part;
|
||||||
}
|
}
|
||||||
|
setPixelColor(vlength - 1, curnew);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -65,24 +65,30 @@ uint32_t color_add(uint32_t c1, uint32_t c2, bool fast)
|
|||||||
* fades color toward black
|
* fades color toward black
|
||||||
* if using "video" method the resulting color will never become black unless it is already black
|
* if using "video" method the resulting color will never become black unless it is already black
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uint32_t color_fade(uint32_t c1, uint8_t amount, bool video)
|
uint32_t color_fade(uint32_t c1, uint8_t amount, bool video)
|
||||||
{
|
{
|
||||||
uint8_t r = R(c1);
|
uint32_t scaledcolor; // color order is: W R G B from MSB to LSB
|
||||||
uint8_t g = G(c1);
|
uint32_t r = R(c1);
|
||||||
uint8_t b = B(c1);
|
uint32_t g = G(c1);
|
||||||
uint8_t w = W(c1);
|
uint32_t b = B(c1);
|
||||||
if (video) {
|
uint32_t w = W(c1);
|
||||||
r = scale8_video(r, amount);
|
if (video) {
|
||||||
g = scale8_video(g, amount);
|
uint32_t scale = amount; // 32bit for faster calculation
|
||||||
b = scale8_video(b, amount);
|
scaledcolor = (((r * scale) >> 8) << 16) + ((r && scale) ? 1 : 0);
|
||||||
w = scale8_video(w, amount);
|
scaledcolor |= (((g * scale) >> 8) << 8) + ((g && scale) ? 1 : 0);
|
||||||
} else {
|
scaledcolor |= ((b * scale) >> 8) + ((b && scale) ? 1 : 0);
|
||||||
r = scale8(r, amount);
|
scaledcolor |= (((w * scale) >> 8) << 24) + ((w && scale) ? 1 : 0);
|
||||||
g = scale8(g, amount);
|
return scaledcolor;
|
||||||
b = scale8(b, amount);
|
}
|
||||||
w = scale8(w, amount);
|
else {
|
||||||
|
uint32_t scale = 1 + amount;
|
||||||
|
scaledcolor = ((r * scale) >> 8) << 16;
|
||||||
|
scaledcolor |= ((g * scale) >> 8) << 8;
|
||||||
|
scaledcolor |= (b * scale) >> 8;
|
||||||
|
scaledcolor |= ((w * scale) >> 8) << 24;
|
||||||
|
return scaledcolor;
|
||||||
}
|
}
|
||||||
return RGBW32(r, g, b, w);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRandomColor(byte* rgb)
|
void setRandomColor(byte* rgb)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user