tags:

views:

259

answers:

3

Hi. I have a color, which I only know at runtime. Using this color i want to create two new colors, one very bright and one none bright version of the color.

So to clarify, say i have the color Red; I want to create the hex-value for a "Light red" color, and a "Dark red" color.

How would i go about doing this? My code is written in Java using GWT.

+1  A: 

I don't know in wich format you have the color (I tried to see if GWT uses colors... but they rely heavily on CSS so they don't have specific properties).

Anyway, if you have one value for each component (Red, green, Blue), and each value ranges between 0 and 255 -this is standard- then apply this algorithm:

  • for each component
    • multiply the original value by a factor (let's say 1.1, 10% more bright)
    • convert the float/double value to int
    • if this value surpass 255, cut it to 255

Then you'll have a new color (a new three component tuple).

Hexa colors

If you have colors in the web format:

RRGGBB

RR - two hexa digits for red
GG - two hexa digits for green
BB - two hexa digits for blue

you'll need to convert them to int and back to hexa:

Hexa string to int

Integer.parseInt("AB", 16"); // returns 171

int to Hexa string

Integer.toHexaString(171); // returns "AB"
helios
+3  A: 

Convert the colours to the HSB/HSV (Hue-Saturation-Brightness/Value ) space and adjust the Brighness up for lighter and down for darker. Then convert back again. In Java:

    import java.awt.Color;

    float hsbVals[] = Color.RGBtoHSB( originalColour.getRed(),
                                       originalColour.getGreen(),
                                       originalColour.getBlue(), null );
    Color highlight = Color.getHSBColor( hsbVals[0], hsbVals[1], 0.5f * ( 1f + hsbVals[2] ));
    Color shadow = Color.getHSBColor( hsbVals[0], hsbVals[1], 0.5f * hsbVals[2] );

The HSB space is designed for this kind of operation.

The essential point is that you only need to vary the Brightness term to get the lightening/darkening effect you want. You'll have to experiment with how much you lighten/darken.

The above code shifts the Brightness to half-way towards white for the highlight and half-way to black for the shadow. (I used this code to create a higlighted border effect on a button.)

See: http://en.wikipedia.org/wiki/HSL_and_HSV and http://www.acasystems.com/en/color-picker/faq-hsb-hsv-color.htm

Adrian Pronk
A: 

There are at least two decent solutions to this, one better (more 'proper', anyway) than the other. It depends on what you want to use the colour for, or a tradeoff against short and simple code.

Using a colour space that models brightness

The problem is your colours are probably specified as RGB (ie, amounts of red, green and blue, reflecting your monitor.) The best way to change a colour's brightness is to specify your colours in a different colour space where brightness is one component, such as HSB - hue (the 'colour'), saturation ('amount' of the colour) and brightness (self-explanatory, I think!)

This Wikipedia article on HSL and HSV color models explains far more than you probably want to know :)

Have a look at this HSB demo.

The point is, once your colours are specified in a different space where one component is brightness, changing the brightness is easy because you can increase or decrease that component as you wish, in the same way you might increase or decrease the amount of blue in a RGB colour. Java, I think, has some colour conversion functions built in - some googling found this page with a handy example of Color.RGBtoHSB() and going back again with Color.HSBtoRGB.

Blending with white or black

This is hackier, but effective in most situations, and most code I've written that needs to get two versions of a colour (for a gradient, for example) for something unimportant like a UI background uses this sort of method. The logic is that a colour will be brighter as it gets closer to white (RGB 255,255,255) and darker as it gets closer to black (RGB 0,0,0). So to brighten something, blend with white by, say, 25%. You can blend between two colours by taking a proportion of one colour, and the inverse of that proportion of the other, for each channel / component.

The following is untested, and is a conversion of Delphi code I have used to do the same thing (the code is taken from memory, and on top of that I haven't used Java for years and don't remember the syntax and classes well, so I don't expect this to compile but you should be able to get an idea):

Color Blend(Color clOne, Color clTwo, float fAmount) {
    float fInverse = 1.0 - fAmount;

    // I had to look up getting colour components in java.  Google is good :)
    float afOne[] = new float[3];
    clOne.getColorComponents(afOne);
    float afTwo[] = new float[3]; 
    clTwo.getColorComponents(afTwo);    

    float afResult[] = new float[3];
    afResult[0] = afOne[0] * fAmount + afTwo[0] * fInverse;
    afResult[1] = afOne[1] * fAmount + afTwo[1] * fInverse;
    afResult[2] = afOne[2] * fAmount + afTwo[2] * fInverse;

    return new Color (afResult[0], afResult[1], afResult[2]);
}

And you'd probably use it like:

Color clBrighter = Blend(Color.red, Color.white, 0.25);

You might want to add some safety code, such as ensuring a clamp between 0..255 for each component, or checking that dAmount is truly in the range 0..1.

The Java Color documentation looks like the Color class has all sorts of useful methods. (Edit: I just noticed you said you're using gwt not awt - I haven't used it and have no idea what classes from standard Java are included. This should point you in the right direction anyway.) It's possible this is not the cleanest way in Java - that'll be due to my lack of knowledge of the classes and methods these days - but it should be enough to get you well down the track. Hope that helps!

David M