const char * UsageLines [] = { "Usage: p6fadetrim (background r) (background g) (background b)", "\t(retention factor between 0 and 9)", "\t[(vertical edge across) (horizontal edge down) ]+", "Reads P6 PPM image from standard input and writes to", "standard output same size but trimmed. Everything outside", "the specified edges is replaced with background color.", " Boundaries alternate", "between vertical edges specified by across (left edge = 0)", "and horizontal edges specified by down (top edge = 0).", "The edge path is always closed. p6fadetrim will use the", "first across again if needed to close path.", "If no path is apecified, will operate on whole image.", "Need a minimum of 4 numbers for any effect (4 will be a rectangle).", "", "Retention of 0 will replace what's outside the edge", "with the specified background color. Retention of 10", "will have no effect (output image will be same as input).", "Numbers from 1 through 9 will fade proportionally.", "", "April 21, 2021. Newest is at gopher -p users/julianbr sdf.org", }; const int NumUsageLines = sizeof (UsageLines)/sizeof (UsageLines [0] ); #include void FadeTrim ( int width, int height, int backgroundr, int backgroundg, int backgroundb, int retention, int * Edges, int NumEdges) { int across1, down1, across2, across, down; int r, g, b, i, j, k; int NumCrossings; printf ("P6\n"); printf ("%d %d\n", width, height); printf ("255\n"); r = getchar (); for (down = 0; down < height; down++) { for (across = 0; across < width; across++) { NumCrossings = 0; i = 0; j = 1; k = 2; while (j < NumEdges) { across1 = Edges [i]; down1 = Edges [j]; if (k < NumEdges) across2 = Edges [k]; else across2 = Edges [0]; if (down >= down1) { if (across2 > across && across >= across1) NumCrossings++; else if (across1 > across && across >= across2) NumCrossings--; } i += 2; j += 2; k += 2; } if (r != EOF) g = getchar (); if (g != EOF) b = getchar (); if (NumCrossings == 0) { putchar (((10 - retention)*backgroundr + retention*r + 5)/10); putchar (((10 - retention)*backgroundg + retention*g + 5)/10); putchar (((10 - retention)*backgroundb + retention*b + 5)/10); } else { putchar (r); putchar (g); putchar (b); } if (b != EOF) r = getchar (); } } if (b == EOF) fprintf (stderr, "***p6fadetrim: Not enough image data.\n"); if (r != EOF) fprintf (stderr, "***p6fadetrim: Too much image data.\n"); } #include int main (int argc, char * argv [] ) { int * Edges; int i, width, height, r, g, b, NumEdges, ok, depth, retention; char c; Edges = NULL; if (argc < 2) { for (i = 0; i < NumUsageLines; i++) printf ("%s\n", UsageLines [i] ); } else if (argc < 5) { fprintf (stderr, "***Usage: %s", argv [0] ); fprintf (stderr, " (r) (g) (b)"); fprintf (stderr, " (retention) (edges)\n"); } else { ok = 1; if (sscanf (argv [1], "%d%c", & r, & c) != 1) { fprintf (stderr, "***p6fadetrim: Expecting number"); fprintf (stderr, " for background r, found"); fprintf (stderr, " \"%s\".\n", argv [1] ); ok = 0; } if (sscanf (argv [2], "%d%c", & g, & c) != 1) { fprintf (stderr, "***p6fadetrim: Expecting number"); fprintf (stderr, " for background g, found"); fprintf (stderr, " \"%s\".\n", argv [2] ); ok = 0; } if (sscanf (argv [3], "%d%c", & b, & c) != 1) { fprintf (stderr, "***p6fadetrim: Expecting number"); fprintf (stderr, " for background b, found"); fprintf (stderr, " \"%s\".\n", argv [3] ); ok = 0; } if (sscanf (argv [4], "%d%c", & retention, & c) != 1 || retention < 0 || retention > 10) { fprintf (stderr, "***p6fadetrim: Expecting number"); fprintf (stderr, " between 0 and 9 for"); fprintf (stderr, " retention, found"); fprintf (stderr, " \"%s\".\n", argv [4] ); ok = 0; } if (ok) { NumEdges = argc - 5; Edges = NULL; if (NumEdges > 0) { Edges = malloc (NumEdges*sizeof (Edges [0] ) ); if (Edges == NULL) { fprintf (stderr, "***p6fadetrim: Not"); fprintf (stderr, " enough memory.\n"); ok = 0; } } } if (ok) { for (i = 0; i < NumEdges; i++) { if (sscanf (argv [i + 5], "%d%c", Edges + i, & c) != 1) { fprintf (stderr, "***p6fadetrim:"); fprintf (stderr, " Expecting"); fprintf (stderr, " number for edge,"); fprintf (stderr, " found \""); fprintf (stderr, "%s", argv [i + 4] ); fprintf (stderr, "\".\n"); ok = 0; } } } if (ok) { if (NumEdges > 2 && NumEdges%2 == 1 && Edges [0] != Edges [NumEdges - 1] ) { fprintf (stderr, "***p6fadetrim:"); fprintf (stderr, " First across must be same"); fprintf (stderr, " as last across but found"); fprintf (stderr, " %d and", Edges [0] ); fprintf (stderr, " %d", Edges [NumEdges - 1] ); fprintf (stderr, ".\nCan omit last across.\n"); ok = 0; } } if (ok) { if (getchar () != 'P' || getchar () != '6' || scanf ("%d", & width) != 1 || scanf ("%d", & height) != 1 || scanf ("%d", & depth) != 1 || getchar () != '\n') { fprintf (stderr, "***p6fadetrim: Improper"); fprintf (stderr, " input,"); fprintf (stderr, " must be P6 PPM.\n"); ok = 0; } } if (ok) FadeTrim (width, height, r, g, b, retention, Edges, NumEdges); } if (Edges != NULL) free (Edges); return 0; }