[comp.sources.amiga] v89i137: iff2sun - convert iff images to sun bitmaps

page%swap@Sun.COM (Bob Page) (05/17/89)

Submitted-by: raz@kilowatt.sun.com (Steve -Raz- Berry)
Posting-number: Volume 89, Issue 137
Archive-name: iff/iff2sun.1

Added Extra-half-bright support and pixel replicating code.  I'm still
looking for the best way to convert HAM (4096) to 8 bit (256) format.

# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
#	iff2sun.c
#	Makefile
#	DOC
# This is archive 1 of a 1-part kit.
# This archive created: Wed May 17 19:35:50 1989
echo "extracting iff2sun.c"
sed 's/^X//' << \SHAR_EOF > iff2sun.c
X/*
X**      This Program created (under tremendous pressure) by Steve Berry
X**      with help and modifications by Mark Thompson.
X**
X**      I hope you guys keep it clean. (If you don't, let me know :-)
X**
X**      Status: PD all the way.
X**
X**      What's it do? This little guy reads an Amiga IFF ILBM file and 
X**      outputs sun rasterfile format. GIGO (Georgous In Garbage Out).
X**
X**	USEAGE: iff2sun [-c] infile outfile
X**		if infile is not specified stdin is used.
X**		if outfile is not specified then stdout is used.
X**      the -c flag yields a color rasterfile (greyscale is default).
X**      the -h flag switches extra half-bright mode on.
X**
X**	Note: this program outputs an 8 bitplane sun file with color table,
X**	which defaults to shades of gray. Using the -c color flag will
X**      put the IFF color table into the rasterfile. If you want to display
X**      this on a monochrome tube (which is what I have) you should go 
X**      through the folowing steps:
X**
X**		1) iff2sun inputfile outputfile
X**		2) rastrepl outputfile output.bigger
X**		3) rasfilter8to1 -d output.bigger output.mono
X**
X**	The rastrepl just pixel replicates the image so that it large
X**	enough to see the detail. you can run this as many times as you
X**	like, but remember the image quadruples each time you use it.
X**
X**		The rasfilter8to1 program converts the color file (8 bit
X**	planes) to mono (1 plane) and does some fancy dithering (-d).
X**
X**	Limitations:
X**              No HAM mode yet.
X**		Also, I have only tested this on DPaintII images, it is
X**		very possible that it might break with other formats.
X**		Unlikely, but possible :*)
X**
X**	CREDITS:
X**			Mark Thompson
X**			Steve (Raz) Berry
X**
X**	Contacts:
X**				Steve Berry ...sun!kilowatt!raz or 
X**                                             raz%kilowatt.EBay@sun.com
X**                                          BIX: razberry
X**                              Mark Thompson  ...decvax!savax!thompson
X**
X**      Revision History:
X**
X**      10/31/88 First release, does only simple conversion and no color.
X**
X**      12/88    Re-released with color support. Unfortunately few if any
X**               one saw this release (it got lost on the way to the moderator)
X**               (This is Mark's claim to fame)
X**
X**      4/26/89  Added Extra-half-bright support, also looking for the
X**               best way to convert HAM (4096) to 8 bit (256) format.
X*/
X
X#include <stdio.h>
X#include <rasterfile.h>
X
X#define HAM 0x800       /* Amiga Viewmodes */
X#define HALF 0x80
X#define HIRES 0x8000
X#define LACE 0x4
X#define TRUE 1
X#define FALSE 0
X
X/* Stupic C needs to be told about functions used before they
X   are defined */
X
Xunsigned char RGBtoLuma();
Xlong parse();
X
X/* Some variables and arrays */
X
Xunsigned char	rmap[128],rhmap[128];
Xunsigned char	gmap[128],ghmap[128];
Xunsigned char	bmap[128],bhmap[128];
X
Xunsigned char scanline[1024][6][128]; /* vert, planes, width (bytes) */
Xlong width, hieght, planes, viewmode, numcolors;
Xlong temp, compress, i, j, k, l;
Xint colorpic=FALSE, halfb = FALSE;
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X	struct rasterfile header;
X	unsigned char clr;
X	long formsize;
X	static char chunk[5];
X	FILE *inh, *outh;
X	char	*progname= argv[0];
X        
X	chunk[4] = 0;
X        
X	inh = stdin;
X	outh = stdout;
X
X	for (i=1;i<3;i++){
X	  if (argv[1][0] == '-') {
X	    switch (argv[1][1]){
X	      case 'c':
X		colorpic = TRUE;
X		--argc;
X		++argv;
X		fprintf(stderr,"Color output selected\n");
X		break;
X	      case 'h':
X		halfb = TRUE;
X		--argc;
X		++argv;
X		fprintf(stderr,"Extra Half-bright selected\n");
X		break;
X	      }
X	  } else break;
X	}
X
X	switch (argc) {
X		case 0:
X			exit(0);
X		case 1:
X			break;
X		case 2:
X			inh = fopen(argv[1],"r");
X			break;
X		case 3:
X			inh = fopen(argv[1],"r");
X			outh = fopen(argv[2],"w");
X			break;
X		default:
X			fprintf(stderr,"Useage %s: -c|-h infile outfile, or stdio\n", argv[0]);
X			fprintf(stderr," -c is the flag to output color \
X                (greyscale is default)\n and -h indicates Halfbright mode.\n");
X			exit(0);
X			break;
X	}
X        
X	if (inh == NULL){
X		perror(argv[1]);
X		exit(-10);
X	}        
X
X	if (outh == NULL){
X		perror(argv[2]);
X		exit(-10);
X	}        
X
X	/* Now comes the fun part... Reading the ILBM's */
X        
X	if (parse(inh,"FORM")) {
X		perror("I don't think that this is an IFF file");
X		exit(-10);
X	}
X
X	fread(&formsize, 4, 1, inh);    /* length of the FORM */
X
X	if (parse(inh,"ILBM")) {
X		perror("I don't think that this is an ILBM");
X		exit(-10);
X	}
X
X	if (parse(inh,"BMHD")) { 
X		perror("Bad format for ILBM.");
X		exit(-10);
X	}
X
X	cc(chunk);
X	fread(chunk, 4, 1, inh);    /* length of the BMHD */
X
X	cc(chunk);
X	fread(chunk, 2, 1, inh);    /* width of bitmap */
X	width = *((short *)chunk);
X
X	cc(chunk);
X	fread(chunk, 2, 1, inh);    /* Height of bitmap */
X	hieght = *((short *)chunk);
X
X	fread(chunk, 4, 1, inh);    /* Don't want the orgins */
X
X	cc(chunk);
X	fread(chunk, 1, 1, inh);    /* # of Planes */
X	planes = *((unsigned char *)chunk);
X
X	fread(chunk, 1, 1, inh);    /* Ignore the Mask */
X
X	cc(chunk);
X	fread(chunk, 1, 1, inh);    /* Compression? */
X
X	compress = *((unsigned char *)chunk);
X
X	fread(chunk, 1, 1, inh);    /* just a pad byte */
X
X/***********************************************************************
X**	DpaintII does not use the CAMG chunk, so we will have to ignore
X**	it for now...
X***********************************************************************/
X
X/*	if (planes == 6) {
X		perror("Sorry, I can't do HAM or Halfbright.");
X		exit(0);
X	} */
X
X	if (parse(inh,"CMAP")) {
X		perror("Bad format for ILBM, couldn't find Color Map.");
X	exit(-10);
X	} 
X
X	cc(chunk);
X	fread(chunk, 4, 1, inh);    /* # of color registers */
X	numcolors = *((long *)chunk);
X        
X	for(i=0; i<64; i++) {
X	  rmap[i]= i;
X	  gmap[i]= i;
X	  bmap[i]= i;
X	}
X
X	numcolors = numcolors/3 ;
X	for (i=0;i<numcolors;i++){
X		fread(chunk, 3, 1, inh);
X		chunk[3] = 0; chunk[4] = 0; 
X		chunk[0] = (chunk[0] >> 4) & 0x0f;
X		chunk[2] = (chunk[2] >> 4) & 0x0f;
X		chunk[1] = (chunk[1] >> 4) & 0x0f;
X		if(colorpic==TRUE) {
X		  rmap[i] = (chunk[0] << 4) | chunk[0];
X		  gmap[i] = (chunk[1] << 4) | chunk[1];
X		  bmap[i] = (chunk[2] << 4) | chunk[2];
X		} else {
X		  rmap[i] = RGBtoLuma(chunk);
X		  gmap[i] = RGBtoLuma(chunk);
X		  bmap[i] = RGBtoLuma(chunk);
X		}
X		if (halfb == TRUE) {
X		  rhmap[i] = rmap[i]>>1;
X		  ghmap[i] = gmap[i]>>1;
X		  bhmap[i] = bmap[i]>>1;
X		}
X	}
X
X	if (numcolors == 2)	/* if a mono image, realign to long word */
X		fread(chunk,1,2,inh);
X
X	if (parse(inh,"BODY")){
X		perror("No BODY data.");
X		exit(0);
X	}
X
X	if ((planes == 6) && (halfb == TRUE) && (numcolors == 16)
X          || (planes != 6) && (halfb == TRUE)){
X	  perror("You specified Half-Bright, but file is not in the correct format\n");
X	  exit(0);
X	}
X
X	fread(chunk, 4, 1, inh);	/* length of body */
X
X	header.ras_magic= 0x59a66a95;
X#ifndef PIXELREP
X	header.ras_width= width;
X#else
X	header.ras_width= width * 2;
X#endif
X  	header.ras_height= hieght;
X  	header.ras_depth= 8;
X#ifndef PIXELREP
X	header.ras_length= width * hieght;
X#else
X	header.ras_length= width * 2 * hieght;
X#endif
X  	header.ras_type= RT_STANDARD;
X  	header.ras_maptype= RMT_EQUAL_RGB;
X  	header.ras_maplength= 3*256;
X
X/* Write out the rasterfile header to the ouput */
X
X	fwrite(&header, sizeof(header), 1, outh);
X
X/* Write out the red colormap to the ouput */
X
X
X	if (fwrite(rmap, sizeof(rmap), 1, outh) == 0) {
X	  perror(progname);
X	  exit(1);
X	} 
X	if (halfb == TRUE) 
X	  fwrite(rhmap, sizeof(rhmap), 1, outh);
X	else 
X	  fwrite(rmap, sizeof(rmap), 1, outh);
X
X/* Write out the green colormap to the ouput */
X	
X	if (fwrite(gmap, sizeof(gmap), 1, outh) == 0) {
X	  perror(progname);
X	  exit(1);
X	} 
X	if (halfb == TRUE) 
X	  fwrite(ghmap, sizeof(ghmap), 1, outh);
X	else 
X	  fwrite(gmap, sizeof(gmap), 1, outh);
X
X/* Write out the blue colormap to the ouput */
X
X	if (fwrite(bmap, sizeof(bmap), 1, outh) == 0) {
X	  perror(progname);
X	  exit(1);
X	} 
X	if (halfb == TRUE) 
X	  fwrite(bhmap, sizeof(bhmap), 1, outh);
X	else 
X	  fwrite(bmap, sizeof(bmap), 1, outh);
X
X/* This part does all the work */
X
X/* Either we uncompress the file, or we read it in... */
X
X	if (compress == 1)
X		uncompress(planes, width, inh);
X	else 
X		for(k = 0;k<hieght;k++)
X			for(i = 0;i<planes;i++) {
X				for(j=0;j<width/8;j++){
X					cc(chunk);
X					if(feof(inh))
X						continue;
X					fread(chunk, 1, 1, inh);
X					scanline[k][i][j] = *((unsigned char *)chunk);
X				}
X			}
X
X/* Here we take the data and output it (finally!) */
X
X	for(j = 0;j<hieght;j++){
X		for(i = 0;i<width/8;i++)
X			process_pixel(i,j,outh);
X	}
X	fclose(inh);
X	fclose(outh);
X} /* end of main */
X
X/* The uncompression routine 					*/
X/* Here we uncompress the data for the number of planes 	*/
X/* and store it in the global array scanline[][][] 		*/
X/* Credits: Leo (the great Caped one) was the originator of the */
X/* code I ripped this off from. 				*/
X
Xuncompress(planes, width, inh)
XFILE *inh;
Xlong planes, width;
X{
X	long i,j,count,bytesperrow;
X	char len;
X	unsigned char byte;
X
X	for(i=0;i<hieght;i++){
X		for(j=0;j<planes;j++){
X			count = 0;
X			bytesperrow = width / 8;
X			while(bytesperrow > 0){
X				if ((len = getc(inh)) >= 0){
X					bytesperrow -= ++len;
X					fread(&scanline[i][j][count],len,1,inh);
X					count += len;
X				} else if (len == -128)
X					;
X				else if (len < 0){
X					len = -len + 1;
X					bytesperrow -= len;
X					byte = getc(inh);
X					while(--len >= 0)
X						scanline[i][j][count++] = byte;
X				}
X			}
X			if(bytesperrow)
X				perror("Compression is messed.");
X		}
X		
X	}
X}
X
X
X/* RGBtoLuma converts the colortable from the Amiga to Luminance information */
X/* This routine was written by Mark Thompson 				     */
X
Xunsigned char RGBtoLuma(color)
Xunsigned char *color;
X{
X	unsigned char r, g, b;
X	unsigned char grey;
X	float fgrey;
X
X	r = (color[0] << 4) + color[0];
X	g = (color[1] << 4) + color[1];
X	b = (color[2] << 4) + color[2];
X	fgrey = 0.3 * r + 0.59 * g + 0.11 * b + 0.5;
X	grey = fgrey;
X	return grey;
X}
X
X/* Process the byte for the scanline 		*/
X/* Can you say shift 3 times fast? 		*/
X
Xprocess_pixel(byte,scan,outh)
XFILE *outh;
Xunsigned char byte;
Xlong scan;
X{
X	long j, i, p, result = 0;
X	unsigned char temp;
X
X	temp = 0; result = 0;
X	for(i=7;i>=0;i--){
X		for(p=0;p<planes;p++) 
X			result = ((((1 << i) & scanline[scan][p][byte])>>i)<<p) | result;
X		result = result & 0x3f;
X		temp = result;
X		fwrite(&temp, 1, 1, outh);
X#ifdef PIXELREP
X		fwrite(&temp, 1, 1, outh);
X#endif
X		result = 0;
X	}
X}
X
X/* look for a chunk in the file */
Xlong parse(inh, str)
XFILE *inh;
Xchar *str;
X{
X        static char chunk[5];
X        chunk[4] = 0;
X        while (strncmp(chunk,str,4)!=0){
X                fread(chunk, 4, 1, inh);
X                if(feof(inh)!=0)
X                        return TRUE;
X        }
X        return FALSE;
X}
X
X/* Clear Chunk variable */
X
Xcc(chunk)
Xchar chunk[5];
X{
X	register int i;
X	for(i=0;i<5;i++)
X		chunk[i] = 0;
X}
SHAR_EOF
echo "extracting Makefile"
sed 's/^X//' << \SHAR_EOF > Makefile
X#
X#	Makefile for iff2sun
X#
X#	Steve -Raz- Berry
X#	4/25/89
X#
X#CFLAGS = -O
XCFLAGS = -O -DPIXELREP
X#
X# PIXELREP will output 2 pixel color values for each actual pixel found.
X# this helps correct some of the aspect ratio differences between the 
X# Amiga and the Sun. If you don't like it... turn it off.
X
XOBJS = iff2sun.o
X
Xiff2sun:	$(OBJS)
X	cc $(CFLAGS) -o $@ $@.c
X
Xclean:
X	rm $(OBJS)
SHAR_EOF
echo "extracting DOC"
sed 's/^X//' << \SHAR_EOF > DOC
X
X                       Iff2sun revision 3, documentation.
X
X        This Program created (under tremendous pressure) by Steve Berry
X        with help and modifications by Mark Thompson.
X  
X        What's it do? This little guy reads an Amiga IFF ILBM file and 
X        outputs sun rasterfile format. GIGO (Georgous In Garbage Out).
X
X        I hope you guys keep it clean. (If you don't, let me know :-)
X  
X        Status: PD all the way.
X  
X        To properly use this program, you must unshar the distribution
X        and type 'make'. Place the binary in a convient directory.
X
X        MAKE your executable on a Sun! It does you very little good
X        to try to compile this on your Amiga.
X  
X  	USEAGE: iff2sun [-c | -h] infile outfile
X  		if infile is not specified stdin is used.
X  		if outfile is not specified then stdout is used.
X        the -c flag yields a color rasterfile (greyscale is default).
X        the -h flag switches extra half-bright mode on.
X  
X  	Note: this program outputs an 8 bitplane sun file with color table,
X  	which defaults to shades of gray. Using the -c color flag will
X        put the IFF color table into the rasterfile. If you want to display
X        this on a monochrome tube (which is what I have) you should go 
X        through the folowing steps:
X  
X  		1) iff2sun inputfile outputfile
X  		2) rastrepl outputfile output.bigger
X  		3) rasfilter8to1 -d output.bigger output.mono
X  
X  	The rastrepl just pixel replicates the image so that it is large
X  	enough to see the detail. you can run this as many times as you
X  	like, but remember the image quadruples each time you use it.
X  
X  		The rasfilter8to1 program converts the color file (8 bit
X  	planes) to mono (1 plane) and does some fancy dithering (-d).
X  
X                To prepare an image for a color system, just include
X        the -c switch and either display it as it is, or replicate it
X        to the desired size first.
X
X  	Limitations:
X  		Don't do HAM yet. I'm working on it.
X  		Also, I have only tested this on DPaintII images, it is
X  		very possible that it might break with other formats.
X  		Unlikely, but possible :*)
X
X	NOTES:
X		Using Extra-half-bright mode, or any 320x400 format will
X	produce an image that will looked elongated on a Sun screen. There
X	are several ways to fix this. The easiest is to convert your pictures
X	to 640x400 mode and then display them. The second easiest is to rip
X	out 1/3 of the horizontal scan lines in the resultant image. The third
X	is to have ME write iff2sun to pixel replicate horizontally to offset
X	the aspect ratio change. If the third option is the only one acceptable
X	to you, then you are in luck. All you have to do is compile iff2sun 
X	with the -DPIXELREP defined. You will now get pictures that will look 
X	somewhat better in this 320 (lo-res) mode. Remember, the executable will
X	now only pixel-replicate in the horizontal direction, and it will
X	ALWAYS do this. That means that a 640 (hi-res) image will come out 1280x400
X	before you do anything to it. You may want to keep two copies of the
X	program around, one that does 320 (lo-res) images and pixel-replicates,
X	and one that will not pixel-replicate for the hires images. I'll probably
X	just add a switch in the next version rather than force you to recompile.
X  
X  	CREDITS:
X  			Mark Thompson
X  			Steve -Raz- Berry
X  
X  	Contacts:
X  				Steve Berry ...sun!kilowatt!raz or 
X                                               raz%kilowatt.EBay@sun.com
X                                            BIX: razberry
X                                Mark Thompson  ...decvax!savax!thompson
X  
X        Revision History:
X  
X        10/31/88 First release, does only simple conversion and no color.
X  
X        12/88    Re-released with color support. Unfortunately few if any
X                 one saw this release (it got lost on the way to the moderator)
X                 (This modification is Mark's claim to fame)
X  
X        4/26/89  Added Extra-half-bright support, also looking for the
X                 best way to convert HAM (4096) to 8 bit (256) format.
X		 Also stuck in the pixel replicating code (trivial).
X
Xswb 4/27/89
X-------
X
XThis is the revision 2 update information as posted by Mark Thompson.
X
X
XWell I said I would do it, so here it is....the modified and improved
Xversion of iff2sun. The following changes have been made:
X
X1) Can now convert IFF images up to 1024 lines vertical resolution.
X    (horizontal res is still 1024)
X2) Improved greyscale contrast.
X3) Now generates a Sun Rasterfile colormap.
X4) Supports either greyscale or color output.
X
XAs for the problems some people have been having with the notorious
X'compression messed' error, it seems this is due to certain implementations
Xof kermit. Binary mode kermit in vt100 on the Amiga does work. If you
Xdon't have any luck with this method, uuencode seems to perform flawlessly.
X
XMark Thompson
Xdecvax!savax!thompson
SHAR_EOF
echo "End of archive 1 (of 1)"
# if you want to concatenate archives, remove anything after this line
exit