const char * UsageLines [] = { "Usage: p6show (background r) (background g) (background b)", "Reads P6 PPM image from standard input.", "Writes text to standard output, one letter for each pixel", "indicating the closest match.", "Exact matches to the specified background color produce spaces", "(except at the edge of the image where - or | is used.)", "(Set background color to -1 -1 -1 to disable this.)", "", "January 23, 2021. Latest is at gopher://sdf.org/1/users/julianbr", "(For the opposite of 'p6show' see 'p6paint'.)", "", "Compiled for the following colors:", "", }; const int NumUsageLines = sizeof (UsageLines) / sizeof (UsageLines [0] ); const struct { char * name; char letter; int r; int g; int b; } Colors [] = { {"rED", 'r', 255, 0, 0 }, {"PiNK", 'i', 255, 192, 203 }, {"oRANGE", 'o', 255, 127, 0 }, {"yELLOW", 'y', 255, 255, 0 }, {"gREEN", 'g', 0, 255, 0 }, {"bLUE", 'b', 0, 0, 255 }, {"pURPLE", 'p', 128, 0, 128 }, {"wHITE", 'w', 255, 255, 255 }, {"GRaY", 'a', 128, 128, 128 }, {"tAN", 't', 210, 180, 140 }, {"BROWn", 'n', 150, 75, 0 }, {"BLACk", 'k', 0, 0, 0 }, }; const int NumColors = sizeof (Colors) / sizeof (Colors [0] ); #include <stdio.h> #include <stdlib.h> void ColorMatch (int BackgroundR, int BackgroundG, int BackgroundB) { unsigned long int distance2, lowest2; int across, down, width, height, depth, r, g, b, k, closest; if (getchar () != 'P' || getchar () != '6' || scanf ("%d", & width) != 1 || scanf ("%d", & height) != 1 || scanf ("%d", & depth) != 1 || getchar () != '\n') { fprintf (stderr, "***p6show: Improper input,"); fprintf (stderr, " must be P6 PPM.\n"); return; } r = getchar (); for (down = 0; down < height; down++) { for (across = 0; across < width; across++) { if (r == EOF) g = EOF; else g = getchar (); if (g == EOF) b = EOF; else b = getchar (); if (r == BackgroundR && g == BackgroundG && b == BackgroundB) { if (across == 0 || across == width - 1) { if (down == 0 || down == height - 1) putchar ('+'); else putchar ('|'); } else { if (down == 0 || down == height - 1) putchar ('-'); else putchar (' '); } } else { lowest2 = 120000; closest = NumColors; for (k = 0; k < NumColors; k++) { distance2 = (r - Colors [k].r)*(r - Colors [k].r) + (g - Colors [k].g)*(g - Colors [k].g) + (b - Colors [k].b)*(b - Colors [k].b); if (distance2 < lowest2) { lowest2 = distance2; closest = k; } } if (closest < NumColors) putchar (Colors [closest].letter); else { if (across == 0 || across == width - 1) { if (down == 0 || down == height - 1) putchar ('+'); else putchar ('|'); } else { if (down == 0 || down == height - 1) putchar ('-'); else putchar (' '); } } } if (b == EOF) r = EOF; else r = getchar (); } putchar ('\n'); } } int main (int argc, char * * argv) { int i, r, g, b, ok; char c; ok = 0; if (argc != 4) { for (i = 0; i < NumUsageLines; i++) printf ("%s\n", UsageLines [i] ); for (i = 0; i < NumColors; i++) printf ("%s ", Colors [i].name); printf ("\n"); } else { ok = 1; if (sscanf (argv [1], "%d%c", & r, & c) != 1) { fprintf (stderr, "***p6show: Improper r \"%s\"", argv [1] ); fprintf (stderr, " - must be integer\n"); ok = 0; } if (sscanf (argv [2], "%d%c", & g, & c) != 1) { fprintf (stderr, "***p6show: Improper g \"%s\"", argv [2] ); fprintf (stderr, " - must be integer\n"); ok = 0; } if (sscanf (argv [3], "%d%c", & b, & c) != 1) { fprintf (stderr, "***p6show: Improper b \"%s\"", argv [3] ); fprintf (stderr, " - must be integer\n"); ok = 0; } } if (ok) ColorMatch (r, g, b); return 0; }