[comp.sys.mac] Looking for GIF to PS on UNIX

perez@andromeda.rutgers.edu.rutgers.edu (Willie Perez) (08/23/89)

I'm looking for a GIF to postscript converter on the Unix file system.
If anyone knows where I can get it or if you can mail me a copy I'd appreciate
it.

mjkobb@mit-amt.MEDIA.MIT.EDU (Michael J Kobb) (08/23/89)

In article <Aug.22.13.44.31.1989.13254@galaxy.rutgers.edu> perez@andromeda (Willie Perez) writes:
>I'm looking for a GIF to postscript converter on the Unix file system.
>If anyone knows where I can get it or if you can mail me a copy I'd appreciate
>it.

PLEASE!!  If anyone knows about such a thing, POST the info!  There are plenty
of people who are interested!  (Myself included, of course :-))

--Mike

Disclaimer: I think that disclaimers are an incredibly sad statement about our
society.  Nonetheless, nothing that I say can or should be construed as having
been said by anyone.  Ever.

planting@hobbes.cs.pittsburgh.edu (Dr. Harry Plantinga) (08/23/89)

>In article <Aug.22.13.44.31.1989.13254@galaxy.rutgers.edu> perez@andromeda (Willie Perez) passionately pleas:
>>I'm looking for a GIF to postscript converter on the Unix file system.
>>If anyone knows where I can get it or if you can mail me a copy I'd appreciate
>>it.
>
>PLEASE!!  If anyone knows about such a thing, POST the info!  There are plenty
>of people who are interested!  (Myself included, of course :-))

Okay, okay.  There was a package of routines called fbm (fuzzy bitmap
manipulation?) posted to comp.sources.unix recently that does that and
much more (converts between various formats, some image processing,
etc.).

You can get a copy by reading the information about source archives
periodically posted to that group.

sbb@esquire.UUCP (Stephen B. Baumgarten) (08/23/89)

In article <558@mit-amt.MEDIA.MIT.EDU> mjkobb@media-lab.media.mit.edu (Michael J Kobb) writes:
>In article <Aug.22.13.44.31.1989.13254@galaxy.rutgers.edu> perez@andromeda (Willie Perez) writes:
>>I'm looking for a GIF to postscript converter on the Unix file system.
>>If anyone knows where I can get it or if you can mail me a copy I'd appreciate
>>it.
>
>PLEASE!!  If anyone knows about such a thing, POST the info!  There are plenty
>of people who are interested!  (Myself included, of course :-))

There are a couple of bitmap conversion packages available for Unix
systems that will do just what you want.  You should take a look at
"fbm" (Fuzzy's Bitmap Package) and "pbm" (Portable Bitmap Package);
both were posted to either comp.sources.unix or comp.sources.misc a
few months ago and should be available in the standard archive
locations.

The author of "fbm" is:

    Michael L. Mauldin (Fuzzy)              School of Computer Science
    ARPA: Michael.Mauldin@NL.CS.CMU.EDU     Carnegie Mellon University
    Phone: (412) 268-3065                   Pittsburgh, PA  15213-3890

According to the README file, you can also get "fbm" via FTP in the
following way:

    Anonymous FTP

    Host:       nl.cs.cmu.edu (128.2.222.56)
    User:       anonymous
    Password:   name@site
    Directory:  /usr/mlm/ftp/
    Filename:   fbm.tar.Z
    Transfer:   'image'

    Note: you must 'cd' to /usr/mlm/ftp directly, you cannot access
    either /usr, or /usr/mlm alone.  Don't forget to specify 'image'
    format transfer.

I don't know whether this information is still correct as I do not
have FTP access to try it out.

The author of "pbm" is:

    Jef Poskanzer
    jef@rtsg.ee.lbl.gov
    {ucbvax, lll-crg, sun!pacbell, apple, hplabs}!well!pokey
	
I've had great success using both packages.  You should try to get
both, as they complement each other, although for your needs
(GIF->PS), "fbm" will do what you want all by itself.

From the "fbps" man page:

    To convert a color GIF file  to  a  3  inch  wide  grayscale
    postscript file for inclusion in a Scribe or TeX document:

        % clr2gray < foo.gif | fbps -s -w3.0 > foo.PS

--
   Steve Baumgarten             | "New York... when civilization falls apart,
   Davis Polk & Wardwell        |  remember, we were way ahead of you."
   cmcl2!esquire!sbb            | 
   esquire!sbb@cmcl2.nyu.edu    |                           - David Letterman

sbj421@leah.Albany.Edu (S B Jacobson) (08/24/89)

There is a un*x program called gif2ps that makes fullsize (8.5 X 11)
grey scale conversions of gif files.  It is accessible via anonymous
ftp.

I don't recall the address off hand, but if anybody would like it,
E-mail me, and I'll look it up.

  - Steve Jacobson  -   | USnail: 171 N. Allen Street Apt 1
JAKE@ALBNYVM1.BITNET    |	  Albany, New York 12206
sbj421@leah.albany.edu  | Disclaimer:  All opinions expressed herein
JAKE@ALBNYVMS.BITNET    |	       are my own.

hampel@demon.siemens.com (Blave a blave blave.) (08/25/89)

In article <5752@pitt.UUCP> planting@cs.pitt.edu (Harry Plantinga) writes:
>>In article <Aug.22.13.44.31.1989.13254@galaxy.rutgers.edu> perez@andromeda (Willie Perez) passionately pleas:
>>>I'm looking for a GIF to postscript converter on the Unix file system.
>>>If anyone knows where I can get it or if you can mail me a copy I'd appreciate
>>>it.
>>
>>PLEASE!!  If anyone knows about such a thing, POST the info!  There are plenty
>>of people who are interested!  (Myself included, of course :-))

