/* wasp - Copyright 1991 by Steven Reiz
 * see COPYING and wasp.c for further info,
 * ppm.c, 24/7/91, 22/10/91 - 25/10/91,
 * 8/12/91, 27/12/91, 21/3/92
 */

static char *sourcefile=__FILE__;

#include "wasp.h"

int
read_ppm(void)
{
	int y;
	long depth;
	char typ[3];

	cread(typ, 3);
	if (typ[0]!='P' || typ[1]<'0' || typ[1]>'9' || typ[2]!='\n') {
		cseek_in(0L, 0);
		return 0;
	}
	typ[2]='\0';
	xsz=getn(' ');
	ysz=getn('\n');
	depth=getn('\n')+1;
	printe("PPM/%s input; %ld x %ld, depth: %ld\n", typ, xsz, ysz, depth);
	if (!outfilename)
		exit(0);
	if (depth!=256) {
		printe("depths other than 256 are not supported\n");
		exit(1);
	}
	rgb=Malloc(ysz*sizeof(u_short *));
	for (y=0; y<ysz; ++y)
	        rgb[y]=Calloc(xsz*sizeof(u_short));
	switch (typ[1]) {
	case '5':
		read_grey8();
	break;
	case '6':
		read_rgb24();
	break;
	default:
		printe("types other than P5 or P6 are not supported\n");
		exit(1);
	break;
	}
	return 1;
}


void
write_ppm(void)
{
	printe("PPM/P6 output; %ld x %ld, depth: 256\n", xsz, ysz);
	cwrite("P6\n", 3);
	putn((int)xsz);
	cwrite(" ", 1);
	putn((int)ysz);
	cwrite("\n255\n", 5);
	write_rgb24();
	erase_counter("PPM file written, %ld bytes", cseek_out(0L, 1));
}


int
getn(char terminator)
{
	int n;
	char c;

	n=0;
	while (1) {
		cread(&c, 1);
		if (c<'0' || c>'9')
			break;
		n=10*n+c-'0';
	}
	assert(c==terminator);
	return n;
}


void
putn(int n)
{
	int i;
	char line[20];

	i=19;
	do {
		line[i--]=n%10+'0';
		n/=10;
	} while (n>0);
	cwrite(line+i+1, 19-i);
}


int
read_hl(void)
{
	int y;
	char typ[3];
	short n;
	long lon;

	cread(typ, 3);
	if (typ[0]!='H' || typ[1]!='L' || typ[2]!='2') {
		cseek_in(0L, 0);
		return 0;
	}
	cread(&n, 2);
	xsz=n;
	cread(&n, 2);
	ysz=n;
	cread(&lon, 4);
	printe("HL2 input; %ld x %ld\n", xsz, ysz);
	if (!outfilename)
		exit(0);
	rgb=Malloc(ysz*sizeof(u_short *));
	for (y=0; y<ysz; ++y)
	        rgb[y]=Calloc(xsz*sizeof(u_short));
	read_rgb24();
	return 1;
}


int
read_mtv(void)
{
	int y, i;
#define TESTBUFSZ 20
	char testbuf[TESTBUFSZ];

	cread_type=CREAD_OPTIONAL;
	cread(testbuf, TESTBUFSZ);
	if (testbuf[0]<'0' || testbuf[0]>'9') {
		cseek_in(0L, 0);
		return 0;
	}
	for (i=1; i<cread_result; ++i) {
		if (testbuf[i]=='\n')
			break;
		if (testbuf[i]!=' ' && (testbuf[i]<'0' || testbuf[i]>'9')) {
			cseek_in(0L, 0);
			return 0;
		}
	}
	cseek_in(0L, 0);
	xsz=getn(' ');
	ysz=getn('\n');
	printe("MTV input; %ld x %ld\n", xsz, ysz);
	if (!outfilename)
		exit(0);
	rgb=Malloc(ysz*sizeof(u_short *));
	for (y=0; y<ysz; ++y)
	        rgb[y]=Calloc(xsz*sizeof(u_short));
	read_rgb24();
	return 1;
}


void
read_rgb24(void)
{
	char *buf;
	int width, color;
	int y, x;
	char *bufp;
	u_short *p;

	cread_type=CREAD_NONFATAL;
	width=xsz*3;
	buf=Malloc(width);
	init_counter(0, (int)ysz, 10, "reading 24-bits RGB");
	for (y=0; y<ysz; ++y) {
		counter();
		cread(buf, width);
		if (cread_result!=width)
			break;
		x=xsz-1;
		bufp=buf;
		p=rgb[y];
		do {
			color=(*bufp++ & 0xf0)<<4;
			color|= *bufp++ & 0xf0;
			color|=(*bufp++ >>4) & 0x0f;
			*p++ =color;
		} while (--x>=0);
	}
	erase_counter(NULL);
	free(buf);
	cread_type=CREAD_STRICT;
}


void
read_grey8(void)
{
	char *buf;
	int color;
	int y, x;
	char *bufp;
	u_short *p;

	cread_type=CREAD_NONFATAL;
	buf=Malloc((int)xsz);
	init_counter(0, (int)ysz, 10, "reading 8-bits grey");
	for (y=0; y<ysz; ++y) {
		counter();
		cread(buf, (int)xsz);
		if (cread_result!=xsz)
			break;
		x=xsz-1;
		bufp=buf;
		p=rgb[y];
		do {
			color= *bufp++ & 0xf0;
			color|=(color<<4)|(color>>4);
			*p++ =color;
		} while (--x>=0);
	}
	erase_counter(NULL);
	free(buf);
	cread_type=CREAD_STRICT;
}


void
write_rgb24(void)
{
	char *buf;
	int width, color;
	int y, x;
	char *bufp;
	u_short *p;
	
	width=xsz*3;
	buf=Malloc(width);
	init_counter(0, (int)ysz, 10, "writing 24-bits RGB");
	for (y=0; y<ysz; ++y) {
		counter();
		x=xsz-1;
		bufp=buf;
		p=rgb[y];
		do {
			color= *p++;
			*bufp++ =(color>>4)&0xf0;
			*bufp++ =color&0xf0;
			*bufp++ =color<<4;
		} while (--x>=0);
		cwrite(buf, width);
	}
	free(buf);
}
