1

I am trying to make a color change on a canvas in java to respresent how strong or weak the values respresented by color are relative to each other.

The rgb colors have to be the same color just different shades, like white to grey to black and every shade of grey in between. How can I change the rgb values considering that the values I am representing vary a lot, from -9999999 to positive 9999999.

anon
  • 697
  • 3
  • 14
  • 19

4 Answers4

4

I think you should take a look at HSL/HSV instead of RGB.

While RGB is elementary in nature in that it expresses colors in terms of the primaries, it does not allow you to make "understandable" changes to the R, G or B values to arrive at "similar" colors. With a HSL/HSV model, you will be able to make changes to Brightness/Lightness/Value (L/V) to arrive at colors with varying amounts of gray, or make changes to Hue (H) to obtain similar colors across the spectrum. You can start at full brightness (White) and create darker tones of gray by decreasing the value of L/V and eventually reach the color of no brightness (Black).

A very mild introduction to color theory, for developers is available here.

As to your question, you should express your colors in terms of HSL, with increasing values of Saturation to have a range of colors starting from white to black. Of course, if you want gray tones in between white and black without any other color, you should keep the hue to a minimum.

A short example on how to get a range of colors follows. For brevity, I've populated the colors into an array, but that is not required since you might want to use the color rightaway (besides considering memory requirements).

private Color[] produceColorRange(int steps)
{
    float value = 1.0f; //Starting with full brightness
    Color[] colors = new Color[steps];
    for(int ctr = 0; ctr < steps; ctr++)
    {
        value = value - (1.0f/steps); //tend to darkness
        int rgb = Color.HSBtoRGB(0.7f, 0.0f, value); //create a darker color
                                             //Hue is Blue, not noticeable
                                             //because Saturation is 0
        Color color = new Color(rgb);
        colors[ctr] = color;
    }
    return colors;
}

If you use the above method and paint a JFrame, you will be able to get a result similar to the one below (except that I've modified the hue and saturation to get my color range).

Color Range screenshot

Note that if you want a simpler way of getting a color range, initialize a Color object with Color.WHITE and invoke color.darker(). Of course, you will not be able to control the increment.

Community
  • 1
  • 1
Vineet Reynolds
  • 76,006
  • 17
  • 150
  • 174
  • This is probably what you want. Paul's solution will work, but only give you 255 different grays, and getting more of them is easiest to do in another color spaces like HSV – Mongoose Sep 14 '09 at 21:32
  • Great, I am using this in JavaScript. For the conversion this library can be used:http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript – Horst Walter Aug 28 '11 at 00:38
3

Yes, scale your values to fit your domain. That depends on how your RGB values are stored. Usually, 8 bits are used for each. Since grey has R = G = B, you want to scale values in range (-9999999,9999999) to (0, 255).

Consider x in the first interval. Since the first range covers also negative numbers, first, do a shift.

x = x + 9999999

Now x is in the interval (0, 19999998). And the next step is to scale it down to (0, 255). Since the colour values grow linearly in that interval, all you have to do is this:

x = x * 255 / 19999998

Now x is in the interval (0, 255) just like you want.

Generally, if your inital values are in an interval (a, b) and want to transform it into (0, c), apply this formula: (Note that a can be negative)

x = (x - a) * c / (b - a)

So if you R, G, B values are 16 bits long, c will be 2**16 = 65536 and the formula:

x = (x + 9999999) * 65536 / 19999998

Hope that helps.

Andrei Vajna II
  • 4,642
  • 5
  • 35
  • 38
0

I'm not completely sure I understand your question, but, if I do:

Why not just scale the RGB values to the values in your range (from -9999999 to positive 9999999)? Moreover, set R, G, and B all to the same value so that you're using shades of gray to represent the value.

Like this:

private final int MIN = -9999999;
private final int MAX = 9999999;

public Color getScaledColor(int val) {
    int gray = (int) Math.round((double) (val - MIN) / (double) (MAX - MIN)
            * 255.0);
    Color color = new Color(gray, gray, gray);

    return color;
}

Note that this solution will not give unique colors for all the values in the range you specified. But also keep in mind that the human eye can only distinguish between so many shades (and 2 * 9999999 + 1 is probably more than the number of shades than it can distinguish between).

Paul Reiners
  • 8,576
  • 33
  • 117
  • 202
0

The HSL Color class implements the formulas provided in the Wikipedia link on HSL/HSV provide above.

camickr
  • 321,443
  • 19
  • 166
  • 288