/*
 * Copyright 1990 by Baylor College of Medicine ALL RIGHTS RESERVED. 
 *
 * This program is subject to a license agreement between 
 * Baylor College of Medicine and MIT. Any use inconsistent with
 * said license and any use by persons other than the faculty, 
 * students and staff at MIT or any use on a computer not operated 
 * as part of the Athena Computing Environment (ACE) is expressly 
 * prohibited.
 */
/*
 *		Routines to read an write raster files to and from images.
 *		At present, images must be Z-Pixmap and only rasterfiles of depth
 *		less than that of the screen can be read in.
 */
#include <stdio.h>
#include <fcntl.h>
#include <rasterfile.h>

static int lrbuf ;
static unsigned char rbuf[512] ;
static unsigned char *rpos ;

static int lwbuf ;
static unsigned char wbuf[512] ;

static
get_chr(size,fd)
{
	if (lrbuf == 0)
	{
		lrbuf = (size > sizeof rbuf) ? sizeof rbuf : size ;
		if (read(fd,rbuf,lrbuf) != lrbuf)
		{
			return -1 ;
		}
		rpos = rbuf ;
	}
	lrbuf-- ;
	return *rpos++ ;
}

static
add_chr(c,fd2)
	unsigned char c ;
{
	if (lwbuf == sizeof wbuf)
	{
		must_write(fd2,wbuf,lwbuf) ;
		lwbuf = 0 ;
	}
	wbuf[lwbuf++] = c ;
}

/*
 *	Reads in rasterfile data from file.
 */
static
read_raster_data(fd,length,type,fd2)
{
	/* If run length encoded then decode image data */
	if (type == RT_BYTE_ENCODED)
	{
		lwbuf = 0 ;
		lrbuf = 0 ;
		rpos = rbuf ;
		while(length)
		{
			{
				unsigned char c = get_chr(length,fd) ;
				length-- ;
				if (c != 128)
				{
					add_chr(c,fd2) ;
					continue ;
				}
			}
			{
				unsigned char count = get_chr(length,fd) ;
				length-- ;
				if (!count)
				{
					add_chr(128,fd2) ;
				}
				else
				{
					unsigned char run_char = get_chr(length,fd) ;
					length-- ;
					do
					{
						add_chr(run_char,fd2) ;
					}
					while(count--) ;
				}
			}
		}
		if (lwbuf > 0)
		{
			must_write(fd2,wbuf,lwbuf) ;
		}
	}
	else
	{
		while(length)
		{
			int bc = (length > sizeof rbuf) ? sizeof rbuf : length ;
			if (read(fd,rbuf,bc) != bc)
			{
				return -1 ;
			}
			if (must_write(fd2,rbuf,bc) != bc)
			{
				return -1 ;
			}
			length -= bc ;
		}
	}

	return 0 ;
}

read_rast_img_fd(fd,fd2)
{
	struct rasterfile rasterfile ;

	/* Read in the header */
	/*
	(void)read(fd,(char *)&rasterfile,sizeof rasterfile) ;
	*/
	read_f(fd,"llllllll",
		&rasterfile.ras_magic,
		&rasterfile.ras_width,
		&rasterfile.ras_height,
		&rasterfile.ras_depth,
		&rasterfile.ras_length,
		&rasterfile.ras_type,
		&rasterfile.ras_maptype,
		&rasterfile.ras_maplength) ;

	/* If not rasterfile then forget it */
	if (rasterfile.ras_magic != RAS_MAGIC)
	{
		return -1 ;
	}

	/* If some stupid encoding then forget it */
	if (rasterfile.ras_type != RT_STANDARD &&
		rasterfile.ras_type != RT_BYTE_ENCODED)
	{
		return -2 ;
	}

	if (write_f(fd2,"lll",rasterfile.ras_width,rasterfile.ras_height,rasterfile.ras_depth) < 0)
	{
		return -1 ;
	}

	/* If a color map is present */
	if (rasterfile.ras_maplength > 0)
	{
		static unsigned char red[256] ;
		static unsigned char green[256] ;
		static unsigned char blue[256] ;
		static struct rgb {
			unsigned char r ;
			unsigned char g ;
			unsigned char b ;
		} map[256] ;
		int map_length = rasterfile.ras_maplength ;

		/* We can only interpret equal_rgb at this time */
		if (rasterfile.ras_maptype == RMT_EQUAL_RGB)
		{
			int i ;
			int map_size = map_length / 3 ;

			if (write_f(fd2,"ll",1,map_size) < 0)
			{
				return -1 ;
			}

			/* Read it in */
			read(fd,red,map_size) ;
			read(fd,green,map_size) ;
			read(fd,blue,map_size) ;

			for(i = 0; i < map_size; i++)
			{
				map[i].r = red[i] ;
				map[i].g = green[i] ;
				map[i].b = blue[i] ;
			}
			if (must_write(fd2,map,map_length) != map_length)
			{
				return -1 ;
			}
		}
		else
		{
			if (write_f(fd2,"l",0) < 0)
			{
				return -1 ;
			}
		}
	}

	/* If no colormap data is there */
	else
	{
		if (write_f(fd2,"l",0) < 0)
		{
			return -1 ;
		}
	}

	/* Read in image data */
	if (read_raster_data(fd,rasterfile.ras_length,rasterfile.ras_type,fd2) < 0)
	{
		return -1 ;
	}
	return 0 ;
}
