2010-01-01 10 views
14

Was ist der beste Weg, um eine System.Drawing.Color in eine ähnliche System.ConsoleColor zu konvertieren?Farbe in ConsoleColor konvertieren?

+1

Ich schlage vor, einen Blick auf http://StackOverflow.com/Questions/28211009 zu werfen, anstatt einer der (hier gezeigten) falschen Antworten zu folgen, die hier präsentiert werden.> _> – mafu

Antwort

12

Obwohl die Windows-Konsole RGB-Farben unterstützen kann, stellt die Console-Klasse leider nur die ConsoleColor-Enumeration zur Verfügung, die die möglichen Farben stark einschränkt. Wenn Sie möchten, dass eine Color-Struktur der ConsoleColor "am nächsten" zugeordnet wird, ist das schwierig.

Aber wenn Sie die genannte Farbe wollen einen entsprechenden Console übereinstimmen können Sie eine Karte machen, wie:

var map = new Dictionary<Color, ConsoleColor>(); 
map[Color.Red] = ConsoleColor.Red; 
map[Color.Blue] = ConsoleColor.Blue; 
etc... 

Oder wenn die Leistung ist nicht so wichtig, Sie Reise durch String abrunden können. (Funktioniert nur für benannte Farben)

var color = Enum.Parse(typeof(ConsoleColor), color.Name); 

EDIT: Hier ist ein Link zu einem question about finding color "closeness".

+0

Ist es ohne die Console-Klasse möglich? –

+0

Erscheint nicht so. Die SetConsoleTextAttribute Win32-API definiert nur 4 x 1-Bit-Flags für R, G, B und ein Intensitätsbit. Das würde nur die 16 Farben unterstützen, die von der ConsoleColor-Enumeration unterstützt werden. – Josh

+1

Aber Sie sagten, dass die Windows-Konsole alle RGB-Farben unterstützt ... –

2

Auf Vista und später siehe die API-Funktion SetConsoleScreenBufferInfoEx.

Für ein Anwendungsbeispiel siehe my answer zu einer anderen sehr ähnlichen StackOverflow-Frage. (Danke Hans Passant für die ursprüngliche Antwort).

22

Hier sind die Farbwerte der Konsole Farbe, wie von .NET 4.5 konvertiert. Zuerst das Programm:

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); 
    } 
} 

Und hier ist der Ausgang. Wie Sie sehen können, gibt es ein Problem mit der Berichterstellung für DarkYellow. Die vollen 32 Bits von diesem zeigen sich als Null. Alle anderen haben 0xFF für den Alpha-Kanal.

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 

edit: Ich habe ein wenig gerade jetzt mehr mitreißen, so ist hier ein Konverter von RGB zum nächstgelegenen ConsoleColor Wert. Beachten Sie, dass die Abhängigkeit von System.Windows.Media nur für den Demonstrations-Kabelbaum gilt; Die eigentliche Funktion bezieht sich nur auf 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)); 
     } 
    } 
} 

Der Ausgang (teilweise) ...

test output

+0

Der DarkYellow Hex-Code oben (der Anfang des Posts) ist falsch. Es steht # 000000, aber es sollte # d7c32a sein (wie hier angegeben => http://rgb.to/color/6990/dark-yellow) – SuperJMN

+0

@SuperJMN Bitte beachten Sie meinen Kommentar im Original Post: "Wie Sie sehen können Es gibt ein Problem mit der Berichterstellung für DarkYellow. " –

+0

Oh, OK! Ich habe nicht gelesen, dass es eine Programmausgabe ist. Ich habe diese Hexadezimalwerte für meine Version Ihres Algorithmus verwendet und erkannte das Problem beim Hinzufügen der Werte zu einem Wörterbuch :) Sorry! – SuperJMN

1

Eine einfache und effektive Vorgehensweise kann durch die Verwendung der GetHue, GetBrightness und GetSaturation Methoden der Color Klasse implementiert werden.

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; 
    } 
} 

Beachten Sie, dass die Farbnamen der Konsole nicht mit den bekannten Farben übereinstimmen. Wenn Sie also ein Farbabbildungsschema testen, müssen Sie beispielsweise beachten, dass Grau in den bekannten Farben dunkelgrau, hellgrau grau, grün dunkelgrün, lime rein grün und oliv dunkel ist Gelb.

2

Sie können Reflexion verwenden.

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; 
    } 
} 

Verbrauch:

private static void Main() 
{ 
    ConsoleColor c; 
    if (ColorHelpers.TryGetConsoleColor(Color.Red, out c)) 
    { 
     Console.ForegroundColor = c; 
    } 
} 
17
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; 
} 

Die ConsoleColors Aufzählung der EGA Stilpalette Bestellung zu verwenden scheint, das ist:

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 

Sie können grob Karte eine 24-Bit-Farbe (oder 32-Bit-Farbe, durch Ignorieren des Alpha-Kanals) zu was ist im Wesentlichen 3-Bit-Farbe mit einer Helligkeitskomponente. In diesem Fall wird das Bit "Helligkeit" gesetzt, wenn eines der roten, grünen oder blauen Bytes von System.Drawing.Color größer als 128 ist und die roten, grünen und blauen Bits gesetzt sind, wenn die entsprechenden Quellbytes größer als 64 sind

Verwandte Themen