Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions wled00/FX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ static um_data_t* getAudioData() {
return um_data;
}


// effect functions

/*
Expand All @@ -125,6 +126,56 @@ uint16_t mode_static(void) {
}
static const char _data_FX_MODE_STATIC[] PROGMEM = "Solid";

/*
* Copy a segment and perform (optional) color adjustments
*/
uint16_t mode_copy_segment(void) {
uint32_t sourceid = SEGMENT.custom3;
if (sourceid >= strip.getSegmentsNum() || sourceid == strip.getCurrSegmentId()) { // invalid source
SEGMENT.fadeToBlackBy(5); // fade out
return FRAMETIME;
}
Segment sourcesegment = strip.getSegment(sourceid);
if (sourcesegment.isActive()) {
uint32_t sourcecolor;
uint32_t destcolor;
if(sourcesegment.is2D()) { // 2D source, note: 2D to 1D just copies the first row (or first column if 'Switch axis' is checked in FX)
for (unsigned y = 0; y < SEGMENT.vHeight(); y++) {
for (unsigned x = 0; x < SEGMENT.vWidth(); x++) {
unsigned sx = x; // source coordinates
unsigned sy = y;
if(SEGMENT.check1) std::swap(sx, sy); // flip axis
if(SEGMENT.check2) {
sourcecolor = strip.getPixelColorXY(sx + sourcesegment.start, sy + sourcesegment.startY); // read from global buffer (reads the last rendered frame)
}
else {
sourcesegment.setDrawDimensions(); // set to source segment dimensions
sourcecolor = sourcesegment.getPixelColorXY(sx, sy); // read from segment buffer
}
destcolor = adjust_color(sourcecolor, SEGMENT.intensity, SEGMENT.custom1, SEGMENT.custom2);
SEGMENT.setDrawDimensions(); // reset to current segment dimensions
SEGMENT.setPixelColorXY(x, y, destcolor);
}
}
} else { // 1D source, source can be expanded into 2D
for (unsigned i = 0; i < SEGMENT.vLength(); i++) {
if(SEGMENT.check2) {
sourcecolor = strip.getPixelColor(i + sourcesegment.start); // read from global buffer (reads the last rendered frame)
}
else {
sourcesegment.setDrawDimensions(); // set to source segment dimensions
sourcecolor = sourcesegment.getPixelColor(i);
}
destcolor = adjust_color(sourcecolor, SEGMENT.intensity, SEGMENT.custom1, SEGMENT.custom2);
SEGMENT.setDrawDimensions(); // reset to current segment dimensions
SEGMENT.setPixelColor(i, destcolor);
}
}
}
return FRAMETIME;
}
static const char _data_FX_MODE_COPY[] PROGMEM = "Copy Segment@,Color shift,Lighten,Brighten,ID,Axis(2D),FullStack(last frame);;;12;ix=0,c1=0,c2=0,c3=0";


/*
* Blink/strobe function
Expand Down Expand Up @@ -10584,6 +10635,7 @@ void WS2812FX::setupEffectData() {
_modeData.push_back(_data_RESERVED);
}
// now replace all pre-allocated effects
addEffect(FX_MODE_COPY, &mode_copy_segment, _data_FX_MODE_COPY);
// --- 1D non-audio effects ---
addEffect(FX_MODE_BLINK, &mode_blink, _data_FX_MODE_BLINK);
addEffect(FX_MODE_BREATH, &mode_breath, _data_FX_MODE_BREATH);
Expand Down
1 change: 1 addition & 0 deletions wled00/FX.h
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ extern byte realtimeMode; // used in getMappedPixelIndex()
#define FX_MODE_LAKE 75
#define FX_MODE_METEOR 76
//#define FX_MODE_METEOR_SMOOTH 77 // replaced by Meteor
#define FX_MODE_COPY 77
#define FX_MODE_RAILWAY 78
#define FX_MODE_RIPPLE 79
#define FX_MODE_TWINKLEFOX 80
Expand Down
17 changes: 17 additions & 0 deletions wled00/colors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,23 @@ uint32_t color_fade(uint32_t c1, uint8_t amount, bool video)
return scaledcolor;
}

/*
* color adjustment in HSV color space (converts RGB to HSV and back), color conversions are not 100% accurate!
shifts hue, increase brightness, decreases saturation (if not black)
note: inputs are 32bit to speed up the function, useful input value ranges are 0-255
*/
uint32_t adjust_color(uint32_t rgb, uint32_t hueShift, uint32_t lighten, uint32_t brighten) {
if(rgb == 0 | hueShift + lighten + brighten == 0) return rgb; // black or no change
CHSV32 hsv;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since CHSV32 is custom HSV class, I would suggest to incorporate constructor from RGBW32 and uint32_t which should hide explicit calls to HSV conversion.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

constructor is implemented in #4615 but it uses the fastled equivalent "rainbow" conversion for nicer colors, however, here we want the technically correct spectrum conversion to avoid color shifts.

rgb2hsv(rgb, hsv); //convert to HSV
hsv.h += (hueShift << 8); // shift hue (hue is 16 bits)
hsv.s = max((int32_t)0, (int32_t)hsv.s - (int32_t)lighten); // desaturate
hsv.v = min((uint32_t)255, (uint32_t)hsv.v + brighten); // increase brightness
uint32_t rgb_adjusted;
hsv2rgb(hsv, rgb_adjusted); // convert back to RGB TODO: make this into 16 bit conversion
return rgb_adjusted;
}

// 1:1 replacement of fastled function optimized for ESP, slightly faster, more accurate and uses less flash (~ -200bytes)
uint32_t ColorFromPaletteWLED(const CRGBPalette16& pal, unsigned index, uint8_t brightness, TBlendType blendType)
{
Expand Down
1 change: 1 addition & 0 deletions wled00/fcn_declare.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ class NeoGammaWLEDMethod {
inline uint32_t color_blend16(uint32_t c1, uint32_t c2, uint16_t b) { return color_blend(c1, c2, b >> 8); };
[[gnu::hot, gnu::pure]] uint32_t color_add(uint32_t, uint32_t, bool preserveCR = false);
[[gnu::hot, gnu::pure]] uint32_t color_fade(uint32_t c1, uint8_t amount, bool video=false);
[[gnu::hot, gnu::pure]] uint32_t adjust_color(uint32_t rgb, uint32_t hueShift, uint32_t lighten, uint32_t brighten);
[[gnu::hot, gnu::pure]] uint32_t ColorFromPaletteWLED(const CRGBPalette16 &pal, unsigned index, uint8_t brightness = (uint8_t)255U, TBlendType blendType = LINEARBLEND);
CRGBPalette16 generateHarmonicRandomPalette(const CRGBPalette16 &basepalette);
CRGBPalette16 generateRandomPalette();
Expand Down