I already responded to the original poster by email.  I didn't realize the
demand for this.  Here's a public domain C program that converts GIF file
formats to Postscript.

-Ken

C source code follows:.........................................................
/*********************************************
 *             GIFtoPS Converter             *
 *                                           *
 *      May 16, 1988  by Scott Hemphill      *
 *                                           *
 * I wrote this program, and hereby place it *
 * in the public domain, i.e. there are no   *
 * copying restrictions of any kind.         *
 *********************************************/

#include <stdio.h>
char *malloc();
int strncmp();

#define min(x,y) ((x) < (y) ? (x) : (y))
#define FALSE 0
#define TRUE 1

typedef int bool;
typedef struct codestruct {
            struct codestruct *prefix;
            unsigned char first,suffix;
        } codetype;

FILE *infile;
unsigned int screenwidth;           /* The dimensions of the screen */
unsigned int screenheight;          /*   (not those of the image)   */
bool global;                        /* Is there a global color map? */
int globalbits;                     /* Number of bits of global colors */
unsigned char globalmap[256][3];    /* RGB values for global color map */
char colortable[256][3];            /* Hex intensity strings for an image */
unsigned char *raster;              /* Decoded image data */
codetype *codetable;                /* LZW compression code data */
int datasize,codesize,codemask;     /* Decoder working variables */
int clear,eoi;                      /* Special code values */

void usage()
{
        fprintf(stderr,"usage: giftops input-file > output-file\n");
        exit(-1);
}

void fatal(s)
char *s;
{
        fprintf(stderr,"giftops: %s\n",s);
        exit(-1);
}

void checksignature()
{
        char buf[6];

        fread(buf,1,6,infile);
        if (strncmp(buf,"GIF",3)) fatal("file is not a GIF file");
        if (strncmp(&buf[3],"87a",3)) fatal("unknown GIF version number");
}

/* 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);
        screenheight = buf[2] + (buf[3] << 8);
        global = buf[4] & 0x80;
        if (global) {
            globalbits = (buf[4] & 0x07) + 1;
            fread(globalmap,3,1<<globalbits,infile);
        }
}

/* Convert a color map (local or global) to an array of two character
   hexadecimal strings, stored in colortable.  RGB is converted to
   8-bit grayscale using integer arithmetic. */

