const char * UsageLines [] = {
	"Usage: p4resize (output width) (output height)",
	"Reads P4 PBM image from standard input.",
	"Resizes image to specified width and height.",
	"Pixels are skipped or repeated to fit.  No",
	"recalculating of pixel values is done.",
	"Writes PBM to standard output.",
	"May 16, 2011.  Newest is at gopher -p users/julianbr sdf.org",
	};
const int NumUsageLines = sizeof (UsageLines)/sizeof (UsageLines [0] );

#include <stdlib.h>
#include <stdio.h>


void ResizeData (
		int InputWidth, int InputHeight,
		int OutputWidth, int OutputHeight)
	{
	unsigned char * InputLineBuffer, * InvPtr;
	int across, down;
	int InputWeight, InputValue, OutputWeight, OutputValue;
	int InputAcross, InputDown;

	InputLineBuffer = malloc ((InputWidth + 7)/8);
	if (InputLineBuffer == NULL) {
		fprintf (stderr, "***p4resize: Not enough memory");
		fprintf (stderr, " for input line buffer.\n");
		return;
		}
	InputValue = 0; /* Just to make it != EOF */
	down = InputHeight/2;
	for (InputDown = 0; InputDown < InputHeight; InputDown++) {
		if (InputValue != EOF) {
			if (fread (InputLineBuffer, (InputWidth + 7)/8,
						1, stdin) < 1)
				InputValue = EOF;
			}
		down += OutputHeight;
		while (down >= InputHeight) {
			across = InputWidth/2;
			InvPtr = InputLineBuffer;
			InputWeight = 128;
			OutputWeight = 128;
			OutputValue = 0;
			for (InputAcross = 0; InputAcross < InputWidth;
						InputAcross++) {
				if (InputValue != EOF && InputWeight == 128) {
					InputValue = InvPtr [0];
					InvPtr++;
					}
				across += OutputWidth;
				while (across >= InputWidth) {
					if (InputValue != EOF
					&& InputValue >= InputWeight)
						OutputValue += OutputWeight;
					OutputWeight /= 2;
					if (OutputWeight == 0) {
						putchar (OutputValue);
						OutputValue = 0;
						OutputWeight = 128;
						}
					across -= InputWidth;
					}
				if (InputValue != EOF
						&& InputValue >= InputWeight)
					InputValue -= InputWeight;
				InputWeight /= 2;
				if (InputWeight == 0)
					InputWeight = 128;
				}
			if (OutputWeight < 128)
				putchar (OutputValue);
			down -= InputHeight;
			}
		}
	free (InputLineBuffer);
	if (InputValue == EOF) {
		fprintf (stderr, "***p4resize: Premature end of");
		fprintf (stderr, " input image data.\n");
		}
	else if (getchar () != EOF) {
		fprintf (stderr, "***p4resize: Extra image data");
		fprintf (stderr, " in input PBM.\n");
		}
	}


void ResizeFile (int OutputWidth, int OutputHeight)
	{
	int InputWidth, InputHeight;

	if (getchar () != 'P' || getchar () != '4'
			|| scanf ("%d", & InputWidth) != 1
			|| InputWidth < 1
			|| scanf ("%d", & InputHeight) != 1
			|| InputHeight < 1
			|| getchar () == EOF) {
		fprintf (stderr, "***p4resize: Wrong input type, must");
		fprintf (stderr, " be P4.\n");
		}
	else {
		printf ("P4\n");
		printf ("%d %d\n", OutputWidth, OutputHeight);
		ResizeData (
				InputWidth, InputHeight,
				OutputWidth, OutputHeight);
		}
	}


int main (int argc, char * argv [] )
	{
	int OutputWidth, OutputHeight, ok, i;
	char c;

	if (argc < 2) {
		for (i = 0; i < NumUsageLines; i++)
			printf ("%s\n", UsageLines [i] );
		}
	else if (argc == 3) {
		ok = 1;
		if (sscanf (argv [1], "%d%c", & OutputWidth, & c) != 1) {
			fprintf (stderr, "***p4resize: Expecting");
			fprintf (stderr, " output width, found");
			fprintf (stderr, " \"%s\".\n", argv [1] );
			ok = 0;
			}
		if (sscanf (argv [2], "%d%c", & OutputHeight, & c) != 1) {
			fprintf (stderr, "***p4resize: Expecting");
			fprintf (stderr, " output height, found");
			fprintf (stderr, " \"%s\".\n", argv [2] );
			ok = 0;
			}
		if (ok)
			ResizeFile (OutputWidth, OutputHeight);
		}
	else {
		fprintf (stderr, "Usage: p4resize");
		fprintf (stderr, " (output width) (output height)\n");
		}
	return 0;
	}