System.Drawing.Color
を同様のSystem.ConsoleColor
に変換する最良の方法は何ですか?
残念ながら、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);
編集:ここに 色の「近さ」を見つけることについての質問 へのリンクがあります。
.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));
}
}
}
出力(部分的)...
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より大きい場合は赤、緑、青のビットが設定されます。 。
リフレクションを使用できます。
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;
}
}
Vista以降では、 SetConsoleScreenBufferInfoEx API関数を参照してください。
使用例については、 私の答え 別の非常によく似たStackOverflowの質問を参照してください。 (元の回答をくれたHans Passantに感謝します)。
シンプルで効果的なアプローチは、GetHue
クラスのGetBrightness
、GetSaturation
、および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;
}
}
コンソールの色名は、よく知られている色と一致しないことに注意してください。したがって、カラーマッピングスキームをテストする場合、(たとえば)よく知られている色では、グレーはダークグレー、ライトグレーはグレー、グリーンはダークグリーン、ライムは純粋なグリーン、オリーブはダークであることに注意する必要があります。黄。
簡単なもの...
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
バージョン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