void initcolors(colortable,colormap,ncolors)
char colortable[256][3];
unsigned char colormap[256][3];
int ncolors;
{
        static char hextab[] = {'0','1','2','3','4','5','6','7',
                                '8','9','A','B','C','D','E','F'};
        register unsigned color;
        register i;

        for (i = 0; i < ncolors; i++) {
            color = 77*colormap[i][0] + 150*colormap[i][1] + 29*colormap[i][2];
            color >>= 8;
            colortable[i][0] = hextab[color >> 4];
            colortable[i][1] = hextab[color & 15];
            colortable[i][2] = '\0';
        }
}

/* Write a postscript header to the standard output.  Standard paper size
   (8.5 by 11) is hard-coded, as is the whole initialization sequence.  */

void writeheader(left,top,width,height)
unsigned left,top,width,height;
{
        double scale;
        int scaledwidth,scaledheight;

        scale = min(648.0/screenwidth, 468.0/screenheight);
        scaledwidth = (int)(scale*screenwidth+0.5);
        scaledheight = (int)(scale*screenheight+0.5);

        printf("currentscreen /proc exch def /angle exch def /frequency exch def\n");
        printf("/angle 90 def /frequency 60 def\n");
        printf("frequency angle /proc load setscreen\n");
        printf("/picstr %d string def\n",width);
        printf("/screen {%d %d 8 [%d 0 0 -%d 0 %d]\n",width,height,width,height,height);
        printf("   {currentfile picstr readhexstring pop} image} def\n");
        printf("%d %d translate 90 rotate %d %d scale screen\n",
               306+(scaledheight>>1),396-(scaledwidth>>1),
               scaledwidth, scaledheight);
}

/* Output the bytes associated with a code to the raster array */

void outcode(p,fill)
register codetype *p;
register unsigned char **fill;
{
        if (p->prefix) outcode(p->prefix,fill);
        *(*fill)++ = p->suffix;
}

/* Process a compression code.  "clear" resets the code table.  Otherwise
   make a new code table entry, and output the bytes associated with the
   code. */

void process(code,fill)
register code;
unsigned char **fill;
{
        static avail,oldcode;
        register codetype *p;

        if (code == clear) {
            codesize = datasize + 1;
            codemask = (1 << codesize) - 1;
            avail = clear + 2;
            oldcode = -1;
        } else if (code < avail) {
            outcode(&codetable[code],fill);
            if (oldcode != -1) {
                p = &codetable[avail++];
                p->prefix = &codetable[oldcode];
                p->first = p->prefix->first;
                p->suffix = codetable[code].first;
                if ((avail & codemask) == 0 && avail < 4096) {
                    codesize++;
                    codemask += avail;
                }
            }
            oldcode = code;
        } else if (code == avail && oldcode != -1) {
            p = &codetable[avail++];
            p->prefix = &codetable[oldcode];
            p->first = p->prefix->first;
            p->suffix = p->first;
            outcode(p,fill);
            if ((avail & codemask) == 0 && avail < 4096) {
                codesize++;
                codemask += avail;
            }
            oldcode = code;
        } else {
            fatal("illegal code in raster data");
        }
}

/* Decode a raster image */

void readraster(width,height)
unsigned width,height;
{
        unsigned char *fill = raster;
        unsigned char buf[255];
        register bits=0;
        register unsigned count,datum=0;
        register unsigned char *ch;
        register int code;

        datasize = getc(infile);
        clear = 1 << datasize;
        eoi = clear+1;
        codesize = datasize + 1;
        codemask = (1 << codesize) - 1;
        codetable = (codetype*)malloc(4096*sizeof(codetype));
        if (!codetable) fatal("not enough memory for code table");
        for (code = 0; code < clear; code++) {
            codetable[code].prefix = (codetype*)0;
            codetable[code].first = code;
            codetable[code].suffix = code;
        }
        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) goto exitloop;  /* This kludge put in
                                                        because some GIF files
                                                        aren't standard */
                    process(code,&fill);
                }
            }
        }
exitloop:
        if (fill != raster + width*height) fatal("raster has the wrong size");
        free(codetable);
}

/* Read a row out of the raster image and write it to the output file */

void rasterize(row,width)
int row,width;
{
        register unsigned char *scanline;
        register i;

        scanline = raster + row*width;
        for (i = 0; i < width; i++) {
            if (i % 40 == 0) printf("\n");  /* break line every 80 chars */
            fputs(colortable[*scanline++],stdout);
        }
        printf("\n");
}

