Colorful.Console icon indicating copy to clipboard operation
Colorful.Console copied to clipboard

24Bit Color support using VT100

Open Unknown6656 opened this issue 5 years ago • 1 comments

Hi, I just wanted to leave the comment that C# supports 24Bit colors for the Windows console. You can find an example in one of my libraries:

Color Setter Functions

public static class ConsoleExtensions
{
    public static RGBAColor ForegroundColor
    {
        set => Console.Write(value.ToVT100ForegroundString());
    }

    public static RGBAColor BackgroundColor
    {
        set => Console.Write(value.ToVT100BackgroundString());
    }


    // this static constructor is needed on non-unix machines, as the VT100 color codes are not always enabled by default.
    // see https://github.com/Unknown6656/Unknown6656.Core/blob/master/Unknown6656.Core/Controls/Console/ConsoleExtensions.cs
    static ConsoleExtensions()
    {
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            STDINConsoleMode |= ConsoleMode.ENABLE_VIRTUAL_TERMINAL_PROCESSING;
            STDOUTConsoleMode |= ConsoleMode.ENABLE_VIRTUAL_TERMINAL_PROCESSING;
        }
    }
}

https://github.com/Unknown6656/Unknown6656.Core/blob/master/Unknown6656.Core/Controls/Console/ConsoleExtensions.cs#L37..L57

Color Data Structure

public struct RGBAColor
{
    public byte B,G,B,A;


    public RGBAColor(uint argb)
        : this()
    {
        if (argb <= 0xffff)
            argb = ((argb & 0xf000) << 16)
                 | ((argb & 0xff00) << 12)
                 | ((argb & 0x0ff0) << 8)
                 | ((argb & 0x00ff) << 4)
                 | (argb & 0x000f);

        A = (byte)((argb >> 24) & 0xff);
        R = (byte)((argb >> 16) & 0xff);
        G = (byte)((argb >> 8) & 0xff);
        B = (byte)(argb & 0xff);
    }

    
    public string ToVT100ForegroundString() => $"\x1b[38;2;{R};{G};{B}m";

    public string ToVT100BackgroundString() => $"\x1b[48;2;{R};{G};{B}m";


    public static implicit operator RGBAColor(uint argb) => new RGBAColor(argb);

    public static implicit operator RGBAColor(ConsoleColor color) => color_scheme[color];

    private static readonly Dictionary<ConsoleColor, RGBAColor> color_scheme = new()
    {
        [ConsoleColor.Black      ] = 0xff000000,
        [ConsoleColor.DarkBlue   ] = 0xff000080,
        [ConsoleColor.DarkGreen  ] = 0xff008000,
        [ConsoleColor.DarkCyan   ] = 0xff008080,
        [ConsoleColor.DarkRed    ] = 0xff800000,
        [ConsoleColor.DarkMagenta] = 0xff800080,
        [ConsoleColor.DarkYellow ] = 0xff808000,
        [ConsoleColor.Gray       ] = 0xffc0c0c0,
        [ConsoleColor.DarkGray   ] = 0xff808080,
        [ConsoleColor.Blue       ] = 0xff0000ff,
        [ConsoleColor.Green      ] = 0xff00ff00,
        [ConsoleColor.Cyan       ] = 0xff00ffff,
        [ConsoleColor.Red        ] = 0xffff0000,
        [ConsoleColor.Magenta    ] = 0xffff00ff,
        [ConsoleColor.Yellow     ] = 0xffffff00,
        [ConsoleColor.White      ] = 0xffffffff,
    };
}

https://github.com/Unknown6656/Unknown6656.Core/blob/master/Unknown6656.Core/Imaging/RGBAColor.cs

Usage

public void Main()
{
    ConsoleExtensions.ForegroundColor = 0xfe80; // set color using hex literals.
    ConsoleExtensions.BackgroundColor = ConsoleColor.Blue; // traditional method.

    Console.WriteLine("Hello World!");
    Console.WriteLine("\x1b[4mHello World!\x1b[24m"); // this is underlined text using VT100-commands!
}

Maybe this feature could be handy for you...

Unknown6656 avatar Nov 12 '20 11:11 Unknown6656

Ah nevermind, I missed that #24 is already open

Unknown6656 avatar Nov 12 '20 11:11 Unknown6656