[comp.lang.postscript] GIF to Postscript

mhill@hawk.cs.ukans.edu (Mike Hill) (03/06/91)

Keywords:GIF Postscript 
Date: Wed, 6 Mar 1991 03:23:56 GMT

I am looking for a program that will take gif files and tranlate them
into a postscript file for printing.  Does such a program exist?  This
program would preferably be a program that would not have to display the
gif file (ie could run program from a dumb terminal anywhere).

Thanks in advance,
Mike Hill
mhill@hawk.cs.ukans.edu

jik@athena.mit.edu (Jonathan I. Kamens) (03/07/91)

  The best package for manipulating graphics images of all sorts, including
changing GIF images and other image types into PostScript for printing, is
IMHO the pbmplus package by Jef Poskanzer.

  It is ftp'able from a large number of ftp sites.  The machine
export.lcs.mit.edu (18.30.0.238) has it in the directory
/contrib/pbmplus.tar.Z.

  (Posted instead of mailed because other people may be interested in this.)

  BTW, "export.lcs.mit.edu" used to be "expo.lcs.mit.edu".  The anonymous ftp
machine name was changed recently to cut down the load on expo.

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8085			      Home: 617-782-0710

mhill@hawk.cs.ukans.edu (Mike Hill) (03/08/91)

Thanks for all of you that responded to my original post.  I have
received several programs that work nicely to convert gif file to
postscript and extended postscript.  If anyone would like a copy of
these, just send me a message and I will happily forward you a copy.

Thanks again,
  Mike Hill

mhill@hawk.cs.ukans.edu (Mike Hill) (03/08/91)

In article <1991Mar7.212339.6797@hawk.cs.ukans.edu> mhill@hawk.cs.ukans.edu (Mike Hill) writes:
>Thanks for all of you that responded to my original post.  I have
>received several programs that work nicely to convert gif file to
>postscript and extended postscript.  If anyone would like a copy of
>these, just send me a message and I will happily forward you a copy.
>
>Thanks again,
>  Mike Hill

I have had a lot of response to my last post, so I decided to post
the program to convert gif to ps and eps.  I hope I am not breaking
any rules by doing this.

Here you go...have fun!  If you have any good pictures or know about
some anonymous ftp sites, please let me know.

Mike

-----------------------------------cut here-------------------- 

/* received on jan 29, 1991 from
Bob Boag                                BITNET:   boag@marshall
Senior Software Systems Analyst         Internet: boag@marshall.wvnet.edu
Marshall University Computer Center     Phone:    (304)696-2624
Huntington, WV 25755-5320               FAX:      (304)696-3601
*/

/*********************************************
 *                                           *
 *  January 31, 1991 (not much) by John Gay  *
 *                                           *
 * rehacked so that either giftops or        *
 * giftoeps could be compiled.  giftops is   *
 * the default unless the symbol EPS is      *
 * defined.                                  *
 *                                           *
 *********************************************
 *             GIFtoEPS Converter            *
 *                                           *
 *      July 10, 1990  by David S. Joerg     *
 *                                           *
 * cc -DEPS -O -s -o giftoeps \              *
 *                      giftoeps.c -lsys_s   *
 * will give you a nice little 16K binary.   *
 *********************************************
 * If giftoeps does something wrong, you can *
 * email me at... joerg@alliant.mcs.anl.gov  *
 * but I probably won't be much help, I have *
 * no idea whatsoever how this beast really  *
 * works, beacause it's just an overly       *
 * simpleminded kludge of...                 *
 *********************************************
 *             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()
{
#ifdef EPS
        fprintf(stderr,"usage: giftoeps input-file > output-file\n");
#else
        fprintf(stderr,"usage: giftops input-file > output-file\n");
#endif
        exit(-1);
}

void fatal(s)
char *s;
{
#ifdef EPS
        fprintf(stderr,"giftoeps: %s\n",s);
#else
        fprintf(stderr,"giftops: %s\n",s);
#endif
        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.  */
/* (DSJ) - Write an EPS header, try not to hardcode anything. */

void writeheader(left,top,width,height)
unsigned left,top,width,height;
{
#ifndef EPS
        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");
#else
        printf("%%!PS-Adobe-2.0 EPSF-2.0\n");
        printf("%%%%Creator:giftoeps\n");
        printf("%%%%BoundingBox: %f %f %f %f\n\n", 0.0, 0.0, (double)width, (double)height);
        printf("currentscreen 3 1 roll pop pop 60 90 3 -1 roll setscreen\n");
#endif
        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");
#ifdef EPS
        printf("%d %d scale screen\n", width, height);
#else
        printf("%d %d translate 90 rotate %d %d scale screen\n",
               306+(scaledheight>>1),396-(scaledwidth>>1),
               scaledwidth, scaledheight);
#endif
}

/* 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) {
#ifdef EPS
            perror("giftoeps");
#else
            perror("giftops");
#endif
            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);
}