将颜色转换为ConsoleColor?
将System.Drawing.Color
转换为类似的System.ConsoleColor
的最佳方法是什么?
不幸的是,即使Windows控制台可以支持RGB颜色,Console类也只暴露ConsoleColor枚举,这极大地限制了您可以使用的颜色。 如果你想将Color结构映射到“最接近的”ConsoleColor,那将是棘手的。
但是,如果您希望命名的Color与相应的ConsoleColor匹配,您可以创建一个映射,例如:
var map = new Dictionary(); map[Color.Red] = ConsoleColor.Red; map[Color.Blue] = ConsoleColor.Blue; etc...
或者如果性能不那么重要,您可以通过String进行往返。 (仅适用于指定颜色 )
var color = Enum.Parse(typeof(ConsoleColor), color.Name);
编辑:这是一个关于寻找颜色“亲近”的问题的链接。
以下是由.NET 4.5转换的控制台颜色hex值。 首先是该计划:
using System; using System.Drawing; class Program { static void Main(string[] args) { foreach (var n in Enum.GetNames(typeof(ConsoleColor))) Console.WriteLine("{0,-12} #{1:X6}", n, Color.FromName(n).ToArgb() & 0xFFFFFF); } }
这是输出。 如您所见, DarkYellow
的报告存在问题。 那个完整的32位显示为零。 所有其他的alpha通道都有0xFF。
Black #000000 DarkBlue #00008B DarkGreen #006400 DarkCyan #008B8B DarkRed #8B0000 DarkMagenta #8B008B DarkYellow #000000 <-- see comments Gray #808080 DarkGray #A9A9A9 Blue #0000FF Green #008000 Cyan #00FFFF Red #FF0000 Magenta #FF00FF Yellow #FFFF00 White #FFFFFF
编辑:我刚刚带走了一些,所以这里是从RGB
到最近的ConsoleColor
值的转换器。 请注意,对System.Windows.Media
的依赖仅适用于演示工具; 实际的函数本身只引用System.Drawing
。
using System; using System.Windows.Media; class NearestConsoleColor { static ConsoleColor ClosestConsoleColor(byte r, byte g, byte b) { ConsoleColor ret = 0; double rr = r, gg = g, bb = b, delta = double.MaxValue; foreach (ConsoleColor cc in Enum.GetValues(typeof(ConsoleColor))) { var n = Enum.GetName(typeof(ConsoleColor), cc); var c = System.Drawing.Color.FromName(n == "DarkYellow" ? "Orange" : n); // bug fix var t = Math.Pow(cR - rr, 2.0) + Math.Pow(cG - gg, 2.0) + Math.Pow(cB - bb, 2.0); if (t == 0.0) return cc; if (t < delta) { delta = t; ret = cc; } } return ret; } static void Main() { foreach (var pi in typeof(Colors).GetProperties()) { var c = (Color)ColorConverter.ConvertFromString(pi.Name); var cc = ClosestConsoleColor(cR, cG, cB); Console.ForegroundColor = cc; Console.WriteLine("{0,-20} {1} {2}", pi.Name, c, Enum.GetName(typeof(ConsoleColor), cc)); } } }
输出(部分)......
public static System.ConsoleColor FromColor(System.Drawing.Color c) { int index = (cR > 128 | cG > 128 | cB > 128) ? 8 : 0; // Bright bit index |= (cR > 64) ? 4 : 0; // Red bit index |= (cG > 64) ? 2 : 0; // Green bit index |= (cB > 64) ? 1 : 0; // Blue bit return (System.ConsoleColor)index; }
ConsoleColors枚举似乎使用EGA样式调色板排序,即:
index Brgb 0 0000 dark black 1 0001 dark blue 2 0010 dark green 3 0011 dark cyan 4 0100 dark red 5 0101 dark purple 6 0110 dark yellow (brown) 7 0111 dark white (light grey) 8 1000 bright black (dark grey) 9 1001 bright blue 10 1010 bright green 11 1011 bright cyan 12 1100 bright red 13 1101 bright purple 14 1110 bright yellow 15 1111 bright white
您可以将24位颜色(或32位颜色,通过忽略Alpha通道)粗略地映射到基本上具有亮度分量的3位颜色。 在这种情况下,如果System.Drawing.Color中的任何一个红色,绿色或蓝色字节大于128,则设置’brightness’位;如果等效源字节大于64,则设置红色,绿色,蓝色位。
在Vista上,稍后会看到SetConsoleScreenBufferInfoEx API函数。
有关用法的示例,请参阅我对另一个非常相似的StackOverflow问题的回答。 (感谢Hans Passant的原始答案)。
你可以使用reflection。
public static class ColorHelpers { public static bool TryGetConsoleColor(Color color, out ConsoleColor consoleColor) { foreach (PropertyInfo property in typeof (Color).GetProperties()) { Color c = (Color) property.GetValue(null); if (color == c) { int index = Array.IndexOf(Enum.GetNames(typeof (ConsoleColor)), property.Name); if (index != -1) { consoleColor = (ConsoleColor) Enum.GetValues(typeof (ConsoleColor)).GetValue(index); return true; } } } consoleColor = default (ConsoleColor); return false; } }
用法:
private static void Main() { ConsoleColor c; if (ColorHelpers.TryGetConsoleColor(Color.Red, out c)) { Console.ForegroundColor = c; } }
通过使用Color
类的GetHue
, GetBrightness
和GetSaturation
方法,可以实现一种简单有效的方法。
public static ConsoleColor GetConsoleColor(this Color color) { if (color.GetSaturation() < 0.5) { // we have a grayish color switch ((int)(color.GetBrightness()*3.5)) { case 0: return ConsoleColor.Black; case 1: return ConsoleColor.DarkGray; case 2: return ConsoleColor.Gray; default: return ConsoleColor.White; } } int hue = (int)Math.Round(color.GetHue()/60, MidpointRounding.AwayFromZero); if (color.GetBrightness() < 0.4) { // dark color switch (hue) { case 1: return ConsoleColor.DarkYellow; case 2: return ConsoleColor.DarkGreen; case 3: return ConsoleColor.DarkCyan; case 4: return ConsoleColor.DarkBlue; case 5: return ConsoleColor.DarkMagenta; default: return ConsoleColor.DarkRed; } } // bright color switch (hue) { case 1: return ConsoleColor.Yellow; case 2: return ConsoleColor.Green; case 3: return ConsoleColor.Cyan; case 4: return ConsoleColor.Blue; case 5: return ConsoleColor.Magenta; default: return ConsoleColor.Red; } }
请注意,控制台的颜色名称与众所周知的颜色不匹配。 因此,如果你测试颜色映射方案,你必须记住(例如)众所周知的颜色,灰色是深灰色,浅灰色是灰色,绿色是深绿色,石灰是纯绿色,橄榄色是黑色黄色。
容易一个……
公共共享函数ColorToConsoleColor(cColor As Color)作为ConsoleColor Dim cc作为ConsoleColor如果不是System.Enum.TryParse(Of ConsoleColor)(cColor.Name,cc)那么Dim intensity = If(Color.Gray.GetBrightness()
cc = CType(intensity + r + g + b, ConsoleColor) End If Return cc End Function
- 我是否可以在不写入中间临时存储的情况下获取文件的GZipStream?
- 如何在.net中检索硬盘固件序列号?
- 使用IN运算符和存储过程参数
- 如何以编程方式将访问密钥(快捷方式)添加到WPF ContextMenu?
- 为什么Observable.Generate()抛出System.StackOverflowException?
- 为什么不将违反方案委托给价值类型?
- 用于修改machine.config文件的API – ‘DbProviderFactories’部分每个配置文件只能出现一次
- 如何从video文件的“媒体创建”列中提取日期?
- 检测程序是否由Visual Studio运行,而不是从Windows资源管理器运行