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
55 changes: 54 additions & 1 deletion 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 @@ -93,7 +94,58 @@ uint16_t mode_static(void) {
}
static const char _data_FX_MODE_STATIC[] PROGMEM = "Solid";


/*
* Copy selected segment
*/
uint16_t mode_copy_segment(void) {

uint32_t sourceid = SEGMENT.custom1;
SEGMENT.fadeToBlackBy(16); // fades out unused pixels, still allows overlay (also fades out if invalid ID is set)
if (sourceid >= strip._segments.size() || sourceid == strip.getCurrSegmentId()) return FRAMETIME; // invalid source
CRGB sourcecolor;
if (strip._segments[sourceid].isActive()) {
// note: copying 1D to 2D as well as 2D to 1D is not supported
if(SEGMENT.is2D() && strip._segments[sourceid].is2D()) { // 2D setup
uint32_t cx, cy; // sizes to copy
cx = std::min(strip._segments[sourceid].virtualWidth(), SEGMENT.virtualWidth()); // get smaller width
cy = std::min(strip._segments[sourceid].virtualHeight(), SEGMENT.virtualHeight()); // get smaller height
for (unsigned x = 0; x < cx; x++) {
for (unsigned y = 0; y < cy; y++) {
sourcecolor = strip._segments[sourceid].getPixelColorXY(x, y);
if(SEGMENT.custom2 > 0) // color shifting enabled
{
CHSV pxHSV = rgb2hsv(sourcecolor); //convert to HSV
pxHSV.h += SEGMENT.custom2; // shift hue
hsv2rgb_spectrum(pxHSV, sourcecolor); // convert back to RGB

}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This gets copy and pasted below - probably it wants to be a little static function instead.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

indeed, can you help out? I do not know what the best way to implement it is. just adding a function?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yup, pretty much. Something like:

static CRGB shift_hue(CRGB sourcecolor, uint8_t amount) {
  if (amount > 0) {
    CHSV pxHSV = rgb2hsv(sourcecolor); //convert to HSV
    pxHSV.h += amount; // shift hue
    hsv2rgb_spectrum(pxHSV, sourcecolor); // convert back to RGB       
   }
  return sourcecolor;
}

My inclination would be to leave it here in FX.cpp (hence static), to allow the compiler to inline it if it wants to. Organizationally though it might be a better fit for colors.cpp.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

oh, I though you meant some fancy C++ macro magic ;)
but good point, will add this to color utils

Copy link
Collaborator

Choose a reason for hiding this comment

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

if the shift_hue function is on a critical path (like pixel copy), then it would be smarter to put the static function into fx.cpp so the compiler can inline. Inlined functions are faster (no overhead due to call-and-return).

But the compiler will not inline things that are defined in a different .cpp file.

SEGMENT.setPixelColorXY(x, y, sourcecolor);
//SEGMENT.setPixelColorXY(x, y, strip._segments[sourceid].getPixelColorXY(x, y)); //use this for no colorshift option
}

}
}
else if(!SEGMENT.is2D() && !strip._segments[sourceid].is2D()) { // 1D strip
uint32_t cl; // length to copy
cl = std::min(strip._segments[sourceid].virtualLength(), SEGMENT.virtualLength()); // get smaller length
for (unsigned i = 0; i < cl; i++) {
sourcecolor = strip._segments[sourceid].getPixelColor(i);
if(SEGMENT.custom2 > 0) // color shifting enabled
{
CHSV pxHSV = rgb2hsv(sourcecolor); //convert to HSV
pxHSV.h += SEGMENT.custom2; // shift hue
sourcecolor = (CRGB)pxHSV; // convert back to RGB
}
SEGMENT.setPixelColor(i, sourcecolor);
// SEGMENT.setPixelColor(i, strip._segments[sourceid].getPixelColor(i)); //use this for no colorshift option
}
}
}
return FRAMETIME;
}
//static const char _data_FX_MODE_COPY[] PROGMEM = "Copy Segment@,,ID;;;12;c1=0,c2=0";
static const char _data_FX_MODE_COPY[] PROGMEM = "Copy Segment@,,ID,Color shift;;;12;c1=0,c2=0";

/*
* Blink/strobe function
* Alternate between color1 and color2
Expand Down Expand Up @@ -7835,6 +7887,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
26 changes: 26 additions & 0 deletions wled00/colors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,32 @@ void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb
}
}

CHSV rgb2hsv(const CRGB& rgb) // convert rgb to hsv, more accurate and faster than fastled version
{
int32_t r = rgb.r;
int32_t g = rgb.g;
int32_t b = rgb.b;
CHSV 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 hsv; // black
hsv.v = maxval;
delta = maxval - minval;
hsv.s = (255 * delta) / maxval;
if (hsv.s == 0) return hsv; // 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;
return hsv;
}

//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
1 change: 1 addition & 0 deletions wled00/fcn_declare.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ 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
CHSV rgb2hsv(const CRGB& rgb); //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