[comp.sources.amiga] v02i061: iff2sun - convert IFF picture files to Sun raster files

page@swan.ulowell.edu (Bob Page) (11/18/88)

Submitted-by: raz@raster.uucp (Steve Berry)
Posting-number: Volume 2, Issue 61
Archive-name: iff/iff2sun.1

Iff2sun will take an IFF picture file and convert it to a Sun raster
file. It's great for making custom backgrounds for Sun workstations.

I'm currently at {masscomp,alliant,decvax}raster!raz
But soon: ...alliant!sberry

[compile this on a Sun, it's not meant for your Amiga.  ..Bob]

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:    Shell Archiver
#	Run the following text with /bin/sh to create:
#	iff2sun.c
# This archive created: Thu Nov 17 21:54:29 1988
cat << \SHAR_EOF > iff2sun.c
/*
**      This Program created (under tremendous pressure) by Steve Berry.
**
**      I hope you guys keep it clean. (If you don't, let me know :-)
**
**      Status: PD all the way.
**
**      What's it do? This little guy reads an Amiga IFF ILBM file and 
**      outputs sun rasterfile format. GIGO (Georgous In Garbage Out).
**
**	USEAGE: iff2sun infile outfile
**		if infile is not specified stdin is used.
**		if outfile is not specified then stdout is used.
**
**	Note: this program outputs a COLOR sun file with no color table,
**	which defaults to shades of gray. If you want to display this on
**	a monochrome tube (which is what I have) you should go through the
**	folowing steps:
**		1) iff2sun inputfile outputfile
**		2) rastrepl outputfile output.bigger
**		3) rasfilter8to1 -d output.bigger output.mono
**	The rastrepl just pixel replicates the image so that it large
**	enough to see the detail. you can run this as many times as you
**	like, but remember the image quadruples each time you use it.
**		The rasfilter8to1 program converts the color file (8 bit
**	planes) to mono (1 plane) and does some fancy dithering (-d).
**
**	Limitations:
**		Don't do HAM or ExtraHalfBright. I am planning on adding
**		EHB because it would be relitively simple to do, and 64
**		colors would improve the image quality for the dithering
**		routines.
**		Also, I have only tested this on DPaintII images, it is
**		very possible that it might break with other formats.
**		Unlikely, but possible :*)
**
**	CREDITS:
**			Mark Thompson
**			Steve (Raz) Berry
**
**	Contacts:
**			USENET	...alliant!sberry
**			BIX:	razberry
**
**      10/31/88
*/

#include <stdio.h>
#include <rasterfile.h>

#define HAM 0x800       /* Amiga Viewmodes */
#define HALF 0x80
#define HIRES 0x8000
#define LACE 0x4
#define TRUE 1
#define FALSE 0

/* Stupic C needs to be told about functions used before they
   are defined */

unsigned char RGBtoLuma();
long parse();

/* Some variables and arrays */

unsigned char scanline[500][6][128]; /* vert, planes, width (bytes) */
unsigned char coltable[256];
long width, hieght, planes, viewmode, numcolors;
long temp, compress, i, j, k, l;

main(argc,argv)
int argc;
char **argv;
{
	struct rasterfile header;
	unsigned char clr;
	long formsize;
	static char chunk[5];
	FILE *inh, *outh;
        
	chunk[4] = 0;
        
	inh = stdin;
	outh = stdout;
	switch (argc) {
		case 0:
			exit(0);
		case 1:
			break;
		case 2:
			inh = fopen(argv[1],"r");
			break;
		case 3:
			inh = fopen(argv[1],"r");
			outh = fopen(argv[2],"w");
			break;
		default:
			printf("Useage %s: infile outfile, or stdio\n", 
				argv[0]);
			exit(0);
			break;
	}
        
	if (inh == NULL){
		perror(argv[1]);
		exit(-10);
	}        

	if (outh == NULL){
		perror(argv[2]);
		exit(-10);
	}        

	/* Now comes the fun part... Reading the ILBM's */
        
	if (parse(inh,"FORM")) {
		perror("I don't think that this is an IFF file");
		exit(-10);
	}

	fread(&formsize, 4, 1, inh);    /* length of the FORM */

	if (parse(inh,"ILBM")) {
		perror("I don't think that this is an ILBM");
		exit(-10);
	}

	if (parse(inh,"BMHD")) { 
		perror("Bad format for ILBM.");
		exit(-10);
	}

	cc(chunk);
	fread(chunk, 4, 1, inh);    /* length of the BMHD */

	cc(chunk);
	fread(chunk, 2, 1, inh);    /* width of bitmap */
	width = *((short *)chunk);

	cc(chunk);
	fread(chunk, 2, 1, inh);    /* Height of bitmap */
	hieght = *((short *)chunk);

	fread(chunk, 4, 1, inh);    /* Don't want the orgins */

	cc(chunk);
	fread(chunk, 1, 1, inh);    /* # of Planes */
	planes = *((unsigned char *)chunk);

	fread(chunk, 1, 1, inh);    /* Ignore the Mask */

	cc(chunk);
	fread(chunk, 1, 1, inh);    /* Compression? */

	compress = *((unsigned char *)chunk);

	fread(chunk, 1, 1, inh);    /* just a pad byte */

/***********************************************************************
**	DpaintII does not use the CAMG chunk, so we will have to ignore
**	it for now...
***********************************************************************/

	if (planes == 6) {
		perror("Sorry, I can't do HAM or Halfbright.");
		exit(0);
	} 

	if (parse(inh,"CMAP")) {
		perror("Bad format for ILBM, couldn't find Color Map.");
	exit(-10);
	} 

	cc(chunk);
	fread(chunk, 4, 1, inh);    /* # of color registers */
	numcolors = *((long *)chunk);
        
	numcolors = numcolors/3 ;
	for (i=0;i<numcolors;i++){
		fread(chunk, 3, 1, inh);
		chunk[3] = 0; chunk[4] = 0; 
		chunk[0] = (chunk[0] >> 4) & 0x0f;
		chunk[2] = (chunk[2] >> 4) & 0x0f;
		chunk[1] = (chunk[1] >> 4) & 0x0f;
		coltable[i] = RGBtoLuma(chunk);
	}

	if (numcolors == 2)	/* if a mono image, realign to long word */
		fread(chunk,1,2,inh);

	if (parse(inh,"BODY")){
		perror("No BODY data.");
		exit(0);
	}

	fread(chunk, 4, 1, inh);	/* length of body */

  	header.ras_magic= 0x59a66a95;
  	header.ras_width= width;
  	header.ras_height= hieght;
  	header.ras_depth= 8;
  	header.ras_length= 0;
  	header.ras_type= RT_STANDARD;
  	header.ras_maptype= RMT_NONE;
  	header.ras_maplength= 0;

/* Write out the rasterfile header to the ouput */

	fwrite(&header, sizeof(header), 1, outh);

/* This part does all the work */

/* Either we uncompress the file, or we read it in... */

	if (compress == 1)
		uncompress(planes, width, inh);
	else 
		for(k = 0;k<hieght;k++)
			for(i = 0;i<planes;i++) {
				for(j=0;j<width/8;j++){
					cc(chunk);
					if(feof(inh))
						continue;
					fread(chunk, 1, 1, inh);
					scanline[k][i][j] = *((unsigned char *)chunk);
				}
			}

/* Here we take the data and output it (finally!) */

	for(j = 0;j<hieght;j++){
		for(i = 0;i<width/8;i++)
			process_pixel(i,j,outh);
	}
	fclose(inh);
	fclose(outh);
} /* end of main */

/* The uncompression routine 					*/
/* Here we uncompress the data for the number of planes 	*/
/* and store it in the global array scanline[][][] 		*/
/* Credits: Leo (the great Caped one) was the originator of the */
/* code I ripped this off from. 				*/

uncompress(planes, width, inh)
FILE *inh;
long planes, width;
{
	long i,j,count,bytesperrow;
	char len;
	unsigned char byte;

	for(i=0;i<hieght;i++){
		for(j=0;j<planes;j++){
			count = 0;
			bytesperrow = width / 8;
			while(bytesperrow > 0){
				if ((len = getc(inh)) >= 0){
					bytesperrow -= ++len;
					fread(&scanline[i][j][count],len,1,inh);
					count += len;
				} else if (len == -128)
					;
				else if (len < 0){
					len = -len + 1;
					bytesperrow -= len;
					byte = getc(inh);
					while(--len >= 0)
						scanline[i][j][count++] = byte;
				}
			}
			if(bytesperrow)
				perror("Compression is messed.");
		}
		
	}
}


/* RGBtoLuma converts the colortable from the Amiga to Luminance information */
/* This routine was written by Mark Thompson 				     */

unsigned char RGBtoLuma(color)
unsigned char *color;
{
	unsigned char r, g, b;
	unsigned char grey;
	float fgrey;

	r = color[0];
	g = color[1];
	b = color[2];
	fgrey = (0.3 * r + 0.59 * g + 0.11 * b)*16 + 0.5;
	grey = fgrey;
	return grey;
}

/* Process the byte for the scanline 		*/
/* Can you say shift 3 times fast? 		*/

process_pixel(byte,scan,outh)
FILE *outh;
unsigned char byte;
long scan;
{
	long j, i, p, result = 0;
	unsigned char temp;

	temp = 0; result = 0;
	for(i=7;i>=0;i--){
		for(p=0;p<planes;p++) 
			result = ((((1 << i) & scanline[scan][p][byte])>>i)<<p) | result;
		result = result & 0x1f;
		temp = coltable[result];
		fwrite(&temp, 1, 1, outh);
		result = 0;
	}
}

/* look for a chunk in the file */
long parse(inh, str)
FILE *inh;
char *str;
{
        static char chunk[5];
        chunk[4] = 0;
        while (strncmp(chunk,str,4)!=0){
                fread(chunk, 4, 1, inh);
                if(feof(inh)!=0)
                        return TRUE;
        }
        return FALSE;
}

/* Clear Chunk variable */

cc(chunk)
char chunk[5];
{
	register int i;
	for(i=0;i<5;i++)
		chunk[i] = 0;
}
SHAR_EOF
#	End of shell archive
exit 0
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.