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