Generate RGB colors for rainbow

I'm currently trying to write a function that takes a percent value as an argument and returns the RGB HEX color of that percentual position in the "rainbow".

At first I thought this would be super easy:

uint32_t rainbow(positionInPercent) {
  return 0xFFFFFF*positionInPercent;
}

But as it turns out, this returns numbers that seem more random than anything else.
So I think I sort of need do different calculations on the single RGB components and somehow shift them together afterwards.
I'm pretty sure this can be done in a single line of code, but I just can't figure out the logic required to do it.

I really hope someone can help me out with this. :confused:

OK, it looks like you're using 24-bit colour. 8 bits for each of R, G and B. Those 8 bits can be represented with 2 hex digits, so FF is fully on and 00 is fully off for that channel.

So, let's start with just a little bit of R, G and B. Just one unit of each. That would be 0x010101. This is also the digital number 65793. Now that 50% of that: 32896, or 0x008080. That has no red at all and green and blue are about half brightness. That isn't halfway between very dark grey and black, is it?

So that indicates that you need to fade each colour channel independently. You have to take X% of the red, X% of green and x% of blue, then add them together to get a 24-bit representation. This will end up with a nice fade between any starting colour and black. You can fade between two colours by moving along the values between the two colours.

The rainbow is caused by the overlap between our eye's different colour sensors. It's red on one end, blue on the other and everything between is something different. The red sensors and green sensors are actually very close together on the spectrum. Also artefacts like the indigo end of the rainbow are caused by the spectrum going outside our visual range, so it appears darker than blue, even though the radiation intensity is the same. Simulating this on a computer monitor is a challenge.

You may also think that the rainbow goes from maximum-blue through maximum-green to maximum-red but that's not the way it works. If you just show a pure red pixel on the screen then that's actually a colour that doesn't exist in the rainbow. So making it look consistent without bright spots at R, G and B is more difficult than you think.

I would do this with 6-7 pre-defined colours. Like tent poles in the tent. Then for any point between those, I work out how far away the nearest tent poles are and blend those two colours. This is 15-20 lines of code, not just 1. Tune the relative brightness and spacing of those colours until it looks right.

Are you looking for just the 7 primary colours of the rainbow or the full colour spectrum?
Have a look at HSL colour wheel here if the full colour spectrum is okay. There are Arduino routines for converting HSL/HSV values to a RGB value you need for LED's.

A colour wheel is pretty easy - you use sin() offset be 120 degrees for red, green, and blue. But his gives you colours not on the rainbow (magenta, in particular).

felic:
I'm pretty sure this can be done in a single line of code, but I just can't figure out the logic required to do it.

I really hope someone can help me out with this. :confused:

I'm pretty sure it needs more than one line of code.

I'd start defining RGB color values for six basic rainbow colors:
Red - Orange- Yellow - Green-Blue- -violet

rainbow(0) would then correspond with red
rainbow(20) corresponds with orange
rainbow(40) correspnds with yellow
rainbow(60 corresponds with green
rainbox(80) corresponds with blue
rainbow(100) corresponds with violet
all other rainbow percentges have to be calculated to get intermediate RGB colors

Six colors mean that there are five intermediate ranges between the basic rainbow colors.
If you make each intermediate range 20 steps, you get 5 ranges * 20 steps = 100 steps total.
100 color steps from red to violet sounds suitable to me for use with apercent parameter. What do you think?