home *** CD-ROM | disk | FTP | other *** search
- /*********************************************
- * GIF to SUN rasterfile *
- * *
- * March 23 1989 By Marcel J.E. Mol *
- * *
- * I hereby place this program *
- * in the public domain, i.e. there are no *
- * copying restrictions of any kind. *
- *********************************************/
-
- /*
- * Usage:
- * gif2ras <gif-file>
- *
- * Compile:
- * cc gif2ras.c -o gif2ras -lpixrect
- *
- */
-
-
- #include <stdio.h>
- #include <rasterfile.h>
-
- char *malloc();
- int strncmp();
-
- #define FALSE 0
- #define TRUE 1
- #define COLSIZE 256
- #define PICSIZE 2;
- #define SHOWCOUNT 10;
-
-
- /*
- * Rasterfile variables
- */
- struct rasterfile header;
-
- /*
- * LZW structures and variables
- */
- typedef int bool;
- 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;
- int oldcode;
-
- /*
- * GIF variables
- */
- FILE *infile;
- unsigned int screenwidth; /* The dimensions of the screen */
- unsigned int screenheight; /* (not those of the image) */
- unsigned int rscreenwidth; /* The dimensions of the raster */
- bool 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 left,top,width,height,rwidth;
-
- char *progname;
- char *filename;
-
- void convert();
- int checksignature();
- void readscreen();
- int readimage();
- void readextension();
- int readraster();
- int process();
- void outcode();
- void initraster();
- void initcolors();
- int rasterize();
- void usage();
-
-
-
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- extern int optind;
- extern char *optarg;
- int flag;
-
- progname = *argv;
-
- while ((flag = getopt(argc, argv, "")) != EOF) {
- switch (flag) {
- default : fprintf(stderr, "ignoring unknown flag %c\n", flag);
- usage();
- }
- }
-
- if (optind >= argc) {
- filename = "stdin";
- convert();
- }
- else {
- filename = argv[1];
- if ((infile = fopen(filename,"r")) == NULL) {
- perror(filename);
- exit(1);
- }
- convert();
- fclose(infile);
- }
-
- #if defined(ARGS)
- else
- while (optind < argc) {
- filename = argv[optind];
- optind++;
- if ((infile = fopen(filename,"r")) == NULL) {
- perror(filename);
- continue;
- }
- convert();
- fclose(infile);
- }
- #endif
-
- } /* main */
-
-
-
- void convert()
- {
- char ch;
-
- /* fprintf(stderr, "%s:\n", filename); */
- if (checksignature())
- return;
- readscreen();
- while ((ch = getc(infile)) != ';' && ch != EOF) {
- switch (ch) {
- case '\0': break; /* this kludge for non-standard files */
- case ',': if (readimage())
- return;
- break;
- case '!': readextension();
- break;
- default: fprintf(stderr, "illegal GIF block type\n");
- return;
- break;
- }
- }
-
- } /* convert */
-
-
-
- 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;
-
- } /* checksignature */
-
-
-
- /*
- * Get information which is global to all the images stored in the file
- */
-
- void readscreen()
- {
- unsigned char buf[7];
-
- 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<<globalbits,infile);
- }
- bgcolor = buf[5];
- /*
- fprintf(stderr, " global screen: %dx%dx%d, backgroundcolor: %d\n",
- screenwidth, screenheight, 1<<globalbits, bgcolor);
- */
-
- } /* readscreen */
-
-
-
-
- readimage()
- {
- unsigned char buf[9];
- bool local, interleaved;
- char localmap[256][3];
- int localbits;
- register row;
- register i;
-
- if (fread(buf, 1, 9, infile) == 0) {
- perror(filename);
- exit(1);
- }
- left = buf[0] + (buf[1] << 8);
- top = buf[2] + (buf[3] << 8);
- width = buf[4] + (buf[5] << 8);
- rwidth = width + width%2; /* compensate odd widths */
- height = buf[6] + (buf[7] << 8);
- local = buf[8] & 0x80;
- interleaved = buf[8] & 0x40;
- /*
- fprintf(stderr, " image: %dx%d %s org: %d,%d\n", width, height,
- interleaved ? "interleaved" : "", left, top);
- */
- if (local == 0 && global == 0) {
- fprintf(stderr, "no colormap present for image\n");
- return 1;
- }
- if ((raster = (unsigned char*) malloc(rwidth*height)) == NULL) {
- fprintf(stderr, "not enough memory for image\n");
- return 1;
- }
- if (readraster(width, height))
- return 1;
-
- if (local) {
- localbits = (buf[8] & 0x7) + 1;
- /*
- fprintf(stderr, " local colors: %d\n", 1<<localbits);
- */
- fread(localmap, 3, 1<<localbits, infile);
- initraster(1<<localbits);
- initcolors(localmap, 1<<localbits, bgcolor);
- } else if (global) {
- initraster(1<<globalbits);
- initcolors(globalmap, 1<<globalbits, bgcolor);
- }
-
- rasterize(interleaved, raster);
- free(raster);
-
- return 0;
-
- } /* readimage */
-
-
-
- /*
- * Read a GIF extension block (and do nothing with it).
- */
-
- void readextension()
- {
- unsigned char code;
- int count;
- char buf[255];
-
- code = getc(infile);
- while (count = getc(infile))
- fread(buf, 1, count, infile);
-
- } /* readextension */
-
-
-
- /*
- * Decode a raster image
- */
-
- readraster(width, height)
- unsigned width,height;
- {
- unsigned char *fill = raster;
- unsigned char buf[255];
- register bits=0;
- register unsigned datum=0;
- register unsigned char *ch;
- register int count, code;
-
- datasize = getc(infile);
- clear = 1 << datasize;
- eoi = clear + 1;
- avail = clear + 2;
- oldcode = -1;
- codesize = datasize + 1;
- codemask = (1 << codesize) - 1;
- for (code = 0; code < clear; code++) {
- prefix[code] = 0;
- suffix[code] = code;
- }
- stackp = stack;
- for (count = getc(infile); count > 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 */
- /*
- fprintf(stderr, "found eoi code\n");
- */
- 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;
-
- } /* readraster */
-
-
-
-
- /*
- * 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;
-
- } /* process */
-
-
-
- void initraster(numcols)
- int numcols;
- {
-
- header.ras_magic= 0x59a66a95;
- header.ras_width= rwidth;
- header.ras_height= height;
- header.ras_depth= 8;
- header.ras_length= rwidth * height;
- header.ras_type= RT_STANDARD;
- header.ras_maptype= RMT_EQUAL_RGB;
- header.ras_maplength= 3*numcols;
-
- if (fwrite(&header, sizeof(header), 1, stdout) == 0) {
- perror(progname);
- exit(1);
- }
-
-
- } /* initraster */
-
-
-
- /*
- * Convert a color map (local or global) to arrays with R, G and B
- * values. Pass colors to SUNVIEW and set the background color.
- */
-
- void initcolors(colormap, ncolors, bgcolor)
- unsigned char colormap[COLSIZE][3];
- int ncolors;
- int bgcolor;
- {
- register i;
- unsigned char red[COLSIZE];
- unsigned char green[COLSIZE];
- unsigned char blue[COLSIZE];
-
- /*
- fprintf(stderr, " ");
- */
- for (i = 0; i < ncolors; i++) {
- red[i] = colormap[i][0];
- green[i] = colormap[i][1];
- blue[i] = colormap[i][2];
- /*
- fprintf(stderr, " %3u: %3u, %3u, %3u", i, red[i], green[i], blue[i]);
- if (i%3 == 2) fprintf(stderr, "\n ");
- */
- }
-
- /*
- fprintf(stderr, "\n Background: %3u: %3u, %3u, %3u\n", bgcolor,
- red[bgcolor], green[bgcolor], blue[bgcolor]);
- */
-
- if (fwrite(red, 1, ncolors, stdout) == 0) {
- perror(progname);
- exit(1);
- }
- if (fwrite(green, 1, ncolors, stdout) == 0) {
- perror(progname);
- exit(1);
- }
- if (fwrite(blue, 1, ncolors, stdout) == 0) {
- perror(progname);
- exit(1);
- }
-
- } /* initcolors */
-
-
-
- /*
- * 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;
-
-
-
- #define DRAWSEGMENT(offset, step) \
- for (row = offset; row < height; row += step) { \
- rr = newras + row*rwidth; \
- bcopy(raster, rr, width); \
- raster += width; \
- }
-
-
- if ((newras = (unsigned char*) malloc(rwidth*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);
-
- if (!fwrite(newras, 1, rwidth*height, stdout)) {
- perror(progname);
- exit(1);
- }
-
- free(newras);
-
-
- } /* rasterize */
-
-
-
- void usage()
- {
-
- fprintf(stderr, "usage: %s [-l<num] [-s<num>] [-b] gif-files\n",
- progname);
-
- } /* usage */
-
-