views:

703

answers:

9

I'm not sure how to ask this but here goes.

I draw a filled coloured rectangle on screen. The colour is in form of R,G,B

I then want to draw text on top of the rectangle, however the colour of the text has to be such that it provides the best contrast, meaning it's readable.

Example:

If I draw a black rectangle, the obvious colour for text would be white.

What I tried right now is this. I pass this function the colour of the rectangle and it returns an inverted colour that I then use for my text.

It works, but it's not the best way.

Any suggestions?

// eg. usage: Color textColor = GetInverseLuminance(rectColor);
private Color GetInverseLuminance(Color color)
{
    int greyscale = (int)(255 - ((color.R * 0.30f) + (color.G * 0.59f) + (color.B * 0.11f)));

    return Color.FromArgb(greyscale, greyscale, greyscale);
}
+1  A: 

why grey? either black or white would be best. white on dark colors, black on light colors. just see if luminance is above a threshold and pick one or the other

(you don't need the .net, c# or asp.net tags, by the way)

Javier
+2  A: 

The most readable color is going to be either white or black. The most 'soothing' color will be something that is not white nor black, it will be a color that lightly contrasts your background color. There is no way to programmatically do this because it is subjective. You will not find the most readable color for everyone because everyone sees things differently.

+1  A: 

You need to study some color theory. A program called "Color Wheel Pro" is fun to play around with and will give you the general idea.

Essentially, you're looking for complimentary colors for a given color.

That said, I think you will find that while color theory helps, you still need a human eye to fine tune.

dicroce
if you simply complement color and keep luminance, a human eye won't pick edges so well (edges are the job of rods, color is done by cones). for readability you need maximum luminance contrast => black or white
Javier
+4  A: 

There's already an SO answer which is close: How to find good looking font color if background color is known? It has some code examples as well that might work for your specific problem.

yukondude
+1  A: 

Some tips about color, particularly concerning foreground and background juxtaposition, such as with text.

The human eye is essentially a simple lens, and therefore can only effectively focus on one color at a time. The lenses used in most modern cameras work around this problem by using multiple lenses of different refractive indexes (chromatic lenses) so that all colors are in focus at one time, but the human eye is not that advanced.

For that reason, your users should only have to focus on one color at a time to read the text. This means that either the foreground is in color, or the background, but never both. This leads to a condition typically called vibration, in which the eye rapidly shifts focus between foreground and background colors, trying to resolve the shape, but it never resolves, the shape is never in focus, and it leads to eyestrain.

TokenMacGuy
+2  A: 

Your function won't work if you supply it with RGB(127,127,127), because it will return the exact same colour. (modifying your function to return either black or white would slightly improve things)

The best way to always have things readable is to have white text with black around it, or the other way around.

It's oftenly achieved by first drawing black text at (x-1,y-1),(x+1,y-1),(x+1,y-1),(x+1,x+1), and then white text at (x,y).

Alternatively, you could first draw a semi-transparent black block, and then non-transparent white text over it. That ensures that there will always be a certain amount of contrast between your background and your text.

Wouter van Nifterick
A: 

Excellent suggestion guys. Well appreciated. One up for everyone :)

Looks like I will go with a black or white approach or look at the link provided by yukondude.

Gautam
+1  A: 

Visit: www.visibone.com

Where due consideration is given to those of us who cannot see colors at all!

Roger
+3  A: 

One simple approach that is guaranteed to give a significantly different color is to toggle the top bit of each component of the RGB triple.

Color inverse(Color c)
{
    return new Color(c.R ^ 0x80, c.G ^ 0x80, c.B ^ 0x80);
}

If the original color was #1AF283, the "inverse" will be #9A7203.

The contrast will be significant. I make no guarantees about the aesthetics.

Update, 2009/4/3: I experimented with this and other schemes. Results at my blog.

George V. Reilly
This is awesome, works very well.What does flipping the last bit actually achieve? Like what does mean and why does it work?
Gautam
Forgot to add, I used the method you posted but then turn the colour into a greyscale and it works very well in terms of contrast
Gautam
Another way to express it for each element is (c.R + 128) % 256. You move halfway across the colorspace. Or, if c.R was < 128, you add 128, significantly brightening, while if c.R was >= 128, you subtract 128, making it noticeably darker.
George V. Reilly
@Gautam: Check out this explanation on Wikipedia: http://en.wikipedia.org/wiki/Complementary_color
Sergio Acosta