views:

1262

answers:

7

I am trying to visualize some values on a form. They range from 0 to 200 and I would like the ones around 0 be green and turn bright red as they go to 200.

Basically the function should return color based on the value inputted. Any ideas ?

+7  A: 

red = (float)Val/200 *255 ;

green = (float)(200-val)/200 *255;

blue = 0;

return red <<16 + green << 8 + blue;

Peter Parker
This will make the midpoint (100) puke green: rgb(127, 127, 0). You would want your midpoint to be a bright yellow or orange. See: http://stackoverflow.com/questions/168838/color-scaling-function#168980
Ates Goral
I agree to this, that it will not look nice, however i am a coder and the midpoint was not part of the specification ;)
Peter Parker
+1  A: 

Looking through this wikipedia article I personally would pick a path through a color space, and map the values onto that path.

But that's a straight function. I think you might be better suited to a javascript color chooser you can find with a quick color that will give you the Hex, and you can store the Hex.

Tom Ritter
+3  A: 

Pick a green that you like (RGB1 = #00FF00, e.g.) and a Red that you like (RGB2 = #FF0000, e.g.) and then calculate the color like this

R = R1 * (200-i)/200 + R2 * i/200
G = G1 * (200-i)/200 + G2 * i/200
B = B1 * (200-i)/200 + B2 * i/200
Lou Franco
+2  A: 

For best controllable and accurate effect, you should use the HSV color space. With HSV, you can easily scale Hue, Saturation and/or Brightness seperate from each other. Then, you do the transformation to RGB.

ypnos
+4  A: 

You don't say in what environment you're doing this. If you can work with HSV colors, this would be pretty easy to do by setting S = 100 and V = 100, and determining H by:

H = 0.4 * value + 120

Converting from HSV to RGB is also reasonably easy.

[EDIT] Note: in contrast to some other proposed solutions, this will change color green -> yellow -> orange -> red.

eaolson
+5  A: 

Basically, the general method for smooth transition between two values is the following function:

function transition(value, maximum, start_point, end_point):
    return start_point + (end_point - start_point)*value/maximum

That given, you define a function that does the transition for triplets (RGB, HSV etc).

function transition3(value, maximum, (s1, s2, s3), (e1, e2, e3)):
    r1= transition(value, maximum, s1, e1)
    r2= transition(value, maximum, s2, e2)
    r3= transition(value, maximum, s3, e3)
    return (r1, r2, r3)

Assuming you have RGB colours for the s and e triplets, you can use the transition3 function as-is. However, going through the HSV colour space produces more "natural" transitions. So, given the conversion functions (stolen shamelessly from the Python colorsys module and converted to pseudocode :):

function rgb_to_hsv(r, g, b):
    maxc= max(r, g, b)
    minc= min(r, g, b)
    v= maxc
    if minc == maxc then return (0, 0, v)
    diff= maxc - minc
    s= diff / maxc
    rc= (maxc - r) / diff
    gc= (maxc - g) / diff
    bc= (maxc - b) / diff
    if r == maxc then
        h= bc - gc
    else if g == maxc then
        h= 2.0 + rc - bc
    else
        h = 4.0 + gc - rc
    h = (h / 6.0) % 1.0 //comment: this calculates only the fractional part of h/6
    return (h, s, v)

function hsv_to_rgb(h, s, v):
    if s == 0.0 then return (v, v, v)
    i= int(floor(h*6.0)) //comment: floor() should drop the fractional part
    f= (h*6.0) - i
    p= v*(1.0 - s)
    q= v*(1.0 - s*f)
    t= v*(1.0 - s*(1.0 - f))
    if i mod 6 == 0 then return v, t, p
    if i == 1 then return q, v, p
    if i == 2 then return p, v, t
    if i == 3 then return p, q, v
    if i == 4 then return t, p, v
    if i == 5 then return v, p, q
    //comment: 0 <= i <= 6, so we never come here

, you can have code as following:

start_triplet= rgb_to_hsv(0, 255, 0) //comment: green converted to HSV
end_triplet= rgb_to_hsv(255, 0, 0) //comment: accordingly for red

maximum= 200

… //comment: value is defined somewhere here

rgb_triplet_to_display= hsv_to_rgb(transition3(value, maximum, start_triplet, end_triplet))
ΤΖΩΤΖΙΟΥ
+1; I was going to ask a new question about how to improve a color algorithm i have for coloring a bar chart in HTML/PHP... SO suggested this question as similar and your answer helped me fix the issue without having to ask the question! Thanks!
beggs
+1, and a better name for your `transition` function would be `lerp` as that's mathematically what you're doing: http://en.wikipedia.org/wiki/Lerp_(computing)
Keith
+1  A: 

If you use linear ramps for Red and Green values as Peter Parker suggested, the color for value 100 will basically be puke green (127, 127, 0). You ideally want it to be a bright orange or yellow at that midpoint. For that, you can use:

Red = max(value / 100, 1) * 255
Green = (1 - max(value / 100, 1)) * 255
Blue = 0
Ates Goral