简体   繁体   中英

C# Convert 4 bit color (=ConsoleColor) to RGB and back

i want do Write a console-like gui for a game, and i start with a real Console. So i have a class, that specifies the colors. Now i want to convert consolecolor to rgb (24 bit) and the other way round. I have tried this:

int d = (((int)col & 8) != 0) ? 255 : 128;
r = (((int)col & 4) != 0) ? d : 0;
g = (((int)col & 2) != 0) ? d : 0;
b = (((int)col & 1) != 0) ? d : 0;

4 Bit colors have this bit-sheme: drgb. When d is 0, the color will be dark, if it's 1, the rgb values will be 255. My problem is: Color 1000 (bright black) and Color 0111 (dark white) are black and gray in my program. they should be darkgray and lightgray. And how to convert the colors back with rounding and not just converting specific colors back?

The light gray color is special case, you just have to handle it separately.

You can set up arrays with the RGB values for the colors and use them for the conversion, they will be handy when you are going to convert the colors back.

Converting 24 bit colors to the palette of 16 colors can be done in many different way. One way is to calculate the difference between the RGB color and the palette colors, and pick the color with the smallest difference:

Example:

byte[] r = { 0, 0, 0, 0, 128, 128, 128, 128, 192, 0, 0, 0, 255, 255, 255, 255 };
byte[] g = { 0, 0, 128, 128, 0, 0, 128, 128, 192, 0, 255, 255, 0, 0, 255, 255 };
byte[] b = { 0, 128, 0, 128, 0, 128, 0, 128, 192, 255, 0, 255, 0, 255, 0, 255 };

Color c = Color.Khaki;
int index = Enumerable.Range(0, 16)
  .OrderBy(i => Math.Abs(c.R - r[i]) + Math.Abs(c.G - g[i]) + Math.Abs(c.B - b[i]))
  .First();

Colors are defined in a 3-dimensional parameter space with the three coordinate axes R, G and B. You can calculate the distance between two colors a and b like this:

double dist = Math.Sqrt(Sqr(a.R - b.R) + Sqr(a.G - b.G) + Sqr(a.B - b.B));

This formula uses this method

private static int Sqr(int x)
{
    return x * x;
}

The best matching color is the one with the smallest distance. You can also use the square of the distance for the comparision of distances (for efficiency):

int sqrDist = Sqr(a.R - b.R) + Sqr(a.G - b.G) + Sqr(a.B - b.B);

Now define an array with the 16 Console colors:

Color[] consoleColors = new[] {
    Colors.Black,
    Colors.Red,
    ...
};

and get the best match with

Color bestMatch;
int bestSqrDist = Int32.MaxValue;
foreach (Color consoleColor in consoleColors) {
    int sqrDist = Sqr(theColor.R - consoleColor.R) +
                  Sqr(theColor.G - consoleColor.G) +
                  Sqr(theColor.B - consoleColor.B);
    if (sqrDist < bestSqrDist) {
        bestMatch = consoleColor;
        bestSqrDist = sqrDist;
    }
}

I'm not sure if I understood you correctly but try this:

    int d = (((int)col & 8) != 0) ? 64 : 0;
    r = (((int)col & 4) != 0) ? d + 191 : d;
    g = (((int)col & 2) != 0) ? d + 191 : d;
    b = (((int)col & 1) != 0) ? d + 191 : d;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM