home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / software / unix / libtiff / lbtif3_3.tar / tools / gif2tiff.c < prev    next >
C/C++ Source or Header  |  1993-08-26  |  9KB  |  398 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Header: /usr/people/sam/tiff/tools/RCS/gif2tiff.c,v 1.9 93/08/26 17:12:53 sam Exp $";
  3. #endif
  4.  
  5. /*
  6.  *    convert a GIF file into a TIFF file.
  7.  *    based on Paul Haeberli's fromgif program which in turn is
  8.  *    based on a GIF file reader by Marcel J.E. Mol March 23 1989 
  9.  *
  10.  *    if input is 320 by 200 pixel aspect is probably 1.2
  11.  *    if input is 640 350 pixel aspect is probably 1.37
  12.  *
  13.  */
  14. #include <math.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18.  
  19. #include "tiffio.h"
  20.  
  21. #define    GIFGAMMA    (1.5)        /* smaller makes output img brighter */
  22. #define    IMAX        ((1<<16)-1)    /* max intensity value */
  23. #define EXTRAFUDGE    128        /* some people write BAD .gif files */
  24.  
  25. unsigned short gamtab[256];
  26.  
  27. void
  28. makegamtab(float gam)
  29. {
  30.     int i;
  31.  
  32.     for(i=0; i<256; i++) 
  33.     gamtab[i] = IMAX*pow(i/255.0,gam)+0.5;
  34. }
  35.  
  36. short rbuf[8192];
  37. short gbuf[8192];
  38. short bbuf[8192];
  39.  
  40. #define COLSIZE 256
  41.  
  42. unsigned char *stackp;
  43. unsigned int prefix[4096];
  44. unsigned char suffix[4096];
  45. unsigned char stack[4096];
  46. int datasize,codesize,codemask;     /* Decoder working variables */
  47. int clear,eoi;                      /* Special code values */
  48. int avail, oldcode;
  49.  
  50. FILE *infile;
  51. int global;                        /* Is there a global color map? */
  52. int globalbits;                     /* Number of bits of global colors */
  53. unsigned char globalmap[COLSIZE][3];/* RGB values for global color map */
  54. unsigned char *raster;              /* Decoded image data */
  55. unsigned int width, height;
  56. unsigned short red[COLSIZE];
  57. unsigned short green[COLSIZE];
  58. unsigned short blue[COLSIZE];
  59. char *filename, *imagename;
  60.  
  61. void    convert(void);
  62. int    checksignature(void);
  63. void    readscreen(void);
  64. int    readgifimage(void);
  65. void    readextension(void);
  66. int    readraster(void);
  67. int    process(int, unsigned char**);
  68. void    initcolors(unsigned char [COLSIZE][3], int);
  69. void    rasterize(int);
  70.  
  71. void
  72. main(int argc, char* argv[])
  73. {
  74.     extern int optind;
  75.     extern char *optarg;
  76.     int flag;
  77.  
  78.     makegamtab(GIFGAMMA);
  79.     if(argc<3) {
  80.     fprintf(stderr,"usage: gif2tif image.gif image.tif\n");
  81.     exit(1);
  82.     }
  83.     filename = argv[1];
  84.     imagename = argv[2];
  85.     if ((infile = fopen(filename,"r")) == NULL) {
  86.     perror(filename);
  87.     exit(1);
  88.     }
  89.     convert();
  90.     fclose(infile);
  91.     exit(0);
  92. }
  93.  
  94. void
  95. convert(void)
  96. {
  97.     char ch;
  98.  
  99.     if (checksignature())
  100.         return;
  101.     readscreen();
  102.     while ((ch = getc(infile)) != ';' && ch != EOF) {
  103.         switch (ch) {
  104.             case '\0':  break;  /* this kludge for non-standard files */
  105.             case ',':   if (readgifimage())
  106.                            return;
  107.                         break;
  108.             case '!':   readextension();
  109.                         break;
  110.             default:    fprintf(stderr, "illegal GIF block type\n");
  111.                         return;
  112.                         break;
  113.         }
  114.     }
  115. }
  116.  
  117. int
  118. checksignature(void)
  119. {
  120.     char buf[6];
  121.  
  122.     fread(buf,1,6,infile);
  123.     if (strncmp(buf,"GIF",3)) {
  124.         fprintf(stderr, "file is not a GIF file\n");
  125.         return 1;
  126.     }
  127.     if (strncmp(&buf[3],"87a",3)) {
  128.         fprintf(stderr, "unknown GIF version number\n");
  129.         return 1;
  130.     }
  131.     return 0;
  132. }
  133.  
  134. /*
  135.  *     readscreen - 
  136.  *        Get information which is global to all the images stored 
  137.  *    in the file
  138.  */
  139. void
  140. readscreen(void)
  141. {
  142.     unsigned char buf[7];
  143.  
  144.     fread(buf,1,7,infile);
  145.     global = buf[4] & 0x80;
  146.     if (global) {
  147.         globalbits = (buf[4] & 0x07) + 1;
  148.         fread(globalmap,3,1<<globalbits,infile);
  149.     }
  150. }
  151.  
  152. int
  153. readgifimage(void)
  154. {
  155.     unsigned char buf[9];
  156.     int local, interleaved;
  157.     unsigned char localmap[256][3];
  158.     int localbits;
  159.     register row;
  160.     register i;
  161.  
  162.     if (fread(buf, 1, 9, infile) == 0) {
  163.         perror(filename);
  164.         exit(1);
  165.     }
  166.     width = buf[4] + (buf[5] << 8);
  167.     height = buf[6] + (buf[7] << 8);
  168.     local = buf[8] & 0x80;
  169.     interleaved = buf[8] & 0x40;
  170.  
  171.     if (local == 0 && global == 0) {
  172.         fprintf(stderr, "no colormap present for image\n");
  173.         return 1;
  174.     }
  175.     if ((raster = (unsigned char*) malloc(width*height+EXTRAFUDGE)) == NULL) {
  176.         fprintf(stderr, "not enough memory for image\n");
  177.         return 1;
  178.     }
  179.     if (readraster())
  180.         return 1;
  181.     if (local) {
  182.         localbits = (buf[8] & 0x7) + 1;
  183.  
  184.         fprintf(stderr, "   local colors: %d\n", 1<<localbits);
  185.  
  186.         fread(localmap, 3, 1<<localbits, infile);
  187.         initcolors(localmap, 1<<localbits);
  188.     } else if (global) {
  189.         initcolors(globalmap, 1<<globalbits);
  190.     }
  191.     rasterize(interleaved);
  192.     free(raster);
  193.     return 0;
  194. }
  195.  
  196. /*
  197.  *     readextension -
  198.  *        Read a GIF extension block (and do nothing with it).
  199.  *
  200.  */
  201. void
  202. readextension(void)
  203. {
  204.     int count;
  205.     char buf[255];
  206.  
  207.     (void) getc(infile);
  208.     while (count = getc(infile))
  209.         fread(buf, 1, count, infile);
  210. }
  211.  
  212. /*
  213.  *     readraster -
  214.  *        Decode a raster image
  215.  *
  216.  */
  217. int
  218. readraster(void)
  219. {
  220.     unsigned char *fill = raster;
  221.     unsigned char buf[255];
  222.     register bits=0;
  223.     register unsigned datum=0;
  224.     register unsigned char *ch;
  225.     register int count, code;
  226.  
  227.     datasize = getc(infile);
  228.     clear = 1 << datasize;
  229.     eoi = clear + 1;
  230.     avail = clear + 2;
  231.     oldcode = -1;
  232.     codesize = datasize + 1;
  233.     codemask = (1 << codesize) - 1;
  234.     for (code = 0; code < clear; code++) {
  235.     prefix[code] = 0;
  236.     suffix[code] = code;
  237.     }
  238.     stackp = stack;
  239.     for (count = getc(infile); count > 0; count = getc(infile)) {
  240.     fread(buf,1,count,infile);
  241.     for (ch=buf; count-- > 0; ch++) {
  242.         datum += *ch << bits;
  243.         bits += 8;
  244.         while (bits >= codesize) {
  245.         code = datum & codemask;
  246.         datum >>= codesize;
  247.         bits -= codesize;
  248.         if (code == eoi) {               /* This kludge put in */
  249. #ifdef DEBUG
  250.     fprintf(stderr, "found eoi code\n");
  251. #endif
  252.             goto exitloop;               /* because some GIF files*/
  253.         }                                /* aren't standard */
  254.         if (process(code, &fill)) {
  255.             goto exitloop;
  256.         }
  257.         }
  258.     }
  259.     if (fill >= raster + width*height) {
  260.         fprintf(stderr, "raster full before eoi code\n");
  261.         goto exitloop;
  262.     }
  263.     }
  264. exitloop:
  265.     if (fill != raster + width*height)  {
  266.     fprintf(stderr, "warning: wrong rastersize: %ld bytes\n",
  267.                               (long) (fill-raster));
  268.     fprintf(stderr, "         instead of %ld bytes\n",
  269.                               (long) width*height);
  270.     return 0; /* can still draw a picture ... */
  271.     }
  272.     return 0;
  273. }
  274.  
  275. /*
  276.  *     process - 
  277.  *        Process a compression code.  "clear" resets the code table.  
  278.  *    Otherwise make a new code table entry, and output the bytes 
  279.  *    associated with the code.
  280.  */
  281. int
  282. process(register code, unsigned char** fill)
  283. {
  284.     int incode;
  285.     static unsigned char firstchar;
  286.  
  287.     if (code == clear) {
  288.     codesize = datasize + 1;
  289.     codemask = (1 << codesize) - 1;
  290.     avail = clear + 2;
  291.     oldcode = -1;
  292.     return 0;
  293.     }
  294.  
  295.     if (oldcode == -1) {
  296.     *(*fill)++ = suffix[code];
  297.     firstchar = oldcode = code;
  298.     return 0;
  299.     }
  300.     if (code > avail) {
  301.     fprintf(stderr, "code % d to large for %d\n", code, avail);
  302.     return 1; 
  303.     }
  304.  
  305.     incode = code;
  306.     if (code == avail) {      /* the first code is always < avail */
  307.     *stackp++ = firstchar;
  308.     code = oldcode;
  309.     }
  310.     while (code > clear) {
  311.     *stackp++ = suffix[code];
  312.     code = prefix[code];
  313.     }
  314.  
  315.     *stackp++ = firstchar = suffix[code];
  316.     prefix[avail] = oldcode;
  317.     suffix[avail] = firstchar;
  318.     avail++;
  319.  
  320.     if (((avail & codemask) == 0) && (avail < 4096)) {
  321.     codesize++;
  322.     codemask += avail;
  323.     }
  324.     oldcode = incode;
  325.     do {
  326.     *(*fill)++ = *--stackp;
  327.     } while (stackp > stack);
  328.     return 0;
  329. }
  330.  
  331. /*
  332.  *     initcolors -
  333.  *        Convert a color map (local or global) to arrays with R, G and B
  334.  *     values. 
  335.  *
  336.  */
  337. void
  338. initcolors(unsigned char colormap[COLSIZE][3], int ncolors)
  339. {
  340.     register i, k;
  341.  
  342.     for (i = 0; i < ncolors; i++) {
  343.         red[i]   = gamtab[colormap[i][0]];
  344.         green[i] = gamtab[colormap[i][1]];
  345.         blue[i]  = gamtab[colormap[i][2]];
  346.     }
  347. }
  348.  
  349. void
  350. rasterize(int interleaved)
  351. {
  352.     register row, col;
  353.     register unsigned char *rr;
  354.     unsigned char *newras;
  355.     TIFF *tif;
  356.     
  357. #define DRAWSEGMENT(offset, step)            \
  358.         for (row = offset; row < height; row += step) {    \
  359.             rr = newras + row*width;            \
  360.             memcpy(rr, raster, width);            \
  361.             raster += width;                            \
  362.         }
  363.  
  364.     if ((newras = (unsigned char*) malloc(width*height+EXTRAFUDGE)) == NULL) {
  365.         fprintf(stderr, "not enough memory for image\n");
  366.         return;
  367.     }
  368.     if (interleaved) {
  369.         DRAWSEGMENT(0, 8);
  370.         DRAWSEGMENT(4, 8);
  371.         DRAWSEGMENT(2, 4);
  372.         DRAWSEGMENT(1, 2);
  373.     }
  374.     else 
  375.         DRAWSEGMENT(0, 1);
  376.  
  377.     tif = TIFFOpen(imagename, "w");
  378.     if (!tif) {
  379.     TIFFError(imagename,"Can not open output image");
  380.     exit(-1);
  381.     }
  382.     TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (uint32) width);
  383.     TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (uint32) height);
  384.     TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
  385.     TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
  386.     TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  387.     TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
  388.     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
  389.     TIFFSetField(tif, TIFFTAG_COLORMAP, red, green, blue);
  390.     TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
  391.     for(row=0; row<height; row++)
  392.     if (TIFFWriteScanline(tif, newras+row*width, row, 0) < 0)
  393.         break;
  394.     TIFFClose(tif);
  395.  
  396.     free(newras);
  397.