Skip to content

Instantly share code, notes, and snippets.

@pineapplemachine
Created April 15, 2017 17:35
Show Gist options
  • Select an option

  • Save pineapplemachine/d8fe2e28becededb27cdf76e02dcf526 to your computer and use it in GitHub Desktop.

Select an option

Save pineapplemachine/d8fe2e28becededb27cdf76e02dcf526 to your computer and use it in GitHub Desktop.
Palette coverage visualization tool
/// This program reads an image from the path "palette.png", finds every unique
/// color in the image, and outputs a visualization to "visualpal.png" which
/// visualizes palette coverage by using white to represent colors very closely
/// representable by colors in the palette and black to represent colors that
/// are relatively distant from any color in the palette.
/// Try it with your favorite palette, for example the NES palette!
/// https://upload.wikimedia.org/wikipedia/en/8/80/NES_palette_color_test_chart.png
/// Written using mach commit e1e9c781fc69fe92fa4c632352c601fdd9a62d18
/// https://github.com/pineapplemachine/mach.d/commit/e1e9c781fc69fe92fa4c632352c601fdd9a62d18
/// See mach's readme for installation and usage instructions.
import mach.sdl;
import mach.math;
import mach.collect;
import mach.io.stdio;
import mach.range;
import mach.meta;
/// Compute a distance between two colors.
auto distance(in Color a, in Color b){
return ((a.r - b.r) ^^ 2 * 0.3 + (a.g - b.g) ^^ 2 * 0.6 + (a.b - b.b) ^^ 2 * 0.1) ^^ 0.5;
}
/// Compute the minimum distance between a color and every color in a set.
auto distance(in Color color, in Set!Color* colors){
return colors.map!(c => c.distance(color)).top;
}
void main(){
SDL.load();
SDL.Support.Default.initialize();
stdio.writeln("Reading palette image.");
auto pal = new Surface("palette.png");
auto colors = new Set!Color();
foreach(x; 0 .. pal.width){
foreach(y; 0 .. pal.height){
colors.add(pal.getpixel(x, y));
}
}
stdio.writeln("Found ", colors.length, " unique colors.");
double maxdistance = 0;
Color maxdistcolor;
stdio.writeln("Finding the most distant color.");
auto visual = new Surface(4096, 384);
foreach(r; 0 .. 64){
foreach(g; 0 .. 64){
foreach(b; 0 .. 64){
auto color = Color(r / 63.0, g / 63.0, b / 63.0);
auto dist = distance(color, colors);
if(dist > maxdistance){
maxdistance = dist;
maxdistcolor = color;
}
}
}
}
stdio.writeln("Most distant color by ", maxdistance, ": ", maxdistcolor.bytes);
stdio.writeln("Generating visualization image.");
foreach(r; 0 .. 64){
foreach(g; 0 .. 64){
foreach(b; 0 .. 64){
auto color = Color(r / 63.0, g / 63.0, b / 63.0);
auto dist = distance(color, colors);
foreach(pix; [
vector(r + g * 64, b + 0),
vector(g + b * 64, r + 128),
vector(b + r * 64, g + 256),
]){
visual.putpixel(pix.x, pix.y, color);
visual.putpixel(pix.x, pix.y + 64, Color(1 - dist / maxdistance));
}
}
}
}
stdio.writeln("Writing visualization to output file.");
visual.save("visualpal.png");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment