Reputation: 85715
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?
Upvotes: 25
Views: 59086
Reputation: 11
When you first translated from hex to rgb one way or other...
You know the total value of rgb 3 * 256 = 768. Half of that (384) would be the turning point between white or black text color. And you do not have to complicate it more because the closer the color is at the center the less it would matter if the text is white or black.
private static string GetTextColor(string backgroundColor)
{
string color = "000000";
Color bg = ColorTranslator.FromHtml("#" + backgroundColor);
if (bg.R + bg.G + bg.B < 384)
{
color = "FFFFFF";
}
return color;
}
Note that the method uses hex color without the hashtag.
Upvotes: 0
Reputation: 706
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);
Upvotes: 2
Reputation: 82231
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
Upvotes: 22
Reputation: 586
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;
}
Upvotes: 2
Reputation: 46909
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
}
}
Upvotes: 4
Reputation: 85957
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.
Upvotes: 9
Reputation: 55417
Just convert the hex string to an integer:
int color = Convert.ToInt32("FFFFFF", 16);
Upvotes: 28
Reputation: 17782
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.
Upvotes: 2