using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
///
/// 颜色自动生成帮助类
///
public static class ColorHelper
{
private static readonly Dictionary _colorCache = new Dictionary();//颜色缓存
private static readonly Dictionary _htmlColorCache = new Dictionary();//颜色缓存
///
/// 判断color是否为HtmlColor(HtmlColor格式如#A1B2C3)
///
///
///
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;
}
///
/// 根据key得到一种易识别的颜色,相同的key会得到相同的颜色(若要使多个key得到的颜色具有高对比度,请先调用GenerateColor)
///
///
///
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;
}
///
/// 根据key得到一种易识别的颜色,相同的key会得到相同的颜色(若要使多个key得到的颜色具有高对比度,请先调用GenerateColor)
///
///
///
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;
}
///
/// 提前生成多个易识别且不相近的颜色,生成后通过GetColor或CetHtmlColor获取
///
/// 所有颜色对应的key,个数超过360时效果不佳
///
public static void GenerateColor(IEnumerable 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;
}
}