This has come up before I'm pretty sure but just to make sure I'm

This has come up before I’m pretty sure but just to make sure I’m remembering right. You can create a CRGB from a CHSV:

CRGB foo = CHSV(h, s, v);

… but you can’t create a CHSV from a CRGB (the following won’t work):

CHSV bar = CHSV(leds[i]);

Am I correct in my recollection that this isn’t possible? Is there a reason for this other than “the code hasn’t been written”? I want to do the above. My goal is to take a leds[] array that’s already been rendered into by one pattern, and play with the saturation. Is there another way to accomplish this?

The math is expensive and ugly and made worse by the tweaking that was done for better color representation.

If yo have the ram - keep two led arrays, one HSV and one rgb.

What Dan said.
It’s actually not super expensive, but it’s not cheap. And it is a PITA that I haven’t gotten around to yet.
Just as HSV-to-RGB has a simple, bad-looking “spectrum” version and a more complicated, better looking “rainbow” version, the same is true in reverse. RGB-to-HSV(spectrum) is easier and not as good looking, and RGB-to-HSV(rainbow) looks better but is much more annoying to code.
So basically, yeah, just hasn’t been written yet, and that’s because we’ve been doing other stuff with hopefully a higher ratio of value:effort. Still on the to-do list though.

If you want to fully maximize saturation, subtract out whatever the R G and B have in common and scale the remaining values up to preserve brightness (if desired). Eg, (50,100,150) -> subtract lowest common value(50) from all -> (0,50,100) -> scale back up so the total is the same as it was(300) -> (0,100,200). There are some details left out but that’s the basic idea.

If you want to fully DEsaturate, that’s much easier: set R G and B all to the same value. Use either
val = leds[i].getAverageLight();
or
val = leds[i].getLuma();
and then
leds[i] = CRGB( val, val, val);

And of course you don’t have to go ALL the way in either direction, you can just move that way a little if you prefer. But that’s more math and more annoying.

It turns out the real PITA of RGB-to-HSV(rainbow) is recovery of the Hue. If all you want to do is tinker the Brightness or Saturation, that’s relatively linear, as above. Figuring out what Hue angle is represented by (50,100,150) is … just annoying.

Fair enough, I thought that was the reason behind it. Unfortunately I don’t have the RAM to keep two leds[] arrays :-(. Got 2k left out of my Teensy’s 16k, which I think is pretty good at this point, given I’ve got 12 instances of Fire2012 and Conway’s game of Life (among other things) on a 640-pixel matrix :-).

Maybe all you need to record is the hue[] of each pixel?

@Mark_Kriegsman I think I actually want to DEsaturate—on every beat, I want the extant pattern to flash white, and then “fade” back to whatever it’s meant to be over the next dozen frames. I’ll try that approach.

Or maybe I could just add (CRGB::White % n) to the existing value of leds[i] and get the effect I want…

Oh, yeah. Desaturating is the easy one.
And you can apply a certain amount (0-255) of desaturation with something like this:

CRGB color = leds[i];

uint8_t val = color.getLuma();
CRGB mono = CRGB( val, val, val);

leds[i] = blend( color, mono, desaturation);

Did you know that there’s a blend function that takes two CRGBs and lets you adjust how much of each one you want to use in the result? Well there is. More “hidden secrets of FastLED”.

Oh shit! Well then, problem solved. Awesome.

I have a bit of code that takes an Impact Sensor (http://www.parallax.com/sites/default/files/downloads/29132-Sound-Impact-Sensor-v1.0.pdf) and triggers a LED event that sets the whole strip to full brightness. Between events, the strip is constantly fading down. I’m kinda stuck thinking about how to implement the Blend that Mark mentions above.

Here’s my code:
//void loop(){
// if (trigger > threshold){
// brightness = maxBright;
// fadeTimer = millis();
// }
// if (brightness > 4.0){
// if (millis()-fadeTimer > fadeWait){
// brightness = brightness*fade;
// fadeTimer = millis();
// }
// }
// for (int i = 0; i < LED_COUNT; i++){
// leds[i] = CHSV(hue, 255, brightness);
// }
// LEDS.show();

Does anyone have a recommendation?

Just as a side thought, you could use FastLED.setBrightness(…) to adjust the brightness of the whole strip. Renders dim colors a little better than the CHSV way, too.

So basically, by using the setBrightness, I can reduce my code to this?.?.I think, I’m away from my test rig at the moment.

if(trigger > threshold) {
bright = 255;
fadeTimer = millis();
}

if(bright > 2){
if (millis()-fadeTimer > fadeWait){
bright = bright*fade;
fadeTimer = millis(); }
}

LEDS.setBrightness(bright);
LEDS.show()

Yep, like that!

I like playing with dynamic values for setBrightness…

And, now if I wanted to add the saturation code from above, then I would just have to add a for loop like this?.?.?

for(i = 0; i < NUM_LEDS; i++){
CRGB color = leds[i];
uint8_t val = color.getLuma();
CRGB mono = CRGB( val, val, val);
leds[i] = blend( color, mono, bright);
}

Looks right-ish to me.
A lot depends on what you want and how you want it to look, but this is a good start.

I threw in an implementation with blend() yesterday. Looks great!