it-swarm.com.ru

Преобразование цвета в ConsoleColor?

Каков наилучший способ преобразования System.Drawing.Color в аналогичный System.ConsoleColor?

17
Alon Gubkin

К сожалению, хотя консоль Windows может поддерживать цвета RGB, класс Console предоставляет только перечисление ConsoleColor, которое значительно ограничивает возможные цвета, которые вы можете использовать. Если вы хотите, чтобы структура Color была сопоставлена ​​с "ближайшим" ConsoleColor, это будет сложно.

Но если вы хотите, чтобы названный Color соответствовал соответствующему 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

Вот шестнадцатеричные значения цвета консоли, преобразованные в .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-битные из этого отображаются как ноль. Все остальные имеют 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

29
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 ,.

21
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 и более поздних версиях смотрите API-функцию SetConsoleScreenBufferInfoEx .

Для примера использования обратитесь к мой ответ к другому очень похожему вопросу StackOverflow. (Спасибо Гансу Пассанту за оригинальный ответ).

2
Ash

Простой и эффективный подход может быть реализован с использованием методов 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;
    }
}

Обратите внимание, что названия цветов консоли не совпадают с хорошо известными цветами. Поэтому, если вы тестируете схему цветового отображения, вы должны иметь в виду, что (например) в хорошо известных цветах: серый - темно-серый, светло-серый - серый, зеленый - темно-зеленый, лайм - чистый зеленый, а оливковый - темный. желтый.

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

Отличительный по умолчанию "белый на синем" цвет PowerShell.exe до версии 6 (и любого окна ConsoleWindowClass) фактически DarkYellow включен DarkMagenta , если вы проверите $Host.UI.RawUI. Это связано с тем, что значения перечисления ConsoleColor - это просто индексы в таблице цветов консоли, которая настраивается (см. этот ответ о DarkYellow ).

Вот шестнадцатеричные значения 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