25

I am trying to use this to figure out if a color is light or dark

Evaluate whether a HEX value is dark or light

Now. It takes in a int

 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;
 }

I have a hex color though.

I tried to do this

  var color = System.Drawing.ColorTranslator.FromHtml("#FFFFFF");
  int rgb = color.R + color.G + color.B;
   var a = calcLuminance(rgb);

I got 0.11725 I thought it would have to be in the range of 0-256 or something like that.

What am I doing wrong? Do I have to covert R to an int? Or am I just way off?

Community
  • 1
  • 1
chobo2
  • 83,322
  • 195
  • 530
  • 832

9 Answers9

28

Just convert the hex string to an integer:

int color = Convert.ToInt32("FFFFFF", 16);
Chris Haas
  • 53,986
  • 12
  • 141
  • 274
  • 1
    Whoops, I upvoted this because I misread the question. He is not actually asking "How to convert from hex to RGB" - what he really wants to know is how to get the brightness (luminance) of an RGB color. – BlueRaja - Danny Pflughoeft Apr 20 '11 at 20:09
  • 1
    He's got two different potential questions. "How to do x" and "Is there a better way than x". I answered the first one and you answered the second! – Chris Haas Apr 20 '11 at 20:12
21

You can use:

public string GenerateRgba(string backgroundColor, decimal backgroundOpacity)
{
 Color color = ColorTranslator.FromHtml(hexBackgroundColor);
 int r = Convert.ToInt16(color.R);
 int g = Convert.ToInt16(color.G);
 int b = Convert.ToInt16(color.B);
 return string.Format("rgba({0}, {1}, {2}, {3});", r, g, b, backgroundOpacity);
}

Link To original Post by jeremy clifton on git

StudioLE
  • 656
  • 8
  • 13
Milind Anantwar
  • 81,290
  • 25
  • 94
  • 125
9

I am trying to use this to figure out if a color is light or dark

Just use Color.GetBrightness()


[Edit]

I want to determine if I should use white or black for my text. So anything ≤ .5 I should use white and > .5 black?

There are a number of ways to determine what color to use on a given background, none of which are perfect.

That last link actually recommends using black/white only, but choosing a cutoff point of 0.73 instead of 0.5. I think you should just go with that, and change it if you find it doesn't work for you.

Community
  • 1
  • 1
BlueRaja - Danny Pflughoeft
  • 84,206
  • 33
  • 197
  • 283
  • @BlueRaja - Danny Pflughoeft- so something like this System.Drawing.Color someColor = System.Drawing.Color.FromArgb(color.R, color.G, color.B); float ab = someColor.GetBrightness(); Is there anyway to do this without converting it first to rgb? – chobo2 Apr 20 '11 at 20:12
  • 4
    @chobo2 Just `float ab = System.Drawing.ColorTranslator.FromHtml("#FFFFFF").GetBrightness();` :) – Lasse Espeholt Apr 20 '11 at 20:14
  • @Chobo: Well, how are you *inputting* the color into the computer? The example you gave **is** RGB: in `"#FFFFFF"`, the first `"FF"` is the R *(in hexadecimal)*, the second `"FF"` is the G, and the third `"FF"` is the B. As @lasseespeholt states in the comment above, you can get the brightness from your RGB-string in one line. – BlueRaja - Danny Pflughoeft Apr 20 '11 at 20:15
  • @lasseespeholt - Cool. So I want to determine if I should use white or black for my text. So anything that is .5 and less should I use white and if greater than .5 I should use black? – chobo2 Apr 20 '11 at 20:17
  • Luminance and Brightness are not the same thing. I got better results using Luminance to determine if a color was dark or light – Magnus Apr 20 '11 at 20:17
  • @chobo2: that would work, though values near 0.5 might not give good results using *either* black or white :) – BlueRaja - Danny Pflughoeft Apr 20 '11 at 20:18
  • @chobo2 I've no idea to be honest ;) I know nothing about colors and how humans interpret them => I do not know when it is best to switch or what method you should use to determine it :) I hope others can help you... – Lasse Espeholt Apr 20 '11 at 20:19
  • @ BlueRaja - Danny Pflughoeft - hmm would you know how to choose a color for those? – chobo2 Apr 20 '11 at 20:24
  • @Magnus - Hmm well I am looking for whatever will help me figure out what color to use for text color. Originally I was thinking it is either black or white but now I am not sure. I don't want to spend too long on this so I can only get it to figure out to use white or black and that is good for 80% of the cases then I will be happy with that. If someone knows how to get close to 100% good then I will go with that. – chobo2 Apr 20 '11 at 20:26
