c# - ¿Convertir color a ConsoleColor?
convertir string en system drawing color (6)
¿Cuál es la mejor manera de convertir un System.Drawing.Color
en un System.ConsoleColor
similar?
Puedes usar la reflexión
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;
}
}
Uso:
private static void Main()
{
ConsoleColor c;
if (ColorHelpers.TryGetConsoleColor(Color.Red, out c))
{
Console.ForegroundColor = c;
}
}
Se puede implementar un enfoque simple y efectivo utilizando los GetHue
, GetBrightness
y GetSaturation
de la clase Color
.
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;
}
}
Tenga en cuenta que los nombres de colores de la consola no coinciden con los colores conocidos. Por lo tanto, si prueba un esquema de asignación de color, debe tener en cuenta que (por ejemplo) en los colores conocidos, Gris es gris oscuro, Gris claro es gris, Verde es verde oscuro, Lima es verde puro y Olivo es oscuro amarillo.
public static System.ConsoleColor FromColor(System.Drawing.Color c) {
int index = (c.R > 128 | c.G > 128 | c.B > 128) ? 8 : 0; // Bright bit
index |= (c.R > 64) ? 4 : 0; // Red bit
index |= (c.G > 64) ? 2 : 0; // Green bit
index |= (c.B > 64) ? 1 : 0; // Blue bit
return (System.ConsoleColor)index;
}
La enumeración ConsoleColors parece utilizar el orden de paleta de estilo EGA, que es:
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
Puede asignar aproximadamente un color de 24 bits (o color de 32 bits, ignorando el canal alfa) a un color esencialmente de 3 bits con un componente de brillo. En este caso, el bit ''brillo'' se establece si cualquiera de los bytes rojo, verde o azul de System.Drawing.Color es mayor que 128, y los bits rojo, verde y azul se establecen si los bytes fuente equivalentes son superiores a 64 .
Estos son los valores hexadecimales del color de la consola, convertidos por .NET 4.5. Primero el programa:
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);
}
}
Y aquí está la salida. Como puede ver, hay un problema con los informes de DarkYellow
. Los 32 bits completos de ese se muestran como cero. Todos los demás tienen 0xFF para el canal alfa.
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
editar: Me he ConsoleColor
llevar un poco más, así que aquí hay un convertidor de RGB
al valor de ConsoleColor
más ConsoleColor
. Tenga en cuenta que la dependencia de System.Windows.Media
es solo para el arnés de demostración; la función real solo hace referencia a 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(c.R - rr, 2.0) + Math.Pow(c.G - gg, 2.0) + Math.Pow(c.B - 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(c.R, c.G, c.B);
Console.ForegroundColor = cc;
Console.WriteLine("{0,-20} {1} {2}", pi.Name, c, Enum.GetName(typeof(ConsoleColor), cc));
}
}
}
La salida (parcial) ...
Desafortunadamente, aunque la consola de Windows puede admitir colores RGB, la clase Console solo expone la enumeración de ConsoleColor, que limita en gran medida los colores posibles que puede usar. Si desea que una estructura de Color se asigne a la ConsoleColor "más cercana", será complicado.
Pero si desea que el Color con nombre coincida con un ConsoleColor correspondiente, puede hacer un mapa como:
var map = new Dictionary<Color, ConsoleColor>();
map[Color.Red] = ConsoleColor.Red;
map[Color.Blue] = ConsoleColor.Blue;
etc...
O si el rendimiento no es tan importante, puede realizar un viaje redondo a través de String. (Solo funciona para colores con nombre )
var color = Enum.Parse(typeof(ConsoleColor), color.Name);
EDITAR: Aquí hay un enlace a una pregunta sobre cómo encontrar "cercanía" al color .
En Vista y más tarde, vea la función de la API SetConsoleScreenBufferInfoEx .
Para un ejemplo de uso, consulte mi respuesta a otra pregunta de muy similar. (Gracias Hans Passant por la respuesta original).