/* write image trailer to standard output */

void writetrailer()
{
        printf("showpage\n");
}

/* Read image information (position, size, local color map, etc.) and convert
   to postscript. */

void readimage()
{
        unsigned char buf[9];
        unsigned left,top,width,height;
        bool local,interleaved;
        char localmap[256][3];
        int localbits;
        int *interleavetable;
        register row;
        register i;

        fread(buf,1,9,infile);
        left = buf[0] + (buf[1] << 8);
        top = buf[2] + (buf[3] << 8);
        width = buf[4] + (buf[5] << 8);
        height = buf[6] + (buf[7] << 8);
        local = buf[8] & 0x80;
        interleaved = buf[8] & 0x40;
        if (local) {
            localbits = (buf[8] & 0x7) + 1;
            fread(localmap,3,1<<localbits,infile);
            initcolors(colortable,localmap,1<<localbits);
        } else if (global) {
            initcolors(colortable,globalmap,1<<globalbits);
        } else {
            fatal("no colormap present for image");
        }
        writeheader(left,top,width,height);
        raster = (unsigned char*)malloc(width*height);
        if (!raster) fatal("not enough memory for image");
        readraster(width,height);
        if (interleaved) {
            interleavetable = (int*)malloc(height*sizeof(int));
            if (!interleavetable) fatal("not enough memory for interleave table");
            row = 0;
            for (i = top; i < top+height; i += 8) interleavetable[i] = row++;
            for (i = top+4; i < top+height; i += 8) interleavetable[i] = row++;
            for (i = top+2; i < top+height; i += 4) interleavetable[i] = row++;
            for (i = top+1; i < top+height; i += 2) interleavetable[i] = row++;
            for (row = top; row < top+height; row++) rasterize(interleavetable[row],width);
            free(interleavetable);
        } else {
            for (row = top; row < top+height; row++) rasterize(row,width);
        }
        free(raster);
        writetrailer();
}

/* Read a GIF extension block (and do nothing with it). */

void readextension()
{
        unsigned char code,count;
        char buf[255];

        code = getc(infile);
        while (count = getc(infile)) fread(buf,1,count,infile);
}

main(argc,argv)
int argc;
char *argv[];
{
        int quit = FALSE;
        char ch;

        if (argc != 2) usage();
        infile = fopen(argv[1],"r");
        if (!infile) {
            perror("giftops");
            exit(-1);
        }
        checksignature();
        readscreen();
        do {
            ch = getc(infile);
            switch (ch) {
                case '\0':  break;  /* this kludge for non-standard files */
                case ',':   readimage();
                            break;
                case ';':   quit = TRUE;
                            break;
                case '!':   readextension();
                            break;
                default:    fatal("illegal GIF block type");
                            break;
            }
        } while (!quit);
}

rob@NRC.COM (Rob Pawsner) (09/08/89)

Here's a complete program, for those without access to archives.

/*
comp.sources.misc: Volume 3, Issue 21

The following program converts a GIF file to a PostScript source file.
It is public domain.  It is complete in one file:

  cc -o giftops giftops.c

It has been tested on Sys V and BSD systems and another (non-Unix)
system with 32-bit ints.  It shouldn't need more than 16-bit ints,
though.

The PostScript code written by this program doesn't conform to Adobe's
standards.

Scott Hemphill  hemphill@csvax.caltech.edu
    ...!ames!elroy!cit-vax!hemphill
*/


#include <stdio.h>
char *malloc();
int strncmp();

#define min(x,y) ((x) < (y) ? (x) : (y))
#define FALSE 0
#define TRUE 1

typedef int bool;
typedef struct codestruct {
      struct codestruct *prefix;
      unsigned char first,suffix;
    } codetype;

FILE *infile;
unsigned int screenwidth;       /* The dimensions of the screen */
unsigned int screenheight;      /*   (not those of the image)   */
bool global;            /* Is there a global color map? */
int globalbits;           /* Number of bits of global colors */
unsigned char globalmap[256][3];  /* RGB values for global color map */
char colortable[256][3];      /* Hex intensity strings for an image */
unsigned char *raster;        /* Decoded image data */
codetype *codetable;        /* LZW compression code data */
int datasize,codesize,codemask;   /* Decoder working variables */
int clear,eoi;            /* Special code values */

