Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!ncar!ames!decwrl!sgi!paul@manray.sgi.com From: paul@manray.sgi.com (Paul Haeberli) Newsgroups: comp.sys.sgi Subject: Program to convert GIF image files to IRIS image file format Message-ID: <42453@sgi.sgi.com> Date: 3 Oct 89 08:01:33 GMT Sender: paul@manray.sgi.com Organization: Silicon Graphics, Inc., Mountain View, CA Lines: 397 /* * fromgif - * convert a GIF file into an IRIS image file. * * I hereby place this program * in the public domain, i.e. there are no * copying restrictions of any kind. * * based on a GIF file reader by Marcel J.E. Mol March 23 1989 * * Paul Haeberli @ Silicon Graphics - 1989 * * To compile use: * * cc -I/usr/include/gl fromgif.c -o fromgif -limage * */ #include "image.h" short rbuf[4096]; short gbuf[4096]; short bbuf[4096]; #define COLSIZE 256 unsigned char *stackp; unsigned int prefix[4096]; unsigned char suffix[4096]; unsigned char stack[4096]; int datasize,codesize,codemask; /* Decoder working variables */ int clear,eoi; /* Special code values */ int avail, oldcode; FILE *infile; int global; /* Is there a global color map? */ int globalbits; /* Number of bits of global colors */ unsigned char globalmap[COLSIZE][3];/* RGB values for global color map */ char bgcolor; /* background color */ unsigned char *raster; /* Decoded image data */ unsigned int width, height; unsigned char red[COLSIZE]; unsigned char green[COLSIZE]; unsigned char blue[COLSIZE]; char *filename, *imagename; main(argc,argv) int argc; char *argv[]; { extern int optind; extern char *optarg; int flag; if(argc<2) { fprintf(stderr,"usage: fromgif image.gif image.rgb\n"); exit(1); } filename = argv[1]; imagename = argv[2]; if ((infile = fopen(filename,"r")) == NULL) { perror(filename); exit(1); } convert(); fclose(infile); exit(0); } convert() { char ch; if (checksignature()) return; readscreen(); while ((ch = getc(infile)) != ';' && ch != EOF) { switch (ch) { case '\0': break; /* this kludge for non-standard files */ case ',': if (readgifimage()) return; break; case '!': readextension(); break; default: fprintf(stderr, "illegal GIF block type\n"); return; break; } } } checksignature() { char buf[6]; fread(buf,1,6,infile); if (strncmp(buf,"GIF",3)) { fprintf(stderr, "file is not a GIF file\n"); return 1; } if (strncmp(&buf[3],"87a",3)) { fprintf(stderr, "unknown GIF version number\n"); return 1; } return 0; } /* * readscreen - * Get information which is global to all the images stored * in the file */ readscreen() { unsigned char buf[7]; unsigned int screenwidth; /* The dimensions of the screen */ unsigned int screenheight; /* (not those of the image) */ unsigned int rscreenwidth; /* The dimensions of the raster */ fread(buf,1,7,infile); screenwidth = buf[0] + (buf[1] << 8); rscreenwidth = screenwidth + screenwidth%2; /* compensate odd widths */ screenheight = buf[2] + (buf[3] << 8); global = buf[4] & 0x80; if (global) { globalbits = (buf[4] & 0x07) + 1; fread(globalmap,3,1<0; count = getc(infile)) { fread(buf,1,count,infile); for (ch=buf; count-- > 0; ch++) { datum += *ch << bits; bits += 8; while (bits >= codesize) { code = datum & codemask; datum >>= codesize; bits -= codesize; if (code == eoi) { /* This kludge put in */ #ifdef DEBUG fprintf(stderr, "found eoi code\n"); #endif goto exitloop; /* because some GIF files*/ } /* aren't standard */ if (process(code, &fill)) { goto exitloop; } } } if (fill >= raster + width*height) { fprintf(stderr, "raster full before eoi code\n"); goto exitloop; } } exitloop: if (fill != raster + width*height) { fprintf(stderr, "warning: wrong rastersize: %ld bytes\n", (long) (fill-raster)); fprintf(stderr, " instead of %ld bytes\n", (long) width*height); return 0; /* can still draw a picture ... */ } return 0; } /* * process - * Process a compression code. "clear" resets the code table. * Otherwise make a new code table entry, and output the bytes * associated with the code. */ process(code, fill) register code; unsigned char **fill; { int incode; static unsigned char firstchar; if (code == clear) { codesize = datasize + 1; codemask = (1 << codesize) - 1; avail = clear + 2; oldcode = -1; return 0; } if (oldcode == -1) { *(*fill)++ = suffix[code]; firstchar = oldcode = code; return 0; } if (code > avail) { fprintf(stderr, "code % d to large for %d\n", code, avail); return 1; } incode = code; if (code == avail) { /* the first code is always < avail */ *stackp++ = firstchar; code = oldcode; } while (code > clear) { *stackp++ = suffix[code]; code = prefix[code]; } *stackp++ = firstchar = suffix[code]; prefix[avail] = oldcode; suffix[avail] = firstchar; avail++; if (((avail & codemask) == 0) && (avail < 4096)) { codesize++; codemask += avail; } oldcode = incode; do { *(*fill)++ = *--stackp; } while (stackp > stack); return 0; } /* * initcolors - * Convert a color map (local or global) to arrays with R, G and B * values. Pass colors to SUNVIEW and set the background color. * */ initcolors(colormap, ncolors, bgcolor) unsigned char colormap[COLSIZE][3]; int ncolors; int bgcolor; { register i, k; for (i = 0; i < ncolors; i++) { red[i] = colormap[i][0]; green[i] = colormap[i][1]; blue[i] = colormap[i][2]; } } /* * rasterize - * Read a row out of the raster image and write it to the screen * */ rasterize(interleaved, raster) int interleaved; register unsigned char *raster; { register row, col; register unsigned char *rr; unsigned char *newras; IMAGE *image; #define DRAWSEGMENT(offset, step) \ for (row = offset; row < height; row += step) { \ rr = newras + row*width; \ bcopy(raster, rr, width); \ raster += width; \ } if ((newras = (unsigned char*) malloc(width*height)) == NULL) { fprintf(stderr, "not enough memory for image\n"); return 1; } rr = newras; if (interleaved) { DRAWSEGMENT(0, 8); DRAWSEGMENT(4, 8); DRAWSEGMENT(2, 4); DRAWSEGMENT(1, 2); } else DRAWSEGMENT(0, 1); image = iopen(imagename,"w",RLE(1),3,width,height,3); if(!image) { fprintf(stderr,"fromgif: can't open output image %s\n",imagename); exit(1); } rastertoimg(newras,image,width,height); iclose(image); free(newras); }