tags:

views:

65

answers:

5

Something like calculating the average value of rgb components and then decide whether to use black or white?

Do I have to convert RGB to HSV in first step 'cause RGB is not always what the human eyes see?

I'm using C#

A: 

You could do a simple calculation depending on color depth, if say you had a #FFFFFF color format, you could just add the RGB values and calculate if they're under half way.

The max in that case is 255 (F x F = 256) per, so just check if it's under that threshold:

var colorCode = ((R + B + G) < 255*3) ? "#FFFFFF" : "#000000";

If the color's below, it's darker...use a white background. If it's above, it's lighter...use a black background. It's not perfect, but an idea to get started.

Nick Craver
I tried something like this originally in my project, and it resulted in some occasions where the white/black labels were not as noticeable against their background colors.
JYelton
+6  A: 

It just so happens I needed this function for a project not long ago.

private int PerceivedBrightness(Color c)
{
    return (int)Math.Sqrt(
    c.R * c.R * .241 +
    c.G * c.G * .691 +
    c.B * c.B * .068);
}

This formula I found on the web somewhere that dealt with perceived colors and color conversion formula. If you need the source I'll see if I can find it again.

Edit: The formula can be found here: Nbd Tech The site gives a lot of information that is helpful.

Edit 2: For anyone not sure how to use this to select black or white:

Color foreColor = (PerceivedBrightness(backColor) > 130 ? Color.Black : Color.White);

You can adjust use a value other than 130 as the cutoff, it is preference.

JYelton
This is basically the formula for luma, squaring values to give outliers more weight. The result is a 0-255 scale. http://en.wikipedia.org/wiki/Luma_%28video%29
Rob Elliott
That's correct, except luminance alone isn't quite sufficient to determine whether a black or white foreground color is more readable, at least in my experiments.
JYelton
A: 

If I'm understanding correctly, one approach might be to get hold of the desktop wallpaper image, check in some manor what colour it is and then change your application colour based on that.

There's an article on geekpedia about getting hold of the current desktop wallpaper (and lots of hits on google on that), but the basic premise is to grab the registry value of the current wallpaper:

RegistryKey rkWallPaper = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", false);
string WallpaperPath = rkWallPaper.GetValue("WallPaper").ToString();

You could then use that path to open the image. You can then get hold of lots of properties, such as the dimensions and individual pixel colours in RGB.

To work out whether it's "more white" or "more black" you have many options.

One idea would be to get each pixel colour in RGB, average the values (to get the greyscale value) and then average the greyscale value of each pixel across the image. If this comes out > 128 then it could be condidered to be "white". If < 128 then "black". Basically you are deciding which side of the mid-grey dividing line the images pixel intensities average out to.

// Psudo code - can't check the C# spec atm.
foreach(Pixel p in image)
{
    // get average of colour components.
    double greyScale = (p.Red + p.Green + p.Blue) / 3;
    totalIntensity += greyScale;
}

double averageImageIntensity = totalIntensity / image.NumPixels;

if(totalIntensity > 128) // image could be considered to be "white"
else // image could be considered "black".

Problems: could be a slow procedure, you might want to sample only some of the pixels (say, every 10th one etc.) to save time. More generally, it seems like a fairly hacky thing to be doing at all. Pulling user files at run-time and messing with them is hardly clean, and it provides potential security and stability concerns. What if the image is duff or corrupt etc.

Personally I'd suggest simply giving the user the choice of colour / theme / skin themselves, or better yet let them customise it!

xan
I don't want to change the whole app color. I'm using a listview in which items have bg color and the text of each item should be readable...
Kai
A: 

what about that?

private static Color GetReadableForeColor(Color c)
{
    return (((c.R + c.B + c.G) / 3) > 128) ? Color.Black : Color.White;
}
Kai
A: 

The Color struct supports conversion to HSB natively.

if (Color.GetBrightness() > 0.5f) {
  // win
}

You may want to add a component of saturation as well, considering saturation also contributes to apparent 'lightness'.

Ron Warholic