HSV from RGB: a poll Folks periodically ask about recovering HSV from RGB,

HSV from RGB: a poll
Folks periodically ask about recovering HSV from RGB, and I’ve demurred, because frankly it’s just a pain in the butt to code given our fancy rainbow colors. So here are the two questions I want to ask everyone:

  1. Have YOU ever really wanted/needed to recover HSV values from an RGB pixel? And…
  2. Did you actually care about H and S and V, or did you mostly just want to recover the Hue?
    I ask the second question because that code (hue recovery only) may turn out to be much faster and smaller than full rgb2hsv.
    Thanks for the input!
  1. No
  2. See 1)

I haven’t needed it really badly.

There are examples out there in other languages that do the trick.

There were times early on where I thought I wanted #1. But eventually I figured my way around it. I think I actually was mostly concerned with V (ie making brightness pulses). But if you program cleverly you shouldn’t need to recover it from CRGB

Well, that code out there would do the trick for HSV “spectrum” colors. That’s basically trivial.

But that’s not the color wheel we use by default. Instead, we use the more colorful HSV “rainbow” color wheel: brighter yellows, better color spacing, almost perfectly even brightnesses (radiance) at any hue. See https://github.com/FastLED/FastLED/wiki/FastLED-HSV-Colors

And that’s why I’ve been dragging my feet: reversing RGB into rainbow hues is just a relatively annoying (to me) collection of special cases and potential performance pitfalls… and y’all know how we feel about maintaining high performance…

Anyway, thanks for the input. I know that rgb2hsv isn’t nearly as useful as the other way, but it probably time to publish this “missing piece”, too.

Also for what it’s worth, the CRGB class already has the methods “getAverageLight()” and “getLuma()” both of which can help tell you how “bright” a color is.

H and V would be nice, but I’d be OK doing without and just maintain an extra array as required, especially if it adds much overhead.

Only code that uses the new methods will have to “pay” for them. If you never call the new methods, your code will be exactly as before: just as fast, just as small.

And even so, the new methods aren’t actually that bad, performance-wise; I’m just obsessed.

I think it’s a simple case that if you need the stuff that takes the time then you accept that hit in performance.

If the function doesn’t give an exact H, S and V back then people might find oddities in their animations — the errors it might cause will be amplified?

My answer is; yes, I’ve wanted it and probably wanted it so that it gives me very very close values.

  1. No
  2. No
    If I would need it I could accept that I need to “pay” for it.

@James_Carruthers : the current code that I’m testing is acceptably fast, and in the “pure hue” cases (H=xxx, S=255, V=255), it returns an answer that is within 1% of the original “perfect” hue in 99% of cases. In all cases, it is within 2% of the original hue value.

It is less precise as S and V do down from maximum values-- but still acceptably fast.

I suppose I could make a high precision version that was much slower, but for this pass in going for “useful in all cases, and great at pure hue recovery.”

@Mark_Kriegsman sounds like a good solution— as long as you put a disclaimer it’s fine.

Be nice to have an indication in the docs that something is perhaps more suitable for a Teensy 3.1 than an 8 MHz Arduino. Those using faster hardware can worry much less.

I’ve started measuring all my loops etc in microseconds to get a better idea of how long various bits of code are taking. It’s actually quite surprising. I thought I was being clever adding in an if statement to a piece of code to stop it from doing extraneous maths but it was horrendous for execution time!

Welcome to the brotherhood of the profiler, and I’m glad to have you here with us!

If I am running out of memory, then its definitely desirable. As it stands I maintain a crgb array, brightness array and hue array. But this might just be my ignorance of all the awesomeness that is in FastLED. I would love to hear how people get around modifying the brightness and or hue without already knowing what it was previously.

1.) Yes - RGB to HSV to manipulate the hue to ‘remix’ existing patterns
2.) Yes, I’d like to have H as well as S/V.

FTR I have my own c-code function I wrote to do the conversion.

Matt, that’s great! Would you be willing to let me look at your approach? I’m tryingn to solve sixteen problems at once and it might help clear my head a bit.

Wow, Whoops, total brain fart on my part. This was an HSL (vs HSV) conversion, and it was done in processing. Lesson: stay off social media while I’m working :stuck_out_tongue: !!

This is exactly what I need!

Ed: how are you using it (or rather, how do you envision using it)? And how much precision do you need in S and V, versus raw execution speed.
(As stated above, accuracy for Hue is very good, and reasonably fast, too.)

Mark,

I’m pretty new to controlling leds, so forgive me for my inexperience.

I’ve created a Arduino sketch using your 2.1 library to digitally control 150 pixels around my television and it works beautifully. I’m now trying to add in some older analog driven leds.

So, I’m attempting to average the values representing the left and right sides of my tv (digital strip) and write them out to analog.

This works, but the problem I’m having is that the averaged value decreases the brightness of the output and I can’t figure out how to scale the brightness of analog RGB values back up to what the digital is.

Daniel suggested (in my support post) looking at https://github.com/FastLED/FastLED/wiki/Pixel-reference#dimming-and-brightening-colors for scaling, but I haven’t pieced together (in my mind) an easy way to do it. I’ve tried the manual code for scaling from that link, but my output is either white (255) on all pins or 0.

So, I’m thinking that it would be so much simpler if I could convert my RGB value to Hue and then just plug in my global brightness variable to the Saturation and Value, convert it back to RGB and write it to the pins.

There are a couple of functions floating around on the net. But I’m trying to stay away from floating point arithmetic.

Sorry for the long answer. BTW, precision isn’t a big factor in my case.