Is there a simple way to increase the contrast of the colors in my

@Mark_Kriegsman I dug a little deeper and think I had a fundamental misunderstanding of how FastLED.setBrightness() works. I thought it never scaled color values down to zero, but that’s not the case. Tracing the source, it appears that it uses scale8 rather than scale8_video (at least for ARM like the Teensy LC I’m using; haven’t checked AVR).

If I add the _video feature to the standard scale8 code like this…

return (((uint16_t)i * (uint16_t)(scale) ) >> 8) + ((i&&scale)?1:0);

…I get output much closer to what I would expect. True, as the global brightness setting decreases, contrast fades, but that is a fair tradeoff for losing sudden color shifts due to one or more subpixels totally dropping out.

Now, am I missing something here? Is there a better way to keep FastLED.setBrightness from crushing values to black other than altering the library source?

There are two things we’d really like to change but are constraint on clock cycles in the realtime processing code:
First, we want scale8 to round UP, not down. This would help with color rendering across the board.
And second, we’d love for for the realtime brightness rendering to basically use scale8_video, instead of scale8. This would also improve color rendering at low brightnesses.

However, on AVR, we’re basically out of clock cycles; those two code changes would add enough extra delay that we could no longer do the brightness adjustment on the fly in realtime as we do now. On ARM, we probably do have enough cycles, but Dan and I are not quite ready yet to split the functionality of FastLED and say “it can do X Y and Z, but only on ARM.” That day will come, and when it does we have some more tricks and features that will be ARM-only, but we’re still very strongly committed to trying to keep feature parity all the way down to a lowly 8MHz ATtiny, even though it lacks even a MULtiply instruction.

So given the AVR clock cycle constraints, we don’t think we can upgrade the brightness transform code (as desired, above) that’s in show() and still have it work in realtime.

That said, you still have choices. Instead of using the realtime master brightness control, you can just scale your LED values down yourself, using as good an algorithm as you wish, and store the post-scaled values in the LED array. Leave setBrightness(255), and you’ll have more control in your own code.

Do bear in mind that even at brightness 255, some scaling is still taking place (we’d ALSO like to improve this!), so
Output = floor( Input * (255/256))

It makes us a little crazy that we know how to “fix” the rounding issues (eg round up, not down!), but we’re unable to implement them and still keep the processing realtime, on-the-fly, and nondestructive. We’d love to improve it, but I think on AVR at least, we can’t.

@Mark_Kriegsman Thanks for the reply. FastLED is a magnificent bit of work, and I only have more respect for you guys after examining the source. I totally understand your priority on platform parity. That said, I really do need this change so will edit my copy of the library. Would you consider…

A) An undocumented/unsupported public boolean that toggles the two improvements you mentioned on ARM hardware only? That would allow me to upgrade to future source releases without remembering where to make my hack. Or…

B) Telling me the best way to make setBrightness() use scale8_video with a source edit? I’m currently editing scale8 directly because I couldn’t find where it was actually being called.

FYI I’m running extremely low on Flash, or I’d incorporate my own brightness control like you suggested.