Make foregroundcolor black or white depending on background

Solution 1:

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 at Nbd Tech that dealt with perceived colors and color conversion formula. The site gives a lot of information that is helpful.

Here's how to use this to select black or white:

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

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


Update: According to Darel Rex Finley at his site:

The values I came up with by playing with Photoshop were actually .241, .691, and .068, but I have since been informed that the values .299, .587, and .114 are more accurate.

This specification follows ITU-R Recommendation BT.601 (or Rec. 601 for short). The site I mentioned above, Nbd Tech, hasn't yet been updated to reflect this.

Based on this, here is the updated method (thanks to DTI-Matt for the comment):

private int PerceivedBrightness(Color c)
{
    return (int)Math.Sqrt(
    c.R * c.R * .299 +
    c.G * c.G * .587 +
    c.B * c.B * .114);
}

Note on threshold preference:

Colors with a perceived brightness near the middle (e.g. 120-140) will be more subjective. For example, it's debatable whether red (FF0000), which evaluates to 139, is clearer with a black or white overlay.

White and Black on Red

Solution 2:

what about that?

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

Solution 3:

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'.