psihodelia psihodelia - 1 month ago 18
C Question

RGB palette designated for ordered values

I have a function f(x,y), mostly monotonic, which produces some values in the range {0.0 .. 100.0}. I would like to draw them using different colors as a 2D picture, where (x,y) are coordinates and where distinctive colors stand for distinctive values of the function. The problem is following: I don't know how to map the values of this function to RGB color space preserving the order (visibly). I have found that smth. like:

R = f(x,y) * 10.0f;
G = f(x,y) * 20.0f;
B = f(x,y) * 30.0f;
color = B<<16|G<<8|R; //@low-endian


works fine, but the resulting picture is too dark. If I increase these constants, it makes things not better, because at some moment a color component will be greater than 0xFF, so it will overflow (one color component should be in the range {0 .. 0xFF}.

Do you have any idea how to map values from {0.0 .. 100.0} to

RGB=[{0 .. 0xFF}<<16|{0 .. 0xFF}<<8|{0 .. 0xFF}] so that the resulting RGB values are visibly Ok?

PS: maybe you know, where to find more info about related theory online? I remember only Comp.Graphics by Foley/Van Dam, but I don't have this book.

UPDATE: I am looking for how to generate a chroma palette like one on the right:
enter image description here

Answer

You could just try clamping the values to a maximum of 255 (0xff).

R = min((int)(f(x,y) * 10.0f), 0xff);
G = min((int)(f(x,y) * 20.0f), 0xff);
B = min((int)(f(x,y) * 30.0f), 0xff);

Edit: There are a lot of different ways to convert to colors automatically, but you might find that none of them generates the exact progression you're looking for. Since you already have a picture of an acceptable palette, one method would be to create a lookup table of 256 colors.

#define RGB(R,G,B) (B<<16|G<<8|R)

int palette[256] = { RGB(0,0,0), RGB(0,0,128), ... };

int greyscale = (int)(f(x,y) * 2.559999);
assert(greyscale >= 0 && greyscale <= 255);
int rgb = palette[greyscale];

If the lookup table is too much trouble, you could also break the greyscale range into different subranges and do a linear interpolation between the endpoints of each range.

int interpolate(int from, int to, double ratio)
{
    return from + (int)((to - from) * ratio); 
}
if (greyscale <= 48)
{
    R = 0;
    G = 0;
    B = interpolate(0, 255, greyscale/48.0);
}
else if (greyscale <= 96)
{
    R = 0;
    G = interpolate(0, 255, (greyscale-48)/48.0);
    B = interpolate(255, 0, (greyscale-48)/48.0);
}
else if ...