const char * UsageLines [] = {
	"Usage: p6fade (background r) (background g) (background b)",
	"\t(fade factor between -10 and 10)",
	"\t[(vertical edge across) (horizontal edge down) ]+",
	"Reads P6 PPM image from standard input and writes to",
	"standard output same size.",
	"",
	"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.  p6fade 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).",
	"",
	"Fade factor of 0 will cause input image to pass to output unchanged.",
	"Fade factor of 10 will replace everything outside boundary",
	"with specified background color.  Fade factor between 1 and 9",
	"will fade area outside boundary proportionally.",
	"Fade factor of -10 will replace everything inside boundary",
	"with specified background color.  Fade factor between -1 and -9",
	"will fade area inside boundary proportionally.",
	"",
	"If no boundary is specified, p6fade will operate on whole",
	"image if fade factor is between 1 and 10.",
	"",
	"April 21, 2021.  Newest is at gopher -p users/julianbr sdf.org",
	};
const int NumUsageLines = sizeof (UsageLines)/sizeof (UsageLines [0] );


#include <stdio.h>


void Fade (
		int width, int height,
		int backgroundr, int backgroundg, int backgroundb,
		int fade,
		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) {
				if (fade > 0) {
					putchar ((fade*backgroundr
						+ (10 - fade)*r + 5)/10);
					putchar ((fade*backgroundg
						+ (10 - fade)*g + 5)/10);
					putchar ((fade*backgroundb
						+ (10 - fade)*b + 5)/10);
					}
				else {
					putchar (r);
					putchar (g);
					putchar (b);
					}
				}
			else {
				if (fade < 0) {
					putchar ((- fade*backgroundr
						+ (10 + fade)*r + 5)/10);
					putchar ((- fade*backgroundg
						+ (10 + fade)*g + 5)/10);
					putchar ((- fade*backgroundb
						+ (10 + fade)*b + 5)/10);
					}
				else {
					putchar (r);
					putchar (g);
					putchar (b);
					}
				}
			if (b != EOF)
				r = getchar ();
			}
		}
	if (b == EOF)
		fprintf (stderr, "***p6fade: Not enough image data.\n");
	if (r != EOF)
		fprintf (stderr, "***p6fade: 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, fade;
	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, " (fade) (edges)\n");
		}
	else {
		ok = 1;
		if (sscanf (argv [1], "%d%c", & r, & c) != 1) {
			fprintf (stderr, "***p6fade: 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, "***p6fade: 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, "***p6fade: Expecting number");
			fprintf (stderr, " for background b, found");
			fprintf (stderr, " \"%s\".\n", argv [3] );
			ok = 0;
			}
		if (sscanf (argv [4], "%d%c", & fade, & c) != 1
				|| fade < -10 || fade > 10) {
			fprintf (stderr, "***p6fade: Expecting number");
			fprintf (stderr, " between -10 and 10 for");
			fprintf (stderr, " fade, 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, "***p6fade: 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, "***p6fade:");
					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, "***p6fade:");
				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, "***p6fade: Improper");
				fprintf (stderr, " input,");
				fprintf (stderr, " must be P6 PPM.\n");
				ok = 0;
				}
			}
		if (ok)
			Fade (width, height, r, g, b, fade,
					Edges, NumEdges);
		}
	if (Edges != NULL)
		free (Edges);
	return 0;
	}