views:

1890

answers:

6

This should be a simple question, but I haven't been able to find a way to make it work.

Essentially, I have a silly localhost page that I use in my webdevelopment. When I am surfing between our development server and my local version of the C# code (redirected from the dev url via host file) I have been known to sometimes forget what 'dev.foo.com' points at - local or server.

So I created a page which will run locally as my default web page's default page, so I can easily identify my localhost from the server.

This page does a lot of things randomly (including generating a character's starting stats for D&D), including setting a random background color. I do this by generating 3 random numbers between 0 and 255, and setting them as the RGB value for the body background color in CSS.

Given the 3 ints R, G, and B, how do I determine R2, G2, and B2 such that the second color will have high contrast with the first? I like having the page have random background colors (it keeps me from getting used to the look of the landing page) but I also like to be able to read the text.

A: 

If you flip all the bits, you will get the "opposite" color which would be pretty good contrast.

I believe it's the ~ operator in C#:

R2 = ~R1;
G2 = ~G1;
B2 = ~B1;
bobwienholt
That doesn't work well for colors near the "middle" of the color histogram, like #808080.
Tim Lesher
That's true... but opposite color's have the added benefit of looking pleasing to the eye when put next to each other.
bobwienholt
Tim, you can go ahead and phrase it a bit stronger - it doesn't work at all. :-)
mhenry1384
You could add some "if" statement for those "middle" cases where it doesn't work correctly. You could also have something like "if(light) return Black; else return White;" but that'd obviously reduce the ammount of output colors.
luiscubal
Jeff
+3  A: 

"Contrast" is a loaded word. If you just care about being able to read the text, then one easy way is to work in a luminance-based color space like HSL, and pick foreground and background colors with big differences in luminance.

The conversion between HSL and RGB is well-known--see Wikipedia for the details.

If you're talking about actual color contrast, it's not nearly as cut-and-dried (there are a lot of perceptual factors that, as far as I know, haven't been reduced to a single colors space), but I suspect you don't need that level of sophistication.

Tim Lesher
there is a class that deals with HSL conversions that can be found here http://richnewman.wordpress.com/2007/05/07/using-hsl-color-hue-saturation-luminosity-to-create-better-looking-guis-part-2/
KevB
+1  A: 

I did something like this in a Palm OS application. This is what I came up with. It doesn't give you "high contrast" colors but it gives you a background color that's different enough from the text color to be quite readable:

  // Black background is a special case.  It's fairly likely to occur and 
  // the default color shift we do isn't very noticeable with very dark colors.
  if (backColor.r < 0x20 && backColor.g < 0x20 && backColor.b < 0x20)
  {
   textColor.r = backColor.r + 0x20;
   textColor.g = backColor.g + 0x20;
   textColor.b = backColor.b + 0x20;
  }
  else
  {
   textColor.r = backColor.r + ((backColor.r < 128) ? 0x10 : -0x10);
   textColor.g = backColor.g + ((backColor.g < 128) ? 0x10 : -0x10);
   textColor.b = backColor.b + ((backColor.b < 128) ? 0x10 : -0x10);
  }

You might not need to do black as a special case for your purposes - Palm's color handling is a bit funky (16-bit color).

mhenry1384
+1  A: 

There are some good resources (and algorithms) to address this at http://juicystudio.com/article/luminositycontrastratioalgorithm.php

Michael Bray
+5  A: 

You need a difference in brightness for text to be readable, as color vision itself has too low resolution.

So as an algorithm I'd suggest the following:

  • Pick a random background color.

  • Then decide whether it is a light or a dark color. For example you could check whether the average of the three primary colors is greater or equal 128.

  • For a light color use black text, for a dark one white text.

starblue
This is a fairly simple solution, and one that (now) is working fairly well.I'm going to try this for a while, as it IS always readable, if a bit plain.
Jeff
+1  A: 

Check out this PHP solution: Calculating Color Contrast with PHP by Andreas Gohr. It can be ported to any language of course.

He also has a very nice demonstration of his contrast analyzer where you can find some minimal contrast levels to work with.

tharkun