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 <stdio.h>


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 <stdlib.h>


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;
       }