home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / source / giftops < prev    next >
Text File  |  1990-12-17  |  12KB  |  355 lines

  1. /* local types */
  2. #define min(x,y) ((x) < (y) ? (x) : (y))
  3. #define FALSE 0
  4. #define TRUE 1
  5.  
  6. typedef int bool;
  7. typedef struct codestruct {
  8.             struct codestruct *prefix;
  9.             unsigned char first,suffix;
  10.         } codetype;
  11.  
  12. /* local prototypes */
  13. void usage(void);
  14. void fatal(char *s);
  15. void checksignature(void);
  16. void initcolors(char colortable[256][3],
  17.                 unsigned char colormap[256][3],
  18.                 int ncolors);
  19. void writeheader(unsigned int left, unsigned int top,
  20.                  unsigned int width, unsigned int height);
  21. void outcode(codetype *p,unsigned char **fill);
  22. void process(int code,unsigned char **fill);
  23. void readscreen(void);
  24. void rasterize(int row, int width);
  25. void readraster(unsigned int width,unsigned int height);
  26. void writetrailer(void);
  27. void readimage(void);
  28. void readextension(void);
  29. ------------------------------End of giftops.h---------------------------
  30.  
  31. ------------Cut here to save below into a file called giftops.c---------
  32. /*********************************************
  33.  *             GIFtoPS Converter             *
  34.  *                                           *
  35.  *      May 16, 1988  by Scott Hemphill      *
  36.  *                                           *
  37.  * I wrote this program, and hereby place it *
  38.  * in the public domain, i.e. there are no   *
  39.  * copying restrictions of any kind.         *
  40.  *********************************************/
  41.  
  42. #include <stdio.h>
  43. #include "giftops.h"
  44.  
  45. char *malloc();
  46. int strncmp();
  47.  
  48. FILE *infile;
  49. unsigned int screenwidth;           /* The dimensions of the screen */
  50. unsigned int screenheight;          /*   (not those of the image)   */
  51. bool global;                        /* Is there a global color map? */
  52. int globalbits;                     /* Number of bits of global colors */
  53. unsigned char globalmap[256][3];    /* RGB values for global color map */
  54. char colortable[256][3];            /* Hex intensity strings for an image */
  55. unsigned char *raster;              /* Decoded image data */
  56. codetype *codetable;                /* LZW compression code data */
  57. int datasize,codesize,codemask;     /* Decoder working variables */
  58. int clear,eoi;                      /* Special code values */
  59.  
  60. void usage(void)
  61. {
  62.         fprintf(stderr,"usage: giftops input-file > output-file\n");
  63.         exit(-1);
  64. }
  65.  
  66. void fatal(char *s)
  67. {
  68.         fprintf(stderr,"giftops: %s\n",s);
  69.         exit(-1);
  70. }
  71.  
  72. void checksignature(void)
  73. {
  74.         char buf[6];
  75.  
  76.         fread(buf,1,6,infile);
  77.         if (strncmp(buf,"GIF",3)) fatal("file is not a GIF file");
  78.         if (strncmp(&buf[3],"87a",3)) fatal("unknown GIF version number");
  79. }
  80.  
  81. /* Get information which is global to all the images stored in the file */
  82.  
  83. void readscreen(void)
  84. {
  85.         unsigned char buf[7];
  86.  
  87.         fread(buf,1,7,infile);
  88.         screenwidth = buf[0] + (buf[1] << 8);
  89.         screenheight = buf[2] + (buf[3] << 8);
  90.         global = buf[4] & 0x80;
  91.         if (global) {
  92.             globalbits = (buf[4] & 0x07) + 1;
  93.             fread(globalmap,3,1<<globalbits,infile);
  94.         }
  95. }
  96.  
  97. /* Convert a color map (local or global) to an array of two character
  98.    hexadecimal strings, stored in colortable.  RGB is converted to
  99.    8-bit grayscale using integer arithmetic. */
  100.  
  101. void initcolors(char colortable[256][3],
  102.                 unsigned char colormap[256][3],
  103.                 int ncolors)
  104. {
  105.         static char hextab[] = {'0','1','2','3','4','5','6','7',
  106.                                 '8','9','A','B','C','D','E','F'};
  107.         register unsigned int color;
  108.         register int i;
  109.  
  110.         for (i = 0; i < ncolors; i++) {
  111.             color = 77*colormap[i][0] + 150*colormap[i][1] + 29*colormap[i][2];
  112.             color >>= 8;
  113.             colortable[i][0] = hextab[color >> 4];
  114.             colortable[i][1] = hextab[color & 15];
  115.             colortable[i][2] = '\0';
  116.         }
  117. }
  118.  
  119. /* Write a postscript header to the standard output.  Standard paper size
  120.    (8.5 by 11) is hard-coded, as is the whole initialization sequence. */
  121.  
  122. void writeheader(unsigned int left,unsigned int top,
  123.                  unsigned int width,unsigned int height)
  124. {
  125.         double scale;
  126.         int scaledwidth,scaledheight;
  127.  
  128.         scale = min(648.0/screenwidth, 468.0/screenheight);
  129.         scaledwidth = (int)(scale*screenwidth+0.5);
  130.         scaledheight = (int)(scale*screenheight+0.5);
  131.  
  132.         printf("currentscreen /proc exch def /angle exch def /frequency exch def\n");
  133.         printf("/angle 90 def /frequency 60 def\n");
  134.         printf("frequency angle /proc load setscreen\n");
  135.         printf("/picstr %d string def\n",width);
  136.         printf("/screen {%d %d 8 [%d 0 0 -%d 0 %d]\n",width,height,width,height,height);
  137.         printf("   {currentfile picstr readhexstring pop} image} def\n");
  138.         printf("%d %d translate 90 rotate %d %d scale screen\n",
  139.                306+(scaledheight>>1),396-(scaledwidth>>1),
  140.                scaledwidth, scaledheight);
  141. }
  142.  
  143. /* Output the bytes associated with a code to the raster array */
  144.  
  145. void outcode(register codetype *p,register unsigned char **fill)
  146. {
  147.         if (p->prefix) outcode(p->prefix,fill);
  148.         *(*fill)++ = p->suffix;
  149. }
  150.  
  151. /* Process a compression code.  "clear" resets the code table. Otherwise
  152.    make a new code table entry, and output the bytes associated with the
  153.    code. */
  154.  
  155. void process(register int code,unsigned char **fill)
  156. {
  157.         static avail,oldcode;
  158.         register codetype *p;
  159.  
  160.         if (code == clear) {
  161.             codesize = datasize + 1;
  162.             codemask = (1 << codesize) - 1;
  163.             avail = clear + 2;
  164.             oldcode = -1;
  165.         } else if (code < avail) {
  166.             outcode(&codetable[code],fill);
  167.             if (oldcode != -1) {
  168.                 p = &codetable[avail++];
  169.                 p->prefix = &codetable[oldcode];
  170.                 p->first = p->prefix->first;
  171.                 p->suffix = codetable[code].first;
  172.                 if ((avail & codemask) == 0 && avail < 4096) {
  173.                     codesize++;
  174.                     codemask += avail;
  175.                 }
  176.             }
  177.             oldcode = code;
  178.         } else if (code == avail && oldcode != -1) {
  179.             p = &codetable[avail++];
  180.             p->prefix = &codetable[oldcode];
  181.             p->first = p->prefix->first;
  182.             p->suffix = p->first;
  183.             outcode(p,fill);
  184.             if ((avail & codemask) == 0 && avail < 4096) {
  185.                 codesize++;
  186.                 codemask += avail;
  187.             }
  188.             oldcode = code;
  189.         } else {
  190.             fatal("illegal code in raster data");
  191.         }
  192. }
  193.  
  194. /* Decode a raster image */
  195.  
  196. void readraster(unsigned int width,unsigned int height)
  197. {
  198.         unsigned char *fill = raster;
  199.         unsigned char buf[255];
  200.         register int bits=0;
  201.         register unsigned int count,datum=0;
  202.         register unsigned char *ch;
  203.         register int code;
  204.  
  205.         datasize = getc(infile);
  206.         clear = 1 << datasize;
  207.         eoi = clear+1;
  208.         codesize = datasize + 1;
  209.         codemask = (1 << codesize) - 1;
  210.         codetable = (codetype*)malloc(4096*sizeof(codetype));
  211.         if (!codetable) fatal("not enough memory for code table");
  212.         for (code = 0; code < clear; code++) {
  213.             codetable[code].prefix = (codetype*)0;
  214.             codetable[code].first = code;
  215.             codetable[code].suffix = code;
  216.         }
  217.         for (count = getc(infile); count > 0; count = getc(infile)) {
  218.             fread(buf,1,count,infile);
  219.             for (ch=buf; count-- > 0; ch++) {
  220.                 datum += *ch << bits;
  221.                 bits += 8;
  222.                 while (bits >= codesize) {
  223.                     code = datum & codemask;
  224.                     datum >>= codesize;
  225.                     bits -= codesize;
  226.                     if (code == eoi) goto exitloop;  /* This kludge put in
  227.                                                         because some GIF files
  228.                                                         aren't standard */
  229.                     process(code,&fill);
  230.                 }
  231.             }
  232.         }
  233. exitloop:
  234.         if (fill != raster + width*height) fatal("raster has the wrong size");
  235.         free(codetable);
  236. }
  237.  
  238. /* Read a row out of the raster image and write it to the output file */
  239.  
  240. void rasterize(int row,int width)
  241. {
  242.         register unsigned char *scanline;
  243.         register int i;
  244.  
  245.         scanline = raster + row*width;
  246.         for (i = 0; i < width; i++) {
  247.             if (i % 40 == 0) printf("\n");  /* break line every 80 chars */
  248.             fputs(colortable[*scanline++],stdout);
  249.         }
  250.         printf("\n");
  251. }
  252.  
  253. /* write image trailer to standard output */
  254.  
  255. void writetrailer(void)
  256. {
  257.         printf("showpage\n");
  258. }
  259.  
  260. /* Read image information (position, size, local color map, etc.) and convert
  261.    to postscript. */
  262.  
  263. void readimage(void)
  264. {
  265.         unsigned char buf[9];
  266.         unsigned int left,top,width,height;
  267.         bool local,interleaved;
  268.         unsigned char localmap[256][3];
  269.         int localbits;
  270.         int *interleavetable;
  271.         register int row;
  272.         register int i;
  273.  
  274.         fread(buf,1,9,infile);
  275.         left = buf[0] + (buf[1] << 8);
  276.         top = buf[2] + (buf[3] << 8);
  277.         width = buf[4] + (buf[5] << 8);
  278.         height = buf[6] + (buf[7] << 8);
  279.         local = buf[8] & 0x80;
  280.         interleaved = buf[8] & 0x40;
  281.         if (local) {
  282.             localbits = (buf[8] & 0x7) + 1;
  283.             fread(localmap,3,1<<localbits,infile);
  284.             initcolors(colortable,localmap,1<<localbits);
  285.         } else if (global) {
  286.             initcolors(colortable,globalmap,1<<globalbits);
  287.         } else {
  288.             fatal("no colormap present for image");
  289.         }
  290.         writeheader(left,top,width,height);
  291.         raster = (unsigned char*)malloc(width*height);
  292.         if (!raster) fatal("not enough memory for image");
  293.         readraster(width,height);
  294.         if (interleaved) {
  295.             interleavetable = (int*)malloc(height*sizeof(int));
  296.             if (!interleavetable) fatal("not enough memory for interleave table");
  297.             row = 0;
  298.             for (i = top; i < top+height; i += 8) interleavetable[i] = row++;
  299.             for (i = top+4; i < top+height; i += 8) interleavetable[i] = row++;
  300.             for (i = top+2; i < top+height; i += 4) interleavetable[i] = row++;
  301.             for (i = top+1; i < top+height; i += 2) interleavetable[i] = row++;
  302.             for (row = top; row < top+height; row++)
  303. rasterize(interleavetable[row],width);
  304.             free(interleavetable);
  305.         } else {
  306.             for (row = top; row < top+height; row++) rasterize(row,width);
  307.         }
  308.         free(raster);
  309.         writetrailer();
  310. }
  311.  
  312. /* Read a GIF extension block (and do nothing with it). */
  313.  
  314. void readextension(void)
  315. {
  316.         unsigned char code;
  317.         int count;
  318.         char buf[255];
  319.  
  320.         code = getc(infile);
  321.         while (count = getc(infile)) fread(buf,1,(long) count,infile);
  322. }
  323.  
  324. void main(int argc,char *argv[])
  325. {
  326.         int quit = FALSE;
  327.         char ch;
  328.  
  329.         if (argc != 2) usage();
  330.         infile = fopen(argv[1],"r");
  331.         if (!infile) {
  332.             perror("giftops");
  333.             exit(-1);
  334.         }
  335.         checksignature();
  336.         readscreen();
  337.         do {
  338.             ch = getc(infile);
  339.             switch (ch) {
  340.                 case '\0':  break;  /* this kludge for non-standard files */
  341.                 case ',':   readimage();
  342.                             break;
  343.                 case ';':   quit = TRUE;
  344.                             break;
  345.                 case '!':   readextension();
  346.                             break;
  347.                 default:    fatal("illegal GIF block type");
  348.                             break;
  349.             }
  350.         } while (!quit);
  351. }
  352. ---------------------------End of giftops.c-------------------------------
  353.  
  354.  
  355.