-
Notifications
You must be signed in to change notification settings - Fork 0
/
ColorReductions.cs
124 lines (113 loc) · 4.17 KB
/
ColorReductions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
using System;
using System.Collections.Generic;
namespace Dithery_cli
{
public static class ColorReductions
{
public static void TrueColorBytesToWebSafeColorBytes(in byte[] input, ref byte[] output)
{
for (int i = 0; i < input.Length; i++)
{
output[i] = (byte)(Math.Round(input[i] / 51.0) * 51);
}
}
public static void TrueColorBytesToEGABytes(in byte[] input, ref byte[] output)
{
for (int i = 0; i < input.Length; i++)
{
output[i] = (byte)(Math.Round((byte)input[i] / 85.0) * 85);
}
}
private static readonly List<byte[]> fullCGAColors = new List<byte[]>()
{
new byte[] { 0x00, 0x00, 0x00 }, // black
new byte[] { 0x00, 0x00, 0xAA }, // blue
new byte[] { 0x00, 0xAA, 0x00 }, // green
new byte[] { 0x00, 0xAA, 0xAA }, // cyan
new byte[] { 0xAA, 0x00, 0x00 }, // red
new byte[] { 0xAA, 0x00, 0xAA }, // magenta
new byte[] { 0xAA, 0x55, 0x00 }, // brown
new byte[] { 0xAA, 0xAA, 0xAA }, // light gray
new byte[] { 0x55, 0x55, 0x55 }, // dark gray
new byte[] { 0x55, 0x55, 0xFF }, // light blue
new byte[] { 0x55, 0xFF, 0x55 }, // light green
new byte[] { 0x55, 0xFF, 0xFF }, // light cyan
new byte[] { 0xFF, 0x55, 0x55 }, // light red
new byte[] { 0xFF, 0x55, 0xFF }, // light magenta
new byte[] { 0xFF, 0xFF, 0x55 }, // yellow
new byte[] { 0xFF, 0xFF, 0xFF }, // white
};
public static void TrueColorBytesToCGABytes(in byte[] input, ref byte[] output)
{
output = FindNearestColor(input, fullCGAColors);
}
private static readonly List<byte[]> c64Colors = new List<byte[]>()
{
new byte[] { 0x00, 0x00, 0x00 }, // black
new byte[] { 0xFF, 0xFF, 0xFF }, // white
new byte[] { 0x88, 0x00, 0x00 }, // red
new byte[] { 0xAA, 0xFF, 0xEE }, // cyan
new byte[] { 0xCC, 0x44, 0xCC }, // violet / purple
new byte[] { 0x00, 0xCC, 0x55 }, // green
new byte[] { 0x00, 0x00, 0xAA }, // blue
new byte[] { 0xEE, 0xEE, 0x77 }, // yellow
new byte[] { 0xDD, 0x88, 0x55 }, // orange
new byte[] { 0x66, 0x44, 0x00 }, // brown
new byte[] { 0xFF, 0x77, 0x77 }, // light red
new byte[] { 0x33, 0x33, 0x33 }, // dark grey
new byte[] { 0x77, 0x77, 0x77 }, // grey
new byte[] { 0xAA, 0xFF, 0x66 }, // light green
new byte[] { 0x00, 0x88, 0xFF }, // light blue
new byte[] { 0xBB, 0xBB, 0xBB }, // light grey
};
public static void TrueColorBytesToC64Bytes(in byte[] input, ref byte[] output)
{
output = FindNearestColor(input, c64Colors);
}
private static readonly List<byte[]> pico8Colors = new List<byte[]>()
{
new byte[] { 0, 0, 0 }, // black
new byte[] { 29, 43, 83 }, // dark-blue
new byte[] { 126, 37, 83 }, // dark-purple
new byte[] { 0, 135, 81 }, // dark-green
new byte[] { 171, 82, 54 }, // brown
new byte[] { 95, 87, 79 }, // dark-grey
new byte[] { 194, 195, 199 }, // light-grey
new byte[] { 255, 241, 232 }, // white
new byte[] { 255, 0, 77 }, // red
new byte[] { 255, 163, 0 }, // orange
new byte[] { 255, 236, 39 }, // yellow
new byte[] { 0, 228, 54 }, // green
new byte[] { 41, 173, 255 }, // blue
new byte[] { 131, 118, 156 }, // lavender
new byte[] { 255, 119, 168 }, // pink
new byte[] { 255, 204, 170 }, // light-peach
};
public static void TrueColorBytesToPICO8Bytes(in byte[] input, ref byte[] output)
{
output = FindNearestColor(input, pico8Colors);
}
private static byte[] FindNearestColor(byte[] actualColor, List<byte[]> allowedColors)
{
int index = 0;
uint distance = DistanceBetween24BitColors(actualColor, allowedColors[0]);
for (int i = 1; i < allowedColors.Count; i++)
{
uint possibleNewDistance = DistanceBetween24BitColors(actualColor, allowedColors[i]);
if (possibleNewDistance < distance)
{
distance = possibleNewDistance;
index = i;
}
}
return allowedColors[index];
}
private static uint DistanceBetween24BitColors(byte[] firstColors, byte[] secondColors)
{
int redDifference = firstColors[0] - secondColors[0];
int greenDifference = firstColors[1] - secondColors[1];
int blueDifference = firstColors[2] - secondColors[2];
return (uint)((redDifference * redDifference) + (greenDifference * greenDifference) + (blueDifference * blueDifference));
}
}
}