123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- using System;
- using System.Drawing;
- namespace Microsoft.Windows.Forms
- {
- public static partial class RenderEngine
- {
- /// <summary>
- /// 色调,亮度,饱和度颜色
- /// </summary>
- private struct HLSColor
- {
- private const int ShadowAdj = -333;
- private const int HilightAdj = 500;
- private const int WatermarkAdj = -50;
- private const int Range = 240;
- private const int HLSMax = Range;
- private const int RGBMax = 255;
- private const int Undefined = HLSMax * 2 / 3;
- private int hue;
- private int saturation;
- private int luminosity;
- private bool isSystemColors_Control;
- /// <summary>
- /// 构造函数
- /// </summary>
- /// <param name="color">RGBA颜色</param>
- public HLSColor(Color color)
- {
- isSystemColors_Control = (color.ToKnownColor() == SystemColors.Control.ToKnownColor());
- int r = color.R;
- int g = color.G;
- int b = color.B;
- int max, min; /* max and min RGB values */
- int sum, dif;
- int Rdelta, Gdelta, Bdelta; /* intermediate value: % of spread from max */
- /* calculate lightness */
- max = Math.Max(Math.Max(r, g), b);
- min = Math.Min(Math.Min(r, g), b);
- sum = max + min;
- luminosity = (((sum * HLSMax) + RGBMax) / (2 * RGBMax));
- dif = max - min;
- if (dif == 0)
- { /* r=g=b --> achromatic case */
- saturation = 0; /* saturation */
- hue = Undefined; /* hue */
- }
- else
- { /* chromatic case */
- /* saturation */
- if (luminosity <= (HLSMax / 2))
- saturation = (int)(((dif * (int)HLSMax) + (sum / 2)) / sum);
- else
- saturation = (int)((int)((dif * (int)HLSMax) + (int)((2 * RGBMax - sum) / 2))
- / (2 * RGBMax - sum));
- /* hue */
- Rdelta = (int)((((max - r) * (int)(HLSMax / 6)) + (dif / 2)) / dif);
- Gdelta = (int)((((max - g) * (int)(HLSMax / 6)) + (dif / 2)) / dif);
- Bdelta = (int)((((max - b) * (int)(HLSMax / 6)) + (dif / 2)) / dif);
- if ((int)r == max)
- hue = Bdelta - Gdelta;
- else if ((int)g == max)
- hue = (HLSMax / 3) + Rdelta - Bdelta;
- else /* B == cMax */
- hue = ((2 * HLSMax) / 3) + Gdelta - Rdelta;
- if (hue < 0)
- hue += HLSMax;
- if (hue > HLSMax)
- hue -= HLSMax;
- }
- }
- /// <summary>
- /// 色调
- /// </summary>
- public int Hue
- {
- get
- {
- return hue;
- }
- }
- /// <summary>
- /// 亮度
- /// </summary>
- public int Luminosity
- {
- get
- {
- return luminosity;
- }
- }
- /// <summary>
- /// 饱和度
- /// </summary>
- public int Saturation
- {
- get
- {
- return saturation;
- }
- }
- /// <summary>
- /// 获取减小指定亮度后的颜色
- /// </summary>
- /// <param name="percDarker">要减小的亮度</param>
- /// <returns>新的颜色</returns>
- public Color Darker(float percDarker)
- {
- if (isSystemColors_Control)
- {
- // With the usual color scheme, ControlDark/DarkDark is not exactly
- // what we would otherwise calculate
- if (percDarker == 0.0f)
- {
- return SystemColors.ControlDark;
- }
- else if (percDarker == 1.0f)
- {
- return SystemColors.ControlDarkDark;
- }
- else
- {
- Color dark = SystemColors.ControlDark;
- Color darkDark = SystemColors.ControlDarkDark;
- int dr = dark.R - darkDark.R;
- int dg = dark.G - darkDark.G;
- int db = dark.B - darkDark.B;
- return Color.FromArgb((byte)(dark.R - (byte)(dr * percDarker)),
- (byte)(dark.G - (byte)(dg * percDarker)),
- (byte)(dark.B - (byte)(db * percDarker)));
- }
- }
- else
- {
- int oneLum = 0;
- int zeroLum = NewLuma(ShadowAdj, true);
- return ColorFromHLS(hue, zeroLum - (int)((zeroLum - oneLum) * percDarker), saturation);
- }
- }
- /// <summary>
- /// 是否相等
- /// </summary>
- /// <param name="o">要比较的对象</param>
- /// <returns>相等返回true,否则返回false</returns>
- public override bool Equals(object o)
- {
- if (!(o is HLSColor))
- {
- return false;
- }
- HLSColor c = (HLSColor)o;
- return hue == c.hue &&
- saturation == c.saturation &&
- luminosity == c.luminosity &&
- isSystemColors_Control == c.isSystemColors_Control;
- }
- /// <summary>
- /// 是否相等
- /// </summary>
- /// <param name="a">颜色a</param>
- /// <param name="b">颜色b</param>
- /// <returns>相等返回true,否则返回false</returns>
- public static bool operator ==(HLSColor a, HLSColor b)
- {
- return a.Equals(b);
- }
- /// <summary>
- /// 是否不等
- /// </summary>
- /// <param name="a">颜色a</param>
- /// <param name="b">颜色b</param>
- /// <returns>不等返回true,否则返回false</returns>
- public static bool operator !=(HLSColor a, HLSColor b)
- {
- return !a.Equals(b);
- }
- /// <summary>
- /// 获取哈希码
- /// </summary>
- /// <returns>哈希码</returns>
- public override int GetHashCode()
- {
- return hue << 6 | saturation << 2 | luminosity;
- }
- /// <summary>
- /// 获取增加指定亮度后的颜色
- /// </summary>
- /// <param name="percLighter">要增加的亮度</param>
- /// <returns>新的颜色</returns>
- public Color Lighter(float percLighter)
- {
- if (isSystemColors_Control)
- {
- // With the usual color scheme, ControlLight/LightLight is not exactly
- // what we would otherwise calculate
- if (percLighter == 0.0f)
- {
- return SystemColors.ControlLight;
- }
- else if (percLighter == 1.0f)
- {
- return SystemColors.ControlLightLight;
- }
- else
- {
- Color light = SystemColors.ControlLight;
- Color lightLight = SystemColors.ControlLightLight;
- int dr = light.R - lightLight.R;
- int dg = light.G - lightLight.G;
- int db = light.B - lightLight.B;
- return Color.FromArgb((byte)(light.R - (byte)(dr * percLighter)),
- (byte)(light.G - (byte)(dg * percLighter)),
- (byte)(light.B - (byte)(db * percLighter)));
- }
- }
- else
- {
- int zeroLum = luminosity;
- int oneLum = NewLuma(HilightAdj, true);
- return ColorFromHLS(hue, zeroLum + (int)((oneLum - zeroLum) * percLighter), saturation);
- }
- }
- private int NewLuma(int n, bool scale)
- {
- return NewLuma(luminosity, n, scale);
- }
- private int NewLuma(int luminosity, int n, bool scale)
- {
- if (n == 0)
- return luminosity;
- if (scale)
- {
- if (n > 0)
- {
- return (int)(((int)luminosity * (1000 - n) + (Range + 1L) * n) / 1000);
- }
- else
- {
- return (int)(((int)luminosity * (n + 1000)) / 1000);
- }
- }
- int newLum = luminosity;
- newLum += (int)((long)n * Range / 1000);
- if (newLum < 0)
- newLum = 0;
- if (newLum > HLSMax)
- newLum = HLSMax;
- return newLum;
- }
- private Color ColorFromHLS(int hue, int luminosity, int saturation)
- {
- byte r, g, b; /* RGB component values */
- int magic1, magic2; /* calculated magic numbers (really!) */
- if (saturation == 0)
- { /* achromatic case */
- r = g = b = (byte)((luminosity * RGBMax) / HLSMax);
- if (hue != Undefined)
- {
- /* ERROR */
- }
- }
- else
- { /* chromatic case */
- /* set up magic numbers */
- if (luminosity <= (HLSMax / 2))
- magic2 = (int)((luminosity * ((int)HLSMax + saturation) + (HLSMax / 2)) / HLSMax);
- else
- magic2 = luminosity + saturation - (int)(((luminosity * saturation) + (int)(HLSMax / 2)) / HLSMax);
- magic1 = 2 * luminosity - magic2;
- /* get RGB, change units from HLSMax to RGBMax */
- r = (byte)(((HueToRGB(magic1, magic2, (int)(hue + (int)(HLSMax / 3))) * (int)RGBMax + (HLSMax / 2))) / (int)HLSMax);
- g = (byte)(((HueToRGB(magic1, magic2, hue) * (int)RGBMax + (HLSMax / 2))) / HLSMax);
- b = (byte)(((HueToRGB(magic1, magic2, (int)(hue - (int)(HLSMax / 3))) * (int)RGBMax + (HLSMax / 2))) / (int)HLSMax);
- }
- return Color.FromArgb(r, g, b);
- }
- private int HueToRGB(int n1, int n2, int hue)
- {
- /* range check: note values passed add/subtract thirds of range */
- /* The following is redundant for WORD (unsigned int) */
- if (hue < 0)
- hue += HLSMax;
- if (hue > HLSMax)
- hue -= HLSMax;
- /* return r,g, or b value from this tridrant */
- if (hue < (HLSMax / 6))
- return (n1 + (((n2 - n1) * hue + (HLSMax / 12)) / (HLSMax / 6)));
- if (hue < (HLSMax / 2))
- return (n2);
- if (hue < ((HLSMax * 2) / 3))
- return (n1 + (((n2 - n1) * (((HLSMax * 2) / 3) - hue) + (HLSMax / 12)) / (HLSMax / 6)));
- else
- return (n1);
- }
- }
- }
- }
|