Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copy Segment FX #4124

Open
wants to merge 11 commits into
base: 0_15
Choose a base branch
from
46 changes: 46 additions & 0 deletions wled00/FX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ static um_data_t* getAudioData() {
return um_data;
}


// effect functions

/*
Expand All @@ -94,6 +95,50 @@ uint16_t mode_static(void) {
static const char _data_FX_MODE_STATIC[] PROGMEM = "Solid";


/*
* Copy selected segment and perform (optional) color adjustments
*/
// TODO: what is the correct place to put getRenderedPixelXY()?
static uint32_t getRenderedPixelXY(Segment& seg, unsigned x, unsigned y = 0) {
// We read pixels back following mirror/reverse/transpose but ignoring grouping
// For every group-length pixels, add spacing
x *= seg.groupLength(); // expand to physical pixels
y *= seg.groupLength(); // expand to physical pixels
if (x >= seg.width() || y >= seg.height()) return 0; // fill out of range pixels with black
#warning this check can be removed once 2D offset is fixed
DedeHai marked this conversation as resolved.
Show resolved Hide resolved
uint32_t offset = seg.is2D() ? 0 : seg.offset; // dirty fix, offset in 2D segments should be zero but is not TODO: fix the offset
return strip.getPixelColorXY(seg.start + offset + x, seg.startY + y);
DedeHai marked this conversation as resolved.
Show resolved Hide resolved
}

uint16_t mode_copy_segment(void) {
uint32_t sourceid = SEGMENT.custom3;
if (sourceid >= strip._segments.size() || sourceid == strip.getCurrSegmentId()) { // invalid source
DedeHai marked this conversation as resolved.
Show resolved Hide resolved
SEGMENT.fadeToBlackBy(5); // fade out, clears pixels and allows overlapping segments
return FRAMETIME;
}
if (strip._segments[sourceid].isActive()) {
DedeHai marked this conversation as resolved.
Show resolved Hide resolved
uint32_t sourcecolor;
if(!strip._segments[sourceid].is2D()) { // 1D source, source can be expanded into 2D
DedeHai marked this conversation as resolved.
Show resolved Hide resolved
uint32_t cl; // length to copy
for (unsigned i = 0; i < SEGMENT.virtualLength(); i++) {
sourcecolor = getRenderedPixelXY(strip._segments[sourceid], i);
SEGMENT.setPixelColor(i, adjust_color(sourcecolor, SEGMENT.intensity, SEGMENT.custom1, SEGMENT.custom2));
}
} else { // 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.virtualHeight(); y++) {
for (unsigned x = 0; x < SEGMENT.virtualWidth(); x++) {
if(SEGMENT.check2) sourcecolor = getRenderedPixelXY(strip._segments[sourceid], y, x); // flip axis (for 2D -> 1D, in 2D Segments this does the same as 'Transpose')
else sourcecolor = getRenderedPixelXY(strip._segments[sourceid], x, y);
SEGMENT.setPixelColorXY(x, y, adjust_color(sourcecolor, SEGMENT.intensity, SEGMENT.custom1, SEGMENT.custom2));
}
}
}
}
return FRAMETIME;
}
static const char _data_FX_MODE_COPY[] PROGMEM = "Copy Segment@,Color shift,Lighten,Brighten,ID,,Switch axis(2D);;;1;ix=0,c1=0,c2=0,c3=0,o2=0";


/*
* Blink/strobe function
* Alternate between color1 and color2
Expand Down Expand Up @@ -7835,6 +7880,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
4 changes: 2 additions & 2 deletions wled00/FX.h
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,8 @@
#define FX_MODE_WAVESINS 184
#define FX_MODE_ROCKTAVES 185
#define FX_MODE_2DAKEMI 186

#define MODE_COUNT 187
#define FX_MODE_COPY 187
#define MODE_COUNT 188

typedef enum mapping1D2D {
M12_Pixels = 0,
Expand Down
43 changes: 43 additions & 0 deletions wled00/colors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,24 @@ 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(hueShift + lighten + brighten == 0) return rgb; // no change
CHSV hsv;
rgb2hsv(rgb, hsv); //convert to HSV
if(hsv.v == 0) return rgb; // do not change black pixels
hsv.h += hueShift; // shift hue
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
CRGB adjusted;
hsv2rgb_spectrum(hsv, adjusted); // convert back to RGB
return RGBW32(adjusted.r,adjusted.g,adjusted.b,0);
}

void setRandomColor(byte* rgb)
{
lastRandomIndex = get_random_wheel_index(lastRandomIndex);
Expand Down Expand Up @@ -225,6 +243,31 @@ void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb
}
}

void rgb2hsv(const uint32_t rgb, CHSV& hsv) // convert rgb to hsv, more accurate and faster than fastled version
{
int32_t r = (rgb>>16)&0xFF;
int32_t g = (rgb>>8)&0xFF;
int32_t b = rgb&0xFF;
hsv = CHSV(0, 0, 0);
int32_t minval, maxval, delta;
minval = min(r, g);
minval = min(minval, b);
maxval = max(r, g);
maxval = max(maxval, b);
if (maxval == 0) return; // black
hsv.v = maxval;
delta = maxval - minval;
hsv.s = (255 * delta) / maxval;
if (hsv.s == 0) return; // gray value
int32_t h; //calculate hue
if (maxval == r)
h = (43 * (g - b)) / delta;
else if (maxval == g) h = 85 + (43 * (b - r)) / delta;
else h = 171 + (43 * (r - g)) / delta;
if(h < 0) h += 256;
hsv.h = h;
}

//get RGB values from color temperature in K (https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html)
void colorKtoRGB(uint16_t kelvin, byte* rgb) //white spectrum to rgb, calc
{
Expand Down
2 changes: 2 additions & 0 deletions wled00/fcn_declare.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,12 @@ class NeoGammaWLEDMethod {
uint32_t color_blend(uint32_t,uint32_t,uint16_t,bool b16=false);
uint32_t color_add(uint32_t,uint32_t, bool fast=false);
uint32_t color_fade(uint32_t c1, uint8_t amount, bool video=false);
uint32_t adjust_color(uint32_t rgb, uint32_t hueShift, uint32_t lighten, uint32_t brighten);
CRGBPalette16 generateHarmonicRandomPalette(CRGBPalette16 &basepalette);
CRGBPalette16 generateRandomPalette(void);
inline uint32_t colorFromRgbw(byte* rgbw) { return uint32_t((byte(rgbw[3]) << 24) | (byte(rgbw[0]) << 16) | (byte(rgbw[1]) << 8) | (byte(rgbw[2]))); }
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb); //hue, sat to rgb
void rgb2hsv(const uint32_t rgb, CHSV& hsv); //rgb to hsv
void colorKtoRGB(uint16_t kelvin, byte* rgb);
void colorCTtoRGB(uint16_t mired, byte* rgb); //white spectrum to rgb
void colorXYtoRGB(float x, float y, byte* rgb); // only defined if huesync disabled TODO
Expand Down