12

The user of the ASP.NET web app I'm building can select colors for use on some of the elements (e.g. buttons/titles) to facilitate some degree of personalisation.

The problem is that by default the text on those layers is black...what I'm trying to do is to evaluate the HEX value chosen by the user through a picker, and switch between black and white text programmatically - this can be in JavaScript, or in code behind.

The crux of the problem is that I'm just not sure how to evaluate the HEX to make the decision whether the proximity of the chosen color to black is too close to use black text.

Any ideas?

Chris
  • 1,324
  • 5
  • 18
  • 29

4 Answers4

18

Instead of adding the RGB components together like the other answerer (ricknz) said, you should actually take the average of them.

Also, since green is more visible to the human eye than blue, you should also add a weight.

So you have to multiply the Red component first times 0.299, the Green times 0.587 and the Blue times 0.114

so the luminance is given by: Luminance = (r*0.299 + g*0.587 + b*0.114)/3

edit: here is a snippet which calculates it:

 float calcLuminance(int rgb)
 {
      int r = (rgb & 0xff0000) >> 16;
      int g = (rgb & 0xff00) >> 8;
      int b = (rgb & 0xff);

      return (r*0.299f + g*0.587f + b*0.114f) / 256;
 }

p.s. the division by 256 since we the RGB ran from 0-256 (instead of 0-1)

edit: changed the calculcation as to divide by 256 and not 768 as cleverly commented

Toad
  • 15,593
  • 16
  • 82
  • 128
  • 2
    If you're just comparing for light vs. dark, taking an average won't change the result. – RickNZ Nov 18 '09 at 07:56
  • in any case, `(r*0.299f + g*0.587f + b*0.114f)` will always be in the range 0-255, not 768 – nickf Nov 18 '09 at 08:01
  • This is a very interesting approach for calculating luminance, which will yield different results than my answer - which is the (as far as I know) standard luminance calculation. Where did you get the numbers from? – Johannes Hoff Nov 18 '09 at 08:51
  • 2
    johannes: wikipedia..where else ;^) http://en.wikipedia.org/wiki/YUV The Y part of YUV is luminance. – Toad Nov 18 '09 at 09:12
  • After testing (thanks to link provided by Johannes Hoff) this was comfortably the most reliable method, and handled the greens well which soon established themselves as a problem with the other methods. – Chris Nov 18 '09 at 13:40
  • @Toad - How do I first convert my hex to an int? So that I can use this method that you have? – chobo2 Apr 20 '11 at 19:35
  • @chobo: int number = Convert.ToInt32(hexString, 16); The 16 denotes the base (16 for hex). – Toad May 20 '11 at 07:18
10

Convert to HSL and look at the Luminance value. This will tell you how bright it is.

Here is a javascript function for doing the conversion.

Community
  • 1
  • 1
Johannes Hoff
  • 3,731
  • 5
  • 31
  • 37
  • To convert from the string to numbers, you can do for example `parseInt("coffee".substring(0,2), 16)` for red – Johannes Hoff Nov 18 '09 at 07:57
  • 1
    Thanks for the links (+1) they helped me build a quick tester - it worked great,but seemed to be less accurate on the greens and yellows as reinier suggested. – Chris Nov 18 '09 at 13:43
  • Link is broken. Please put the code in the answer, people! – Doug S Mar 22 '14 at 05:50
  • Doug S: I agree with code in the answer in general, but HSL conversion code is so big that I felt it would detract from the answer; rgb to hsl conversion code should be easy enough to find. I replaced the links with wikipedia and stackoverflow links. Hopefully they'll last longer :) – Johannes Hoff Mar 24 '14 at 22:36
5

The methods to do this are built into .Net now:

    var hexcolor = "#FA3CD0";
    var color = System.Drawing.ColorTranslator.FromHtml(hexcolor);
    var brightness = color.GetBrightness();
    if (brightness > .5)
    {
        // color is light
    }
    else
    {
        // color is dark
    }
CodeGrue
  • 5,865
  • 6
  • 44
  • 62
1

A hex color code is composed of three intensity values, one for red, one for green and one for blue, with 2 hex digits for each. To determine dark vs. light, simply add the three values together. Smaller numbers would be darker than larger values.

For #010203, adding the RGB values together gives 01+02+03 = 06. That will be darker than #102030 = 60.

RickNZ
  • 18,448
  • 3
  • 51
  • 66
  • Thanks - how would you evaluate when you get into the AA>FF values? – Chris Nov 18 '09 at 07:39
  • ricknz: this is incorrect since green is much more visible to the eye than blue – Toad Nov 18 '09 at 07:50
  • For AA to FF, you just need to convert the two-digit value from Hex, and then do the math. From JavaScript, you can use the parseInt() function. @reinier: true, but just adding them gives a rough approximation, and is equivalent to simple color --> grayscale/B&W conversion. – RickNZ Nov 18 '09 at 07:55
  • Worked well and really easy to implement - not as accurate IMO as the solution offered by reinier. Thanks again – Chris Nov 18 '09 at 13:44