/* wasp - Copyright 1991 by Steven Reiz
 * see COPYING and wasp.c for further info,
 * readras.c, 24/7/91, 8/12/91, 27/12/91
 */

static char *sourcefile=__FILE__;

#include "wasp.h"

static struct {
	long magic;
	long width;
	long height;
	long depth;
	long length;
	long type;
	long maptype;
	long maplength; /* nr of bytes, always directly behind the header */
} header;
#define MAGIC		0x59a66a95
#define RASOLD		0
#define RASSTANDARD	1
#define RASBYTEENCODED	2
#define RASEXPERIMENTAL	0xffff
#define RMTNONE		0
#define RMTRAW		1
#define RMTRGB		2
#define BUFSZ		32768
static char *buf;
static long xsz1;


read_ras(void)
{
	short y;

	cread(&header, (int)sizeof(header));
	if (header.magic!=MAGIC) {
		cseek_in(0L, 0);
		return 0;
	}
	xsz=header.width;
	xsz1=(xsz+15)& -16L;
	ysz=header.height;
	printe("RAS input; %ld x %ld, depth: %ld", xsz, ysz, header.depth);
	if (header.type==RASBYTEENCODED)
		printe(", compressed");
	if (header.maplength==0)
		header.maptype=RMTNONE;
	if (header.maptype!=RMTNONE)
		printe(", with colormap");
	pute('\n');
	if (!outfilename)
		exit(0);
	if (header.depth!=1)
		error0(E0_FATAL, E1_RAS, E2_FORMAT, E3_ONLYDEPTH1);
	rgb=Malloc(ysz*sizeof(u_short *));
	for (y=0; y<ysz; ++y)
		rgb[y]=Calloc(xsz1*sizeof(u_short));
	buf=Malloc(BUFSZ);
	init_counter(0, (int)ysz, 10, "reading RAS");
	if (header.type==RASBYTEENCODED)
		read_compressed();
	else
		read_normal();
	erase_counter(NULL);
	return 1;
}


void
read_normal(void)
{
	short *bufp;
	int bufn;
	int x, y;
	u_short *p;
	int sh, mask;

	cread_type=CREAD_VARLEN;
	cread(buf, BUFSZ);
	bufn=cread_result/2;
	bufp=(short *)buf;
	for (y=0; y<ysz; ++y) {
		counter();
		x=xsz1/16-1;
		p=rgb[y];
		do {
			if (--bufn<0) {
				bufp=(short *)buf;
				cread(buf, BUFSZ);
				bufn=cread_result/2;
				if (bufn<=0)
					goto end_read_normal;
			}
			sh= *bufp++;
			mask=0x8000;
			do {
				*p++ =(sh&mask ? 0 : 0xfff);
				mask>>=1;
			} while (mask);
		} while (--x>=0);
	}
end_read_normal:
	cread_type=CREAD_STRICT;
}


void
read_compressed(void)
{
	u_char *bufp;
	int bufn;
	int x, y;
	u_short *p;
	int sh, mask, count;

	cread_type=CREAD_VARLEN;
	cread(buf, BUFSZ);
	bufn=cread_result;
	bufp=(u_char *)buf;
	y=0;
	counter();
	x=xsz-1;
	p=rgb[y];
	do {
		if (--bufn<0) {
			bufp=(u_char *)buf;
			cread(buf, BUFSZ);
			bufn=cread_result;
			if (bufn<=0)
				goto end_read_compressed;
		}
		sh= *bufp++;
		if (sh==0x80) {
			if (--bufn<0) {
				bufp=(u_char *)buf;
				cread(buf, BUFSZ);
				bufn=cread_result;
				if (bufn<=0)
					goto end_read_compressed;
			}
			if (count= *bufp++) {
				if (--bufn<0) {
					bufp=(u_char *)buf;
					cread(buf, BUFSZ);
					bufn=cread_result;
					if (bufn<=0)
						goto end_read_compressed;
				}
				sh= *bufp++;
			}
		} else
			count=0;
		do {
			mask=0x80;
			do {
				*p++ =(sh&mask ? 0 : 0xfff);
				if (--x<0) {
					++y;
					if (y>=ysz)
						goto end_read_compressed;
					counter();
					x=xsz-1;
					p=rgb[y];
					mask=0; count=0;
				}
				mask>>=1;
			} while (mask);
		} while (--count>=0);
	} while (1);
end_read_compressed:
	cread_type=CREAD_STRICT;
}
