Skip to content

Instantly share code, notes, and snippets.

@ajai8085
Created October 3, 2016 20:49
Show Gist options
  • Save ajai8085/bd873ebe12cd1a0ecc230cba715ce753 to your computer and use it in GitHub Desktop.
Save ajai8085/bd873ebe12cd1a0ecc230cba715ce753 to your computer and use it in GitHub Desktop.
public static class DynamicColorGenExtensions
{
//Find foreground color for a dynamic background color
public static Color FindForgroundColor(this Color color)
{
if (color.R <= 5 && color.G <= 5 && color.B <= 5)
{
return Color.WhiteSmoke;
}
var delta = 0.05d;
var resultRatio = 4.5d;
var colorHsl = (HSLColor)color;
var lumocity = colorHsl.Luminosity;
var resLumocity = 0d;
double lightness;
if (IsLightColor(color, out lightness))
{
//Find more darker color
resLumocity = ((lumocity + delta) / resultRatio) - delta;
}
else
{
//Find more lighter color
if (lightness <= 15)
{
resultRatio = 21d - lightness;
delta = 0;
}
resLumocity = ((lumocity + delta) * resultRatio) - delta;
}
colorHsl.Luminosity = resLumocity;
return (Color)colorHsl;
}
public static bool IsLightColor(Color bg, out double lightness)
{
//https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness
int nThreshold = 150;
//int nThreshold = 128;
lightness = ((bg.R * 0.299d) + (bg.G * 0.587d) +
(bg.B * 0.114d));
var bgDelta = (int)lightness;
var isLight = (255 - bgDelta < nThreshold) ? true : false;
//Console.WriteLine(string.Format(@"Color is {0} with delta {1} lightness {2}", isLight ? "Light" : "dark", bgDelta, lightness));
return isLight;
}
//https://richnewman.wordpress.com/about/code-listings-and-diagrams/hslcolor-class/
private class HSLColor
{
// Private data members below are on scale 0-1
// They are scaled for use externally based on scale
private double hue = 1.0;
private double saturation = 1.0;
private double luminosity = 1.0;
private const double scale = 240.0;
public double Hue
{
get { return hue * scale; }
set { hue = CheckRange(value / scale); }
}
public double Saturation
{
get { return saturation * scale; }
set { saturation = CheckRange(value / scale); }
}
public double Luminosity
{
get { return luminosity * scale; }
set { luminosity = CheckRange(value / scale); }
}
private double CheckRange(double value)
{
if (value < 0.0)
value = 0.0;
else if (value > 1.0)
value = 1.0;
return value;
}
public override string ToString()
{
return String.Format("H: {0:#0.##} S: {1:#0.##} L: {2:#0.##}", Hue, Saturation, Luminosity);
}
public string ToRGBString()
{
Color color = (Color)this;
return String.Format("R: {0:#0.##} G: {1:#0.##} B: {2:#0.##}", color.R, color.G, color.B);
}
#region Casts to/from System.Drawing.Color
public static implicit operator Color(HSLColor hslColor)
{
double r = 0, g = 0, b = 0;
if (hslColor.luminosity != 0)
{
if (hslColor.saturation == 0)
r = g = b = hslColor.luminosity;
else
{
double temp2 = GetTemp2(hslColor);
double temp1 = 2.0 * hslColor.luminosity - temp2;
r = GetColorComponent(temp1, temp2, hslColor.hue + 1.0 / 3.0);
g = GetColorComponent(temp1, temp2, hslColor.hue);
b = GetColorComponent(temp1, temp2, hslColor.hue - 1.0 / 3.0);
}
}
return Color.FromArgb((int)(255 * r), (int)(255 * g), (int)(255 * b));
}
private static double GetColorComponent(double temp1, double temp2, double temp3)
{
temp3 = MoveIntoRange(temp3);
if (temp3 < 1.0 / 6.0)
return temp1 + (temp2 - temp1) * 6.0 * temp3;
else if (temp3 < 0.5)
return temp2;
else if (temp3 < 2.0 / 3.0)
return temp1 + ((temp2 - temp1) * ((2.0 / 3.0) - temp3) * 6.0);
else
return temp1;
}
private static double MoveIntoRange(double temp3)
{
if (temp3 < 0.0)
temp3 += 1.0;
else if (temp3 > 1.0)
temp3 -= 1.0;
return temp3;
}
private static double GetTemp2(HSLColor hslColor)
{
double temp2;
if (hslColor.luminosity < 0.5) //<=??
temp2 = hslColor.luminosity * (1.0 + hslColor.saturation);
else
temp2 = hslColor.luminosity + hslColor.saturation - (hslColor.luminosity * hslColor.saturation);
return temp2;
}
public static implicit operator HSLColor(Color color)
{
HSLColor hslColor = new HSLColor();
hslColor.hue = color.GetHue() / 360.0; // we store hue as 0-1 as opposed to 0-360
hslColor.luminosity = color.GetBrightness();
hslColor.saturation = color.GetSaturation();
return hslColor;
}
#endregion
public void SetRGB(int red, int green, int blue)
{
HSLColor hslColor = (HSLColor)Color.FromArgb(red, green, blue);
this.hue = hslColor.hue;
this.saturation = hslColor.saturation;
this.luminosity = hslColor.luminosity;
}
public HSLColor() { }
public HSLColor(Color color)
{
SetRGB(color.R, color.G, color.B);
}
public HSLColor(int red, int green, int blue)
{
SetRGB(red, green, blue);
}
public HSLColor(double hue, double saturation, double luminosity)
{
this.Hue = hue;
this.Saturation = saturation;
this.Luminosity = luminosity;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment