/*
*
*  Raster image display program for the IBM PC  
*
*    This program takes binary images, one byte per pixel, and displays them
*  on the PC's color graphics screen.  The dimensions of the image are
*  specified on the command line, each image is read from the file 
*  with block reads, then displayed in the specified position on the screen.
*  Portions of the image that do not fit on the screen are clipped.
*
*  example use:    rev  256 256 -c -m pal.pal list.dat
*     the file 'list.dat' must contain a list of file names of the images
*     that are to be displayed in sequence.
*
*  The space bar pauses and restarts the display.  Return exits after any
*  image.
*
*  The -m file is a special format.  It contains one number per line, in
*  card image format.  The first 16 numbers are the palette register settings
*  as per IBM spec.  The next 256 numbers are mappings from a scale of
*  0 to 255 to a scale of 0-15.  These mappings are used by the EGA line
*  routine to make 256 colors trim to 16 colors.
*
*  National Center for Supercomputing Applications, University of Illinois
*  153 Water Resources Building
*  605 E. Springfield Ave.
*  Champaign, IL  61820     (217)244-0072
*
*  Tim Krauskopf            July 1986
*
*/
#include "stdio.h"
#include "fcntl.h"

#define USAGE  printf("\nUsage: %s xdim ydim [-c][-p xwhere ywhere][-m mapfile] fileofnames\n",argv[0])

#define RAWSIZE 32000
#define SCRX 640
#define SCRY 350
#define LINEPUT    egaline(xwhere,ywhere+i,store[i],xshow,trans)


FILE *fp;
int		i,j,c,xdim,ydim,file,xshow,xwhere=0,ywhere=0;

unsigned char raw[RAWSIZE],             /* for file buffering */
	rmap[256],gmap[256],bmap[256];		/* color map, if specified */
unsigned char filename[128],
		trans[256];
unsigned char palfile[128] = {0,0}; 	/* starts out = NULL */


char *store[1024],      		/* one per line of image */
	*malloc(),*p;  

main(argc,argv)
	int argc;
	char *argv[];
	{
	if (argc < 4 ) {       		/*  requires at least 2 parameters */
		USAGE;
		exit(1);
	}

	xdim = atoi(argv[1]);       /* required parms of x and y dimensions */
	if (xdim > SCRX)
		xshow = SCRX;           /* screen limits  */
	else
		xshow = xdim;

	ydim = atoi(argv[2]);

	if (xdim < 10 || ydim < 10) {
		puts("\n Huh? ");
		exit(1);
	}

	for (i=3; i<argc; i++) {      /* look at each parm */
		if (*argv[i] == '-') 
			switch ( *(argv[i]+1)) {
				case 'c':                	/*  centering  */
					xwhere = (SCRX-xdim)/2;
					ywhere = (SCRY-ydim)/2;
					if (xwhere < 0) 
						xwhere = 0;			/* if larger than screen, */
					if (ywhere < 0)			/* don't center it */
						ywhere = 0;
					break;
				case 'p':                	/* special position */
					xwhere = atoi(argv[++i]);
					ywhere = atoi(argv[++i]);
					if (xwhere > SCRX || ywhere > SCRY) {
						puts("\n Invalid position ");
						USAGE;
						exit(1);
					}
					break;
				case 'm':   				/* color map definition */
					strcpy(palfile,argv[i+1]);
					break;
				default:
					USAGE;
					exit(1);
			}
	}

/*
*  allocate memory for the image, if not enough, then error
*/
	if (enoughspace(xdim,ydim)) {
		puts("\n Not enough memory for image to be stored");
		exit(1);
	}

/*
*  open file with list of file names to display
*/
	if ( NULL == (fp = fopen(argv[argc-1],"ra" ))) {
		printf("\n%s: Error opening %s",argv[0],argv[3]);
		exit(1);
	}

/*
*  graphics initialization
*/
	initega();

	if (*palfile)    					/* if there is a palette specified */
		loadpal(palfile);
	else {
		for (i=0; i<256; i++)			/* fill with dummy values */
			trans[i] = i>>4;
	}

/*
*  cycle through all of the file names
*/
	*filename = '\0';

	while (NULL != fgets(filename,100,fp)) {     /* while there are files */

		if (*filename < 33)
			break;               /* exit the program if end of list */

		p = filename;

		while (*p > 32)          /*  find the first non printable char or sp*/
			p++;
		*p = '\0';               /*  truncate the file name for use by open */


		if ( 0 > (file = open(filename,O_RDONLY | O_RAW))) {
			printf("\n%s: Error opening image file: %s",argv[0],filename);
			resetega();
			exit(1);
		}

		readpic(file,xdim,ydim);        /* block read from disk */

		close(file);

		for (i=0; i<ydim; i++)          /* display the image */
			LINEPUT;

/*
*  see if we should pause because of keypress
*/
		if (kbhit()) {                 	/* if key(s) is pressed */
			while (kbhit())		
				c = getch();            /* empty backlog */

			if (c == ' ') {
				while (!kbhit()) ;      /* wait for another to restart */
				c = getch();            /* clear buffer */
			}

			if (c != ' ') {             /* RETURN will exit program */
				fclose(fp);
				resetega();
				exit(0);
			}
		}

    }

	fclose(fp);
	resetega();
	exit(0);
}

/*************************************************************************/
/*  readpic
*
*      block read the file and copy to main memory storage
*   Block reading the hard disk (or floppy) saves enough time to pay for
*   the extra memory-to-memory move and then some.
*
*/
readpic(file,len,lines)
	int file,len,lines;
	{
	int i,lno,readsize,readfact;
	char *p;

	readfact = RAWSIZE/len - 5;
	readsize =  readfact*len;      /* get good blocking factor */

	lno = 0;
	do {
		read(file,raw,readsize);        /* read one block */
		p = raw;                        /* point to that block */

/*
*  for this block, copy each line into it's own reserved memory
*/
		for (i=0; i < readfact && lno < lines; i++) {
			movmem(p,store[lno++],len);
			p += len;
		}

	} while (lno < lines);

}
		
/**********************************************************************/
/*  enoughspace
*
*   make enough room for maximum row,col size
*
*   Image memory is allocated line by line because of 64K data limitation
*   of the PC.  
*
*   returns error code of 1 if not enough memory
*/
enoughspace(c,l)
	int l,c;
    {
	int i;

   	for (i=0; i < l; i++) {				/* allocate each line separately */
		store[i] = malloc(c);

		if (store[i] == NULL)   		/* malloc returned not enough */
			return(1);
	}

	return(0);                     		/* successful return */

}


/*********************************************************************/

loadpal(fs)
	char *fs;
	{
	int i,pset;
	FILE *pfp;
	char s[100];

    if (NULL == (pfp = fopen(fs,"ra"))) {		resetega();        puts("Error on palette file open ");
        exit(2);    }
	for (i=0; i<16; i++) {          /*  establish palette  */
		fgets(s,100,pfp);
		pset = atoi(s);
		egapal(i,pset);
    }

	for (i=0; i<256; i++) {            /* read in color map */
		fgets(s,100,pfp);
		trans[i] = atoi(s);
	}

	fclose(pfp);

}