void usage()
{
    fprintf(stderr,"usage: giftops input-file > output-file\n");
    exit(-1);
}

void fatal(s)
char *s;
{
    fprintf(stderr,"giftops: %s\n",s);
    exit(-1);
}

void checksignature()
{
    char buf[6];

    fread(buf,1,6,infile);
    if (strncmp(buf,"GIF",3)) fatal("file is not a GIF file");
    if (strncmp(&buf[3],"87a",3)) fatal("unknown GIF version number");
}

/* 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);
    screenheight = buf[2] + (buf[3] << 8);
    global = buf[4] & 0x80;
    if (global) {
      globalbits = (buf[4] & 0x07) + 1;
      fread(globalmap,3,1<<globalbits,infile);
    }
}

/* Convert a color map (local or global) to an array of two character
   hexadecimal strings, stored in colortable.  RGB is converted to
   8-bit grayscale using integer arithmetic. */

void initcolors(colortable,colormap,ncolors)
char colortable[256][3];
unsigned char colormap[256][3];
int ncolors;
{
    static char hextab[] = {'0','1','2','3','4','5','6','7',
                '8','9','A','B','C','D','E','F'};
    register unsigned color;
    register i;

    for (i = 0; i < ncolors; i++) {
      color = 77*colormap[i][0] + 150*colormap[i][1] + 29*colormap[i][2];
      color >>= 8;
      colortable[i][0] = hextab[color >> 4];
      colortable[i][1] = hextab[color & 15];
      colortable[i][2] = '\0';
    }
}

/* Write a postscript header to the standard output.  Standard paper size
   (8.5 by 11) is hard-coded, as is the whole initialization sequence.  */

void writeheader(left,top,width,height)
unsigned left,top,width,height;
{
    double scale;
    int scaledwidth,scaledheight;

    scale = min(648.0/screenwidth, 468.0/screenheight);
    scaledwidth = (int)(scale*screenwidth+0.5);
    scaledheight = (int)(scale*screenheight+0.5);

    printf
      ("currentscreen /proc exch def /angle exch def /frequency exch def\n");
    printf("/angle 90 def /frequency 60 def\n");
    printf("frequency angle /proc load setscreen\n");
    printf("/picstr %d string def\n",width);
    printf
      ("/screen {%d %d 8 [%d 0 0 -%d 0 %d]\n",
       width,height,width,height,height);
    printf("   {currentfile picstr readhexstring pop} image} def\n");
    printf("%d %d translate 90 rotate %d %d scale screen\n",
         306+(scaledheight>>1),396-(scaledwidth>>1),
         scaledwidth, scaledheight);
}

/* Output the bytes associated with a code to the raster array */

void outcode(p,fill)
register codetype *p;
register unsigned char **fill;
{
    if (p->prefix) outcode(p->prefix,fill);
    *(*fill)++ = p->suffix;
}

/* Process a compression code.  "clear" resets the code table.  Otherwise
   make a new code table entry, and output the bytes associated with the
   code. */

void process(code,fill)
register code;
unsigned char **fill;
{
    static avail,oldcode;
    register codetype *p;

    if (code == clear) {
      codesize = datasize + 1;
      codemask = (1 << codesize) - 1;
      avail = clear + 2;
      oldcode = -1;
    } else if (code < avail) {
      outcode(&codetable[code],fill);
      if (oldcode != -1) {
        p = &codetable[avail++];
        p->prefix = &codetable[oldcode];
        p->first = p->prefix->first;
        p->suffix = codetable[code].first;
        if ((avail & codemask) == 0 && avail < 4096) {
          codesize++;
          codemask += avail;
        }
      }
      oldcode = code;
    } else if (code == avail && oldcode != -1) {
      p = &codetable[avail++];
      p->prefix = &codetable[oldcode];
      p->first = p->prefix->first;
      p->suffix = p->first;
      outcode(p,fill);
      if ((avail & codemask) == 0 && avail < 4096) {
        codesize++;
        codemask += avail;
      }
      oldcode = code;
    } else {
      fatal("illegal code in raster data");
    }
}

