#ifndef lint
static char sccsid[] = "@(#)sgigt.c	1.4 3/21/89";
#endif

#include <stdio.h>
#include <gl.h>
#include <device.h>
#include "tiffio.h"

static	int width, height;
extern	char *getenv();
static	int length;
static	u_long *raster;			/* displayable image */
static	Cursor hourglass = {
    0x1ff0, 0x1ff0, 0x0820, 0x0820,
    0x0820, 0x0c60, 0x06c0, 0x0100,
    0x0100, 0x06c0, 0x0c60, 0x0820,
    0x0820, 0x0820, 0x1ff0, 0x1ff0
};

main(argc, argv)
	char *argv[];
{
	int i, xoff, yoff;
	char *origin, *pausetime, *cp, *rindex(), *getenv();
	short c, val;
	TIFFDirectory *td;
	TIFF *tif;

	tif = TIFFOpen(argv[1], "r");
	if (tif == NULL)
		exit(-1);
	if (argc > 1) {
		i = atoi(argv[2])-1;
		while (i > 0 && TIFFReadDirectory(tif))
			i--;
		if (i > 0) {
			fprintf(stderr, "%s: Not that many directories.\n",
			    argv[2]);
			exit(-1);
		}
	}
	td = tif->tif_dir;
	if (td->td_bitspersample != 1 && td->td_bitspersample != 4 &&
	    td->td_bitspersample != 8 && td->td_bitspersample != 16) {
		fprintf(stderr,
		    "Sorry, can only handle 1, 4, and 8-bit pictures\n");
		exit(-1);
	}
	if (td->td_samplesperpixel != 1 && td->td_samplesperpixel != 3 &&
	    td->td_samplesperpixel != 4) {
		fprintf(stderr,
    "Sorry, can only handle 1-channel gray scale or 3-channel color images\n");
		exit(-1);
	}
	width = td->td_imagewidth;
	if (width > 1100)		/* big windows crash system */
		width = 1100;
	height = td->td_imagelength;
	origin = getenv("DSPYORIGIN");
	if (origin && sscanf(origin, "%d,%d", &xoff, &yoff) == 2)
		prefposition(xoff, xoff + width - 1, yoff, yoff + height - 1);
	else
		prefsize(width, height);
	cp = rindex(argv[1], '/');
	if (cp == NULL)
		cp = argv[1];
	else
		cp++;
	if (winopen(cp) < 0) {
		fprintf(stderr, "Can't create window.\n");
		exit(-1);
	}
	raster = (u_long *)malloc(width * height * sizeof (long));
	if (raster == 0) {
		fprintf(stderr, "No space for raster buffer\n");
		exit(-1);
	}
	pseudorgb();
	curstype(C16X1);
	defcursor(1, hourglass);
	setcursor(1, 0, 0);
	if (gt(tif, width, height, raster)) {
		setcursor(0, 0, 0);
		TIFFClose(tif);
		for (;;) {
			lrectwrite(0, 0, width-1, height-1, raster);
			while (qread(&val) != REDRAW)
				;
		}
	}
	exit(0);
}

#define	howmany(x, y)	(((x)+((y)-1))/(y))

static
gt(tif, w, h, raster)
	TIFF *tif;
	int w, h;
	u_long *raster;
{
	register u_char *pp;
	register u_long *cp;
	register RGBvalue c;
	register int x, range;
	register u_short *wp;
	RGBvalue *Map = NULL;
	int scanline;
	u_char *buf;
	TIFFDirectory *td;

	td = tif->tif_dir;
	scanline = td->td_bitspersample * td->td_imagewidth;
	if (td->td_planarconfig == PLANARCONFIG_CONTIG)
		scanline *= td->td_samplesperpixel;
	buf = (u_char *)malloc(howmany(scanline, 8));
	if (buf == 0) {
		fprintf(stderr, "No space for scanline buffer\n");
		return (0);
	}
	if (td->td_photometric != PHOTOMETRIC_RGB ||
	    td->td_minsamplevalue != 0 || td->td_maxsamplevalue != 255) {
		range = td->td_maxsamplevalue - td->td_minsamplevalue + 1;
		Map = (RGBvalue *)malloc(range * sizeof (RGBvalue));
		if (Map == NULL) {
			fprintf(stderr, "No space for mapping table\n");
			return;
		}
		switch (td->td_photometric) {
		case PHOTOMETRIC_RGB:
		case PHOTOMETRIC_MINISBLACK:
			for (x = 0; x < range; x++)
				Map[x] = (x * 255) / range;
			break;
		case PHOTOMETRIC_MINISWHITE:
			for (x = 0; x < range; x++)
				Map[x] = ((range - x) * 255) / range;
			break;
		}
	}
	while (h-- > 0 && TIFFReadScanline(tif, buf) > 0) {
		pp = buf;
		cp = raster + (h-1)*w;
		switch (td->td_photometric) {
		case PHOTOMETRIC_RGB:
			switch (td->td_bitspersample) {
			case 8:
				if (td->td_samplesperpixel == 4) {
					lrectwrite(0, h-1, w-1, h, buf); 
					continue;
				}
				for (x = w; x-- > 0;) {
					*cp++ = rgbi(pp[0], pp[1], pp[2]);
					pp += 3;
				}
				break;
			case 16:
				wp = (u_short *)pp;
				for (x = w; x-- > 0;) {
					*cp++ = rgbi(Map[wp[0]],
					    Map[wp[1]], Map[wp[2]]);
					wp += td->td_samplesperpixel;
				}
				break;
			}
			break;
		case PHOTOMETRIC_MINISWHITE:
		case PHOTOMETRIC_MINISBLACK:
			switch (td->td_bitspersample) {
			case 1:
				for (x = 0; x < w; x += 8) {
					c = Map[(*pp >> 7) & 1];
					*cp++ = rgbi(c, c, c);
					c = Map[(*pp >> 6) & 1];
					*cp++ = rgbi(c, c, c);
					c = Map[(*pp >> 5) & 1];
					*cp++ = rgbi(c, c, c);
					c = Map[(*pp >> 4) & 1];
					*cp++ = rgbi(c, c, c);
					c = Map[(*pp >> 3) & 1];
					*cp++ = rgbi(c, c, c);
					c = Map[(*pp >> 2) & 1];
					*cp++ = rgbi(c, c, c);
					c = Map[(*pp >> 1) & 1];
					*cp++ = rgbi(c, c, c);
					c = Map[*pp++ & 1];
					*cp++ = rgbi(c, c, c);
				}
				break;
			case 4:
				for (x = 0; x < w; x += 2) {
					c = Map[*pp >> 4];
					*cp++ = rgbi(c, c, c);
					c = Map[*pp++ & 0xf];
					*cp++ = rgbi(c, c, c);
				}
				break;
			case 8:
				for (x = w; x-- > 0;) {
					c = Map[*pp++];
					*cp++ = rgbi(c, c, c);
				}
				break;
			}
			break;
		}
	}
done:
	if (Map)
		free((char *)Map);
	free((char *)buf);
}