2010-01-01 195 views
14

System.Drawing.Color轉換爲類似System.ConsoleColor的最佳方法是什麼?將顏色轉換爲ConsoleColor?

+1

我建議看看http://stackoverflow.com/questions/28211009,而不是遵循這裏提供的任何(所有錯誤)答案> _> – mafu 2015-01-29 09:47:58

回答

12

不幸的是,儘管Windows控制檯可以支持RGB顏色,但Console類只公開了ConsoleColor枚舉,這大大限制了您可以使用的可能顏色。如果你想要一個Color結構映射到「最接近的」ConsoleColor,那將是棘手的。

但是如果你想指定的顏色,以配合相應的ConsoleColor你可以做一個地圖,如:

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

或者,如果表現並不重要,你可以通過字符串往返。 (僅適用於命名顏色

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

編輯:這裏有一個question about finding color "closeness"的鏈接。

+0

是否可能沒有Console類? – 2010-01-01 15:22:33

+0

不會出現。 SetConsoleTextAttribute Win32 API僅爲R,G,B和亮度位定義了4 x 1位標誌。這隻會支持ConsoleColor枚舉所支持的16種顏色。 – Josh 2010-01-01 15:35:36

+1

但是你說Windows控制檯支持任何RGB顏色...... – 2010-01-01 15:42:40

2

在Vista和更高版本上,請參閱SetConsoleScreenBufferInfoEx API函數。

有關使用示例,請參閱my answer與另一個非常類似的StackOverflow問題。 (感謝Hans Passant提供的原始答案)。

22

以下是由.NET 4.5轉換後的控制檯顏色十六進制值。第一個程序:

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

輸出(局部的)...

test output

+0

上面的DarkYellow十六進制代碼(帖子的開頭)是錯誤的。它說#000000,但它應該是#d7c32a(如此處所述=> http://rgb.to/color/6990/dark-yellow) – SuperJMN 2017-01-18 19:00:18

+0

@SuperJMN請注意我在原始文章中的評論:「正如您可以看到,DarkYellow的報告存在問題。「 – 2017-01-19 05:27:39

+0

哦,好的!我沒有讀到它是一個程序輸出。我將這個十六進制值用於我的算法版本,並在向字典中添加值時發現問題:)對不起! – SuperJMN 2017-01-19 09:36:50

1

一種簡單而有效的方法可以通過使用Color類的​​,GetBrightnessGetSaturation方法來實現。

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

請注意,控制檯的顏色名稱與衆所周知的顏色不匹配。所以如果你測試一個顏色映射方案,你必須記住(例如)在衆所周知的顏色中,灰色是深灰色,淺灰色是灰色,綠色是深綠色,石灰是純綠色,而橄欖色是黑暗的黃色。

2

您可以使用反射。

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

的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,則設置'亮度'位,如果等效源字節大於64,則設置紅色,綠色和藍色位