/* Decode a raster image */

void readraster(width,height)
unsigned width,height;
{
    unsigned char *fill = raster;
    unsigned char buf[255];
    register bits=0;
    register unsigned count,datum=0;
    register unsigned char *ch;
    register int code;

    datasize = getc(infile);
    clear = 1 << datasize;
    eoi = clear+1;
    codesize = datasize + 1;
    codemask = (1 << codesize) - 1;
    codetable = (codetype*)malloc(4096*sizeof(codetype));
    if (!codetable) fatal("not enough memory for code table");
    for (code = 0; code < clear; code++) {
      codetable[code].prefix = (codetype*)0;
      codetable[code].first = code;
      codetable[code].suffix = code;
    }
    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) goto exitloop;  /* This kludge put in
                            because some GIF files
                            aren't standard */
          process(code,&fill);
        }
      }
    }
exitloop:
    if (fill != raster + width*height) fatal("raster has the wrong size");
    free(codetable);
}

/* Read a row out of the raster image and write it to the output file */

void rasterize(row,width)
int row,width;
{
    register unsigned char *scanline;
    register i;

    scanline = raster + row*width;
    for (i = 0; i < width; i++) {
      if (i % 39 == 0) printf("\n");  /* break line every 78 chars */
      fputs(colortable[*scanline++],stdout);
    }
    printf("\n");
}

/* write image trailer to standard output */

void writetrailer()
{
    printf("showpage\n");
}

/* Read image information (position, size, local color map, etc.) and convert
   to postscript. */

void readimage()
{
    unsigned char buf[9];
    unsigned left,top,width,height;
    bool local,interleaved;
    char localmap[256][3];
    int localbits;
    int *interleavetable;
    register row;
    register i;

    fread(buf,1,9,infile);
    left = buf[0] + (buf[1] << 8);
    top = buf[2] + (buf[3] << 8);
    width = buf[4] + (buf[5] << 8);
    height = buf[6] + (buf[7] << 8);
    local = buf[8] & 0x80;
    interleaved = buf[8] & 0x40;
    if (local) {
      localbits = (buf[8] & 0x7) + 1;
      fread(localmap,3,1<<localbits,infile);
      initcolors(colortable,localmap,1<<localbits);
    } else if (global) {
      initcolors(colortable,globalmap,1<<globalbits);
    } else {
      fatal("no colormap present for image");
    }
    writeheader(left,top,width,height);
    raster = (unsigned char*)malloc(width*height);
    if (!raster) fatal("not enough memory for image");
    readraster(width,height);
    if (interleaved) {
      interleavetable = (int*)malloc(height*sizeof(int));
      if (!interleavetable) fatal("not enough memory for interleave table");
      row = 0;
      for (i = top; i < top+height; i += 8) interleavetable[i] = row++;
      for (i = top+4; i < top+height; i += 8) interleavetable[i] = row++;
      for (i = top+2; i < top+height; i += 4) interleavetable[i] = row++;
      for (i = top+1; i < top+height; i += 2) interleavetable[i] = row++;
      for (row = top; 
	   row < top+height; row++) rasterize(interleavetable[row],width);
      free(interleavetable);
    } else {
      for (row = top; row < top+height; row++) rasterize(row,width);
    }
    free(raster);
    writetrailer();
}

/* Read a GIF extension block (and do nothing with it). */

void readextension()
{
    unsigned char code,count;
    char buf[255];

    code = getc(infile);
    while (count = getc(infile)) fread(buf,1,count,infile);
}

main(argc,argv)
int argc;
char *argv[];
{
    int quit = FALSE;
    char ch;

    if (argc != 2) usage();
    infile = fopen(argv[1],"r");
    if (!infile) {
      perror("giftops");
      exit(-1);
    }
    checksignature();
    readscreen();
    do {
      ch = getc(infile);
      switch (ch) {
        case '\0':  break;  /* this kludge for non-standard files */
        case ',':   readimage();
              break;
        case ';':   quit = TRUE;
              break;
        case '!':   readextension();
              break;
        default:  fatal("illegal GIF block type");
              break;
      }
    } while (!quit);
}

/* end file */