const char * UsageLines [] = {
	"Usage: p6colormatch (r) (g) (b) (radius)",
	"Reads P6 PPM image from standard input.",
	"Outputs bicolor PBM image to standard output.",
	"All input pixels with color components ri gi bi will",
	"produce a '1' output pixel if",
	"(ri - r)**2 + (gi - g)**2 + (bi - b)**2 <= radius**2",
	"and a '0' output pixel otherwise.",
	"Specifying a radius of 0 means only an exact r g b match",
	"produces a '1' output.",
	"May 16, 2011.  Newest is at gopher -p users/julianbr sdf.org",
	};
const int NumUsageLines = sizeof (UsageLines)/sizeof (UsageLines [0] );

#include <stdio.h>


void ColorMatchData (
		int width, int height,
		int MatchingR, int MatchingG, int MatchingB,
		int MatchingRadius)
	{
	unsigned long int MatchingRadius2;
	int InputR, InputG, InputB, OutputWeight, OutputValue;
	int across, down;

	MatchingRadius2 = MatchingRadius*MatchingRadius;
	InputR = getchar ();
	for (down = 0; down < height; down++) {
		OutputWeight = 128;
		OutputValue = 0;
		for (across = 0; across < width; across++) {
			if (InputR == EOF)
				InputG = EOF;
			else
				InputG = getchar ();
			if (InputG == EOF)
				InputB = EOF;
			else
				InputB = getchar ();
			if ((InputR - MatchingR)*(InputR - MatchingR)
				+ (InputG - MatchingG)*(InputG - MatchingG)
				+ (InputB - MatchingB)*(InputB - MatchingB)
					<= MatchingRadius2)
				OutputValue += OutputWeight;
			if (InputB == EOF)
				InputR = EOF;
			else
				InputR = getchar ();
			OutputWeight /= 2;
			if (OutputWeight == 0) {
				putchar (OutputValue);
				OutputWeight = 128;
				OutputValue = 0;
				}
			}
		if (OutputWeight < 128)
			putchar (OutputValue);
		}
	if (InputB == EOF) {
		fprintf (stderr, "***p6colormatch: Premature end");
		fprintf (stderr, " of input image data.\n");
		}
	if (InputR != EOF) {
		fprintf (stderr, "***p6colormatch: Extra input");
		fprintf (stderr, " image data.\n");
		}
	}


void ColorMatchFile (
		int MatchingR, int MatchingG, int MatchingB,
		int MatchingRadius)
	{
	int InputWidth, InputHeight, InputDepth;
	
	if (getchar () != 'P'
			|| getchar () != '6'
			|| scanf ("%d", & InputWidth) != 1
			|| scanf ("%d", & InputHeight) != 1
			|| scanf ("%d", & InputDepth) != 1
			|| getchar () != '\n') { 
		fprintf (stderr, "***p6colormatch: Improper input,");
		fprintf (stderr, " must be P6 PPM.\n");
		}
	else {
		printf ("P4\n");
		printf ("%d %d\n", InputWidth, InputHeight);
		ColorMatchData (
				InputWidth, InputHeight,
				MatchingR, MatchingG, MatchingB,
				MatchingRadius);
		}
	}


int main (int argc, char * argv [] )
	{
	int i, MatchingR, MatchingG, MatchingB, MatchingRadius, ok;
	char c;

	if (argc < 2) {
		for (i = 0; i < NumUsageLines; i++)
			printf ("%s\n", UsageLines [i] );
		}
	else if (argc == 5) {
		ok = 1;
		if (sscanf (argv [1], "%d%c", & MatchingR, & c) != 1) {
			fprintf (stderr, "***p6colormatch: Expecting");
			fprintf (stderr, " r value, found");
			fprintf (stderr, " \"%s\".\n", argv [1] );
			ok = 0;
			}
		if (sscanf (argv [2], "%d%c", & MatchingG, & c) != 1) {
			fprintf (stderr, "***p6colormatch: Expecting");
			fprintf (stderr, " g value, found");
			fprintf (stderr, " \"%s\".\n", argv [2] );
			ok = 0;
			}
		if (sscanf (argv [3], "%d%c", & MatchingB, & c) != 1) {
			fprintf (stderr, "***p6colormatch: Expecting");
			fprintf (stderr, " b value, found");
			fprintf (stderr, " \"%s\".\n", argv [3] );
			ok = 0;
			}
		if (sscanf (argv [4], "%d%c", & MatchingRadius, & c) != 1) {
			fprintf (stderr, "***p6colormatch: Expecting");
			fprintf (stderr, " radius value, found");
			fprintf (stderr, " \"%s\".\n", argv [4] );
			ok = 0;
			}
		if (ok)
			ColorMatchFile (
					MatchingR, MatchingG, MatchingB,
					MatchingRadius);
		}
	else {
		fprintf (stderr, "Usage: p6colormatch");
		fprintf (stderr, " (r) (g) (b) (radius)\n");
		}
	return 0;
	}