/*
** ppmmerge.c -- merges same-size ppms (P6) and pgms (P5) into a single
**               image.
**
** usage: ppmmerge width file1 [file2 [file3] ...]
**
** For example, to join 6 ppms (1.ppm - 6.ppm) into a single image
** constructed like this:
** 
**    +---+---+---+
**    | 1 | 5 | 3 |
**    +---+---+---+
**    | 4 | 2 | 6 |
**    +---+---+---+
**
** use the command:
**
**    ppmmerge 3 1.ppm 5.ppm 3.ppm 4.ppm 2.ppm 6.ppm
**
** By Brian "Beej" Hall and Brian "Bapper" Pomerantz
**    beej@ecst.csuchico.edu, bapper@ecst.csuchico.edu
**
** This program is in the public domain.  And it's a good thing--no one
** would pay for something like this.
*/

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

#define MAXFILES 200

FILE *file[MAXFILES];
int xdim = -1, ydim;
char type[30];

int main(int argc, char *argv[])
{
	int i, j, k, width;
	int numfiles, height;
	char buf[3000];
	void read_headers(FILE *fp);

	if (argc < 3) {
		fprintf(stderr, "usage: ppmmerge width file [file2 [file3] ...]\n");
		exit(1);
	}

	width = atoi(argv[1]);
	if (width < 1 || width > MAXFILES) {
		fprintf(stderr, "ppmmerge: width must be in the range 1-%d\n", MAXFILES);
		exit(1);
	}

	numfiles = argc - 2;
	height = numfiles / width;

	if (width > numfiles) width = numfiles;

	if (numfiles%width != 0) {
		fprintf(stderr, "ppmmerge: number of files must be a multiple of width\n");
		exit(1);
	}

	for (i = 0; i < numfiles; i++) {
		if ((file[i] = fopen(argv[i+2],"rb")) == NULL) {
			fprintf(stderr, "ppmmerge: error opening \"%s\"\n", argv[i+2]);
			exit(1);
		}
		read_headers(file[i]);
	}

	printf("%s\n#created by ppmmerge\n%d %d\n255\n", type, xdim*width, ydim*height);

	for(i = 0; i < numfiles; i += width) {
		for(k = 0; k < ydim; k++) {
			for(j = i; j < i + width; j++) {
				int readwidth;

				if (type[1] == '5') readwidth = xdim;
				else readwidth = xdim * 3;

				if (fread(buf,1,readwidth,file[j]) != readwidth) {
					fprintf(stderr, "ppmmerge: piss off\n");
					exit(1);
				}
				fwrite(buf,1,readwidth,stdout);
			}
		}
	}

	return 0;
}

void read_headers(FILE *fp)
{
	char *p;
	int x,y;
	char *get_next_row(FILE *fp);

	strcpy(type, get_next_row(fp));
	if (strcmp(type, "P6") && strcmp(type, "P5")) {
		fprintf(stderr, "ppmmerge: only P5 and P6 type PPMs are supported\n");
		exit(1);
	}

	p = get_next_row(fp);
	sscanf(p, "%d %d", &x, &y);

	if (xdim == -1) {
		xdim = x;
		ydim = y;
	} else if (x != xdim || y != ydim) {
		fprintf(stderr, "ppmmerge: images must have identical sizes\n");
		exit(1);
	}

	get_next_row(fp);
}

char *get_next_row(FILE *fp)
{
	static char row[500];

	do {
		fgets(row, 500, fp);
	} while (row[0] == '#');

	row[strlen(row)-1] = '\0';

	return row;
}
