web-dev-qa-db-ja.com

色をConsoleColorに変換しますか?

System.Drawing.Colorを同様のSystem.ConsoleColorに変換する最良の方法は何ですか?

19
Alon Gubkin

残念ながら、WindowsコンソールはRGBカラーをサポートできますが、ConsoleクラスはConsoleColor列挙のみを公開するため、使用できる色が大幅に制限されます。 Color構造を「最も近い」ConsoleColorにマップする場合は、注意が必要です。

ただし、名前付きの色を対応するConsoleColorと一致させたい場合は、次のようなマップを作成できます。

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

または、パフォーマンスがそれほど重要でない場合は、Stringを往復できます。 (名前付きの色でのみ機能します)

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

編集:ここに 色の「近さ」を見つけることについての質問 へのリンクがあります。

14
Josh

.NET4.5で変換されたコンソールカラーの16進値は次のとおりです。最初のプログラム:

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のレポートに問題があります。その1つの完全な32ビットはゼロとして表示されます。他のすべてはアルファチャネル用に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

30
Glenn Slayden
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ビットカラー)を、明るさ成分を含む本質的に3ビットカラーに大まかにマッピングできます。この場合、System.Drawing.Colorの赤、緑、または青のバイトのいずれかが128より大きい場合は「明るさ」ビットが設定され、同等のソースバイトが64より大きい場合は赤、緑、青のビットが設定されます。 。

22
Malwyn

リフレクションを使用できます。

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;
    }
}
2
Raz Megrelidze

Vista以降では、 SetConsoleScreenBufferInfoEx API関数を参照してください。

使用例については、 私の答え 別の非常によく似たStackOverflowの質問を参照してください。 (元の回答をくれたHans Passantに感謝します)。

2
Ash

シンプルで効果的なアプローチは、GetHueクラスのGetBrightnessGetSaturation、および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;
    }
}

コンソールの色名は、よく知られている色と一致しないことに注意してください。したがって、カラーマッピングスキームをテストする場合、(たとえば)よく知られている色では、グレーはダークグレー、ライトグレーはグレー、グリーンはダークグリーン、ライムは純粋なグリーン、オリーブはダークであることに注意する必要があります。黄。

1
Lucero

簡単なもの...

Public Shared Function ColorToConsoleColor(cColor As Color) As ConsoleColor
        Dim cc As ConsoleColor
        If Not System.Enum.TryParse(Of ConsoleColor)(cColor.Name, cc) Then
            Dim intensity = If(Color.Gray.GetBrightness() < cColor.GetBrightness(), 8, 0)
            Dim r = If(cColor.R >= &H80, 4, 0)
            Dim g = If(cColor.G >= &H80, 2, 0)
            Dim b = If(cColor.B >= &H80, 1, 0)

            cc = CType(intensity + r + g + b, ConsoleColor)
        End If
        Return cc
    End Function
1
Jens

バージョン6(およびConsoleWindowClassウィンドウ)より前のPowerShell.exeの明確なデフォルトの「青地に白」の色は、実際にはDarkYellowon$Host.UI.RawUIをチェックすると、DarkMagenta。これは、ConsoleColor列挙値が、構成可能なコンソールカラーテーブルへの単なるインデックスであるためです( DarkYellowに関するこの回答 を参照)。

デフォルトのコンソールカラーテーブルの16進RGB値は次のとおりです。

Value Hex RGB Name
    0 #000000 Black
    1 #000080 DarkBlue
    2 #008000 DarkGreen
    3 #008080 DarkCyan
    4 #800000 DarkRed
    5 #012456 DarkMagenta
    6 #EEEDF0 DarkYellow
    7 #C0C0C0 Gray
    8 #808080 DarkGray
    9 #0000FF Blue
   10 #00FF00 Green
   11 #00FFFF Cyan
   12 #FF0000 Red
   13 #FF00FF Magenta
   14 #FFFF00 Yellow
   15 #FFFFFF White
0
brianary