Created
October 3, 2016 20:49
-
-
Save ajai8085/bd873ebe12cd1a0ecc230cba715ce753 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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