improvements to MBS.Framework.Drawing.Color

This commit is contained in:
Michael Becker 2021-04-29 22:33:58 -04:00
parent ba7f6a497a
commit 014a9b99c4
No known key found for this signature in database
GPG Key ID: 98C333A81F18C22C

View File

@ -23,7 +23,7 @@ using System.Text;
namespace MBS.Framework.Drawing namespace MBS.Framework.Drawing
{ {
public struct Color public struct Color : ICloneable
{ {
public static readonly Color Empty; public static readonly Color Empty;
@ -66,6 +66,14 @@ namespace MBS.Framework.Drawing
return Color.FromRGBADouble(((double)r / 255), ((double)g / 255), ((double)b / 255), ((double)a / 255)); return Color.FromRGBADouble(((double)r / 255), ((double)g / 255), ((double)b / 255), ((double)a / 255));
} }
public static Color FromCMYKDouble(double c, double m, double y, double k, double a = 255)
{
double r = (1 - c) * (1 - k);
double g = (1 - m) * (1 - k);
double b = (1 - y) * (1 - k);
return Color.FromRGBADouble(r, g, b, a);
}
public static Color Parse(string value) public static Color Parse(string value)
{ {
return Color.FromString(value); return Color.FromString(value);
@ -131,18 +139,34 @@ namespace MBS.Framework.Drawing
{ {
return (byte)(mvarR * 255); return (byte)(mvarR * 255);
} }
public double GetRedFraction()
{
return R;
}
public byte GetGreenByte() public byte GetGreenByte()
{ {
return (byte)(mvarG * 255); return (byte)(mvarG * 255);
} }
public double GetGreenFraction()
{
return G;
}
public byte GetBlueByte() public byte GetBlueByte()
{ {
return (byte)(mvarB * 255); return (byte)(mvarB * 255);
} }
public double GetBlueFraction()
{
return B;
}
public byte GetAlphaByte() public byte GetAlphaByte()
{ {
return (byte)(mvarA * 255); return (byte)(mvarA * 255);
} }
public double GetAlphaFraction()
{
return A;
}
public string ToHexadecimalVB() public string ToHexadecimalVB()
{ {
@ -183,123 +207,149 @@ namespace MBS.Framework.Drawing
return ToHexadecimalHTML(); return ToHexadecimalHTML();
} }
public double GetHueFraction()
{
return Hue;
}
public void SetHueFraction(double value)
{
Hue = value;
}
public double GetHueScaled(double scale = 240.0)
{
return GetHueFraction() * scale;
}
public void SetHueScaled(double value, double scale = 240.0)
{
SetHueFraction(value / scale);
}
public double Hue public double Hue
{ {
get get
{ {
int r = this.GetRedByte(); GetMinMax(out double min, out double max);
int g = this.GetGreenByte(); if (max == min) return 0.0;
int b = this.GetBlueByte();
byte minRGB = (byte)Math.Min (r, Math.Min (g, b)); double hue = 0.0;
byte maxRGB = (byte)Math.Max (r, Math.Max (g, b)); if (R == max)
if (maxRGB == minRGB) return 0.0;
float num = (float)(maxRGB - minRGB);
float redFraction = (float)((int)maxRGB - r) / num;
float greenFraction = (float)((int)maxRGB - g) / num;
float blueFraction = (float)((int)maxRGB - b) / num;
float hue = 0f;
if (r == (int)maxRGB)
{ {
hue = 60f * (6f + blueFraction - greenFraction); hue = (G - B) / (max - min);
} }
if (g == (int)maxRGB) else if (G == max)
{ {
hue = 60f * (2f + redFraction - blueFraction); hue = 2.0 + (B - R) / (max - min);
} }
if (b == (int)maxRGB) else if (B == max)
{ {
hue = 60f * (4f + greenFraction - redFraction); hue = 4.0 + (R - G) / (max - min);
} }
if (hue > 360f) return ((hue * 60) / 360);
{
hue -= 360f;
}
return (double)(hue / HSL_SCALE);
} }
set { UpdateHSL (value, Saturation, Luminosity); } set { UpdateHSL (value, Saturation, Luminosity); }
} }
public int HueInt32
{
get { return (int)(Hue * HSL_SCALE); }
set { Hue = CheckRange ((double)value / HSL_SCALE); }
}
public double Saturation public double Saturation
{ {
get get
{ {
int minRGB = Math.Min (this.GetRedByte(), Math.Min (this.GetGreenByte(), this.GetBlueByte())); GetMinMax(out double min, out double max);
int maxRGB = Math.Max (this.GetRedByte(), Math.Max (this.GetGreenByte(), this.GetBlueByte())); if (min == max) return 0.0;
if (maxRGB == minRGB) return 0.0;
int num = (int)(maxRGB + minRGB); if (Luminosity <= 0.5)
if (num > 255)
{ {
num = 510 - num; return (max - min) / (max + min);
} }
return (double)((double)(maxRGB - minRGB) / (double)num) / HSL_SCALE; return (max - min) / (2.0 - max - min);
} }
set { UpdateHSL (Hue, value, Luminosity); } set { UpdateHSL (Hue, value, Luminosity); }
} }
public int SaturationInt32
{
get { return (int)(Saturation * HSL_SCALE); }
set { Saturation = CheckRange ((double)value / HSL_SCALE); }
}
public double Luminosity public double Luminosity
{ {
get get
{ {
int minRGB = Math.Min (this.GetRedByte(), Math.Min (this.GetGreenByte(), this.GetBlueByte())); GetMinMax(out double min, out double max);
int maxRGB = Math.Max (this.GetRedByte(), Math.Max (this.GetGreenByte(), this.GetBlueByte())); return (min + max) / 2;
return (double)((double)(maxRGB + minRGB) / 510.0) / HSL_SCALE;
} }
set { UpdateHSL (Hue, Saturation, value); } set { UpdateHSL (Hue, Saturation, value); }
} }
public int LuminosityInt32 public double GetLuminosityFraction()
{ {
get { return (int)(Luminosity * HSL_SCALE); } return Luminosity;
set { Luminosity = CheckRange ((double)value / HSL_SCALE); } }
private void GetMinMax(out double min, out double max)
{
min = Math.Min(GetRedFraction(), Math.Min(GetGreenFraction(), GetBlueFraction()));
max = Math.Max(GetRedFraction(), Math.Max(GetGreenFraction(), GetBlueFraction()));
}
private void GetMinMax(out byte min, out byte max)
{
min = Math.Min(GetRedByte(), Math.Min(GetGreenByte(), GetBlueByte()));
max = Math.Max(GetRedByte(), Math.Max(GetGreenByte(), GetBlueByte()));
}
public static Color FromHSL(int h, int s, int l, double scale = 240.0)
{
return FromHSL ((double)h / scale, (double)s / scale, (double)l / scale);
} }
private void UpdateHSL(double h, double s, double l) private void UpdateHSL(double h, double s, double l)
{ {
if (l != 0) if (s == 0.0)
{ {
if (s == 0) R = l;
R = G = B = l; G = l;
else B = l;
{ return;
double temp2 = GetTemp2(h, s, l);
double temp1 = 2.0 * l - temp2;
R = GetColorComponent(temp1, temp2, h + 1.0 / 3.0);
G = GetColorComponent(temp1, temp2, h);
B = GetColorComponent(temp1, temp2, h - 1.0 / 3.0);
} }
double temp1 = 0.0;
if (l < 0.5)
{
temp1 = l * (1.0 + s);
}
else if (l >= 0.5)
{
temp1 = (l + s) - (l * s);
}
double temp2 = 2 * l - temp1;
double tempR = h + 0.333;
double tempG = h;
double tempB = h - 0.333;
R = GetHSLTempValue(tempR, temp1, temp2);
G = GetHSLTempValue(tempG, temp1, temp2);
B = GetHSLTempValue(tempB, temp1, temp2);
}
private static double GetHSLTempValue(double tempX, double temp1, double temp2)
{
if (6 * tempX < 1)
{
return temp2 + (temp1 - temp2) * 6 * tempX;
} }
else else
{ {
R = 0.0; if (2 * tempX < 1)
G = 0.0;
B = 0.0;
}
}
private const double HSL_SCALE = 240.0;
private double CheckRange(double value)
{ {
if (value < 0.0) return temp1;
value = 0.0;
else if (value > 1.0)
value = 1.0;
return value;
} }
else
public static Color FromHSL(int h, int s, int l)
{ {
return FromHSL ((double)h / HSL_SCALE, (double)s / HSL_SCALE, (double)l / HSL_SCALE); if (3 * tempX < 2)
{
return temp2 + (temp1 - temp2) * (0.666 - tempX) * 6;
}
else
{
return temp2;
}
}
}
} }
public static Color FromHSL(double h, double s, double l) public static Color FromHSL(double h, double s, double l)
@ -419,5 +469,10 @@ namespace MBS.Framework.Drawing
{ {
return Color.FromHSL(this.Hue < 0.5 ? 0 : 1, this.Saturation, this.Luminosity); return Color.FromHSL(this.Hue < 0.5 ? 0 : 1, this.Saturation, this.Luminosity);
} }
public object Clone()
{
return Color.FromRGBADouble(R, G, B, A);
}
} }
} }