123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- /// <summary>
- /// 颜色自动生成帮助类
- /// </summary>
- public static class ColorHelper
- {
- private static readonly Dictionary<string, Color> _colorCache = new Dictionary<string, Color>();//颜色缓存
- private static readonly Dictionary<string, string> _htmlColorCache = new Dictionary<string, string>();//颜色缓存
- /// <summary>
- /// 判断color是否为HtmlColor(HtmlColor格式如#A1B2C3)
- /// </summary>
- /// <param name="color"></param>
- /// <returns></returns>
- public static bool IsHtmlColor(string color)
- {
- if (!color.StartsWith("#")) return false;
- if (color.Length != 7) return false;
- string r = color.Substring(1, 2);
- string g = color.Substring(3, 2);
- string b = color.Substring(5, 2);
- bool r1 = byte.TryParse(r, System.Globalization.NumberStyles.HexNumber, null, out _);
- bool r2 = byte.TryParse(g, System.Globalization.NumberStyles.HexNumber, null, out _);
- bool r3 = byte.TryParse(b, System.Globalization.NumberStyles.HexNumber, null, out _);
- return r1 & r2 & r3;
- }
- /// <summary>
- /// 根据key得到一种易识别的颜色,相同的key会得到相同的颜色(若要使多个key得到的颜色具有高对比度,请先调用GenerateColor)
- /// </summary>
- /// <param name="key"></param>
- /// <returns></returns>
- public static Color GetColor(string key)
- {
- if (key == null) key = "";
- if (_colorCache.ContainsKey(key))
- return _colorCache[key];
- Random random = new Random(key.GetHashCode());
- var H = random.Next(0, 360);//色调
- var S = random.NextDouble();//饱和度
- var L = random.NextDouble();//亮度
- S = 0.7 + S * 0.2; // [0.7 - 0.9] 排除过灰颜色
- L = 0.4 + L * 0.4; // [0.4 - 0.8] 排除过亮过暗色
- byte r, g, b;
- if (S == 0)
- {
- r = g = b = (byte)(L * 255);
- }
- else
- {
- double v1, v2;
- double hue = H / 360d;
- v2 = (L < 0.5) ? (L * (1 + S)) : ((L + S) - (L * S));
- v1 = 2 * L - v2;
- r = (byte)(255 * HueToRGB(v1, v2, hue + (1.0f / 3)));
- g = (byte)(255 * HueToRGB(v1, v2, hue));
- b = (byte)(255 * HueToRGB(v1, v2, hue - (1.0f / 3)));
- }
- var color = Color.FromArgb(r, g, b);
- var rgbhtml = ColorTranslator.ToHtml(color);
- if (!_colorCache.ContainsKey(key))
- _colorCache.Add(key, color);
- if (!_htmlColorCache.ContainsKey(key))
- _htmlColorCache.Add(key, rgbhtml);
- return color;
- }
- /// <summary>
- /// 根据key得到一种易识别的颜色,相同的key会得到相同的颜色(若要使多个key得到的颜色具有高对比度,请先调用GenerateColor)
- /// </summary>
- /// <param name="key"></param>
- /// <returns></returns>
- public static string GetHtmlColor(string key)
- {
- if (key == null) key = "";
- if (_htmlColorCache.ContainsKey(key))
- return _htmlColorCache[key];
- string rgbhtml = ColorTranslator.ToHtml(GetColor(key));
- return rgbhtml;
- }
- /// <summary>
- /// 提前生成多个易识别且不相近的颜色,生成后通过GetColor或CetHtmlColor获取
- /// </summary>
- /// <param name="keys">所有颜色对应的key,个数超过360时效果不佳</param>
- /// <returns></returns>
- public static void GenerateColor(IEnumerable<string> keys)
- {
- _colorCache.Clear();
- _htmlColorCache.Clear();
- keys = keys.Distinct();
- int idx = 0;
- List<(int H, double S, double L)> list = new List<(int H, double S, double L)>();
- int count = keys.Count();
- int value = 360 / count;
- if (value == 0) value = 1;
- foreach (var key in keys)
- {
- Random random = new Random(key.GetHashCode());
- int H = random.Next(idx * value, (idx + 1) * value);//色调
- H %= 360;
- double S = random.NextDouble();//饱和度
- double L = random.NextDouble();//亮度
- S = 0.7 + S * 0.2; // [0.7 - 0.9] 排除过灰颜色
- L = 0.4 + L * 0.4; // [0.4 - 0.8] 排除过亮过暗色
- byte r, g, b;
- if (S == 0)
- {
- r = g = b = (byte)(L * 255);
- }
- else
- {
- double v1, v2;
- double hue = H / 360d;
- v2 = (L < 0.5) ? (L * (1 + S)) : ((L + S) - (L * S));
- v1 = 2 * L - v2;
- r = (byte)(255 * HueToRGB(v1, v2, hue + (1.0f / 3)));
- g = (byte)(255 * HueToRGB(v1, v2, hue));
- b = (byte)(255 * HueToRGB(v1, v2, hue - (1.0f / 3)));
- }
- list.Add((H, S, L));
- var color = Color.FromArgb(r, g, b);
- var rgbhtml = ColorTranslator.ToHtml(color);
- if (!_colorCache.ContainsKey(key))
- _colorCache.Add(key, color);
- else
- _colorCache[key] = color;
- if (!_htmlColorCache.ContainsKey(key))
- _htmlColorCache.Add(key, rgbhtml);
- else
- _htmlColorCache[key] = rgbhtml;
- idx++;
- }
- }
- private static double HueToRGB(double v1, double v2, double vH)
- {
- if (vH < 0)
- vH += 1;
- if (vH > 1)
- vH -= 1;
- if ((6 * vH) < 1)
- return (v1 + (v2 - v1) * 6 * vH);
- if ((2 * vH) < 1)
- return v2;
- if ((3 * vH) < 2)
- return (v1 + (v2 - v1) * ((2.0f / 3) - vH) * 6);
- return v1;
- }
- }
|