2010-01-01 9 views
14

Qual è il modo migliore per convertire uno System.Drawing.Color in uno System.ConsoleColor simile?Conversione del colore in ConsoleColor?

+1

Suggerisco di dare un'occhiata a http://stackoverflow.com/questions/28211009 invece di seguire una qualsiasi delle risposte (tutte sbagliate) presentate qui> _> – mafu

risposta

12

Sfortunatamente, anche se la console di Windows può supportare i colori RGB, la classe Console espone solo l'enumerazione ConsoleColor che limita notevolmente i colori possibili che è possibile utilizzare. Se vuoi che una struttura Color venga mappata sul ConsoleColor "più vicino", sarà difficile.

Ma se si desidera che il nome di colore per abbinare un corrispondente ConsoleColor si può fare una mappa come ad esempio:

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

O se le prestazioni non è così importante, si può arrotondare viaggio attraverso String. (Funziona solo per i colori con nome )

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

EDIT: Ecco un link ad un question about finding color "closeness".

+0

È possibile senza la classe Console? –

+0

Non sembra così. L'API Win32 SetConsoleTextAttribute definisce solo 4 flag x 1 bit per R, G, B, oltre a un bit di intensità. Ciò supporterà solo i 16 colori supportati dall'enum ConsoleColor. – Josh

+1

Ma hai detto che la console di Windows supporta qualsiasi colore RGB ... –

2

Su Vista e successivamente vedere la funzione API SetConsoleScreenBufferInfoEx.

Per un esempio di utilizzo, fare riferimento a my answer in un'altra domanda StackOverflow molto simile. (Grazie Hans Passant per la risposta originale).

22

Qui ci sono i valori esadecimali dei colori della console, come convertito dalla .NET 4.5. Prima il programma:

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

Ed ecco l'output. Come puoi vedere, c'è un problema con la segnalazione di DarkYellow. I 32 bit completi di quello vengono visualizzati come zero. Tutti gli altri hanno 0xFF per il canale 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 

edit: ho avuto un po 'di più trasportare in questo momento, quindi ecco un convertitore da RGB al valore più vicino ConsoleColor. Si noti che la dipendenza da System.Windows.Media è solo per il cablaggio dimostrativo; la funzione stessa si riferisce solo 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)); 
     } 
    } 
} 

L'uscita (parziale) ...

test output

+0

Il codice esadecimale DarkYellow sopra (l'inizio del post) è errato. Dice # 000000, ma dovrebbe essere # d7c32a (come indicato qui => http://rgb.to/color/6990/dark-yellow) – SuperJMN

+0

@SuperJMN Si prega di notare il mio commento nel post originale: "Come puoi vedere , c'è un problema con la segnalazione di DarkYellow. " –

+0

Oh, OK! Non ho letto che è un output del programma. Ho usato quei valori esadecimali per la mia versione del tuo algoritmo e ho realizzato il problema quando ho aggiunto i valori a un dizionario :) Scusa! – SuperJMN

1

Un approccio semplice ed efficace può essere attuato utilizzando i GetHue, GetBrightness e GetSaturation metodi della classe 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; 
    } 
} 

Si noti che i nomi dei colori della console non corrispondono ai colori noti. Quindi, se si prova uno schema di mappatura dei colori, devi tenere a mente che (per esempio) nei colori ben noti, Gray è grigio scuro, grigio chiaro è grigio, il verde è verde scuro, calce è verde puro, e Olive è buio giallo.

2

È possibile utilizzare la riflessione.

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

Usage:

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

Il ConsoleColors enumerazione sembra utilizzare la tavolozza ordinamento stile EGA, che è:

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 

È possibile circa mappare un colore a 24 bit (o colore a 32 bit, ignorando il canale alfa) a ciò che è essenzialmente un colore a 3 bit con un componente di luminosità. In questo caso, il bit "luminosità" viene impostato se uno qualsiasi dei byte rosso, verde o blu di System.Drawing.Color è maggiore di 128 e i bit rosso, verde e blu vengono impostati se i byte di origine equivalenti sono superiori a 64

Problemi correlati