4

A little of topic, but here is an extension method to the Color struct I've created to calculate Luminance with different algorithms. Hope it helps you.

public static class ColorExtensions
{
    /// <summary>
    /// Gets the luminance of the color. A value between 0 (black) and 1 (white)
    /// </summary>
    /// <param name="color">The color.</param>
    /// <param name="algorithm">The type of luminance alg to use.</param>
    /// <returns>A value between 0 (black) and 1 (white)</returns>
    public static double GetLuminance(this Color color, LuminanceAlgorithm algorithm = LuminanceAlgorithm.Photometric)
    {
        switch (algorithm)
        {
            case LuminanceAlgorithm.CCIR601:
                return (0.2126 * color.R + 0.7152 * color.G + 0.0722 * color.B) / 255;

            case LuminanceAlgorithm.Perceived:
                return (Math.Sqrt(0.241 * Math.Pow(color.R, 2) + 0.691 * Math.Pow(color.G, 2) + 0.068 * Math.Pow(color.B, 2)) / 255);

            case LuminanceAlgorithm.Photometric:
                return (0.299 * color.R + 0.587 * color.G + 0.114 * color.B) / 255;
        }

    }

   /// <summary>
   /// The luminances
   /// </summary>
   public enum LuminanceAlgorithm
   {
       /// <summary>
       /// Photometric/digital ITU-R
       /// </summary>
       Photometric,

       /// <summary>
       /// Digital CCIR601 (gives more weight to the R and B components, as preciev by the human eye)
       /// </summary>
       CCIR601,

       /// <summary>
       /// A perceived luminance
       /// </summary>
       Perceived
   }
}
Magnus
  • 45,362
  • 8
  • 80
  • 118
2

The problem, as I see it, is your calculation of rgb. You add the values together which gives you a number between 0 and 3*255 which clearly isn't the value your method expect. You will have to calculate it like this

int rgb = (int)color.R << 16 + (int)color.G << 8 + color.B;

which should be equivalent to this (except for the alpha-value you don't use)

int rgb = color.ToArgb();

Lastly, as you can see in Chris Haas answer, you can skip this step by converting directly to an int.

Lasse Espeholt
  • 17,622
  • 5
  • 63
  • 99
2

Your idea is OK, but your function is wrong, correct one is here:

int rgb = Convert.ToInt32("#FFFFFF", 16);
var a = calcLuminance(rgb);

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;
}
Xiaohuan ZHOU
  • 478
  • 5
  • 6
1

The ranges of the R, G and B from the Color struct are 0-255.

To get the rgb value you expect in your function, you will need to left shift accordingly:

int rgb = (int)color.R << 16 + (int)color.G << 8 + color.B;
Oded
  • 489,969
  • 99
  • 883
  • 1,009
1

calcLuminance only returns a percentage.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
1

You can also convert HEX to RGB without using System.Drawing with this :

 int RGBint = Convert.ToInt32("FFD700", 16);
 byte Red = (byte)((RGBint >> 16) & 255);
 byte Green = (byte)((RGBint >> 8) & 255);
 byte Blue = (byte)(RGBint & 255);
 //Color.FromRgb(Red, Green, Blue);
SioGabx
  • 344
  • 1
  • 8
  • [This answer](https://stackoverflow.com/a/5735950/3744182) by [Chris Haas](https://stackoverflow.com/users/231316/chris-haas) already suggests using `Convert.ToInt32`: *Just convert the hex string to an integer: `int color = Convert.ToInt32("FFFFFF", 16);`*. – dbc Dec 10 '22 at 20:00