New comit of SDL2
[supertux.git] / src / SDL2 / external / tiff-4.0.3 / tools / gif2tiff.c
1 /* $Id: gif2tiff.c,v 1.12 2010-12-15 00:22:44 faxguy Exp $ */
2
3 /*
4  * Copyright (c) 1990-1997 Sam Leffler
5  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and 
8  * its documentation for any purpose is hereby granted without fee, provided
9  * that (i) the above copyright notices and this permission notice appear in
10  * all copies of the software and related documentation, and (ii) the names of
11  * Sam Leffler and Silicon Graphics may not be used in any advertising or
12  * publicity relating to the software without the specific, prior written
13  * permission of Sam Leffler and Silicon Graphics.
14  * 
15  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
16  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
17  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
18  * 
19  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
23  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
24  * OF THIS SOFTWARE.
25  */
26
27 /*
28  *      convert a GIF file into a TIFF file.
29  *      based on Paul Haeberli's fromgif program which in turn is
30  *      based on a GIF file reader by Marcel J.E. Mol March 23 1989 
31  *
32  *      if input is 320 by 200 pixel aspect is probably 1.2
33  *      if input is 640 350 pixel aspect is probably 1.37
34  *
35  */
36 #include "tif_config.h"
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <math.h>
42
43 #ifdef HAVE_UNISTD_H
44 # include <unistd.h>
45 #endif
46
47 #ifdef NEED_LIBPORT
48 # include "libport.h"
49 #endif
50
51 #include "tiffio.h"
52
53 #define GIFGAMMA        (1.5)           /* smaller makes output img brighter */
54 #define IMAX            0xffff          /* max intensity value */
55 #define EXTRAFUDGE      128             /* some people write BAD .gif files */
56
57 #define streq(a,b)      (strcmp(a,b) == 0)
58 #define strneq(a,b,n)   (strncmp(a,b,n) == 0)
59
60 unsigned short gamtab[256];
61
62 void
63 makegamtab(float gam)
64 {
65     int i;
66
67     for(i=0; i<256; i++) 
68         gamtab[i] = (unsigned short) (IMAX*pow(i/255.0,gam)+0.5);
69 }
70
71 char* stuff[] = {
72 "usage: gif2tiff [options] input.gif output.tif",
73 "where options are:",
74 " -r #          make each strip have no more than # rows",
75 "",
76 " -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
77 " -c zip[:opts] compress output with deflate encoding",
78 " -c packbits   compress output with packbits encoding",
79 " -c none       use no compression algorithm on output",
80 "",
81 "LZW and deflate options:",
82 " #             set predictor value",
83 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
84 NULL
85 };
86
87 static void
88 usage(void)
89 {
90         char buf[BUFSIZ];
91         int i;
92
93         setbuf(stderr, buf);
94         fprintf(stderr, "%s\n\n", TIFFGetVersion());
95         for (i = 0; stuff[i] != NULL; i++)
96                 fprintf(stderr, "%s\n", stuff[i]);
97         exit(-1);
98 }
99
100 #define COLSIZE 256
101
102 unsigned char *stackp;
103 unsigned int prefix[4096];
104 unsigned char suffix[4096];
105 unsigned char stack[4096];
106 int datasize,codesize,codemask;     /* Decoder working variables */
107 int clear,eoi;                      /* Special code values */
108 int avail, oldcode;
109
110 FILE *infile;
111 int global;                        /* Is there a global color map? */
112 int globalbits;                     /* Number of bits of global colors */
113 unsigned char globalmap[COLSIZE][3];/* RGB values for global color map */
114 unsigned char *raster;              /* Decoded image data */
115 unsigned long width, height;
116 unsigned short red[COLSIZE];
117 unsigned short green[COLSIZE];
118 unsigned short blue[COLSIZE];
119 char *filename, *imagename;
120
121 static  uint16 compression = COMPRESSION_PACKBITS;
122 static  uint16 predictor = 0;
123 static  uint32 rowsperstrip = (uint32) -1;
124 static  int processCompressOptions(char*);
125
126 int     convert(void);
127 int     checksignature(void);
128 void    readscreen(void);
129 int     readgifimage(char*);
130 void    readextension(void);
131 int     readraster(void);
132 int     process(int, unsigned char**);
133 void    initcolors(unsigned char [COLSIZE][3], int);
134 void    rasterize(int, char*);
135
136 int
137 main(int argc, char* argv[])
138 {
139     extern int optind;
140     extern char *optarg;
141     int c, status;
142
143     while ((c = getopt(argc, argv, "c:r:")) != -1)
144             switch (c) {
145             case 'c':           /* compression scheme */
146                     if (!processCompressOptions(optarg))
147                             usage();
148                     break;
149             case 'r':           /* rows/strip */
150                     rowsperstrip = atoi(optarg);
151                     break;
152             case '?':
153                     usage();
154                     /*NOTREACHED*/
155             }
156     if (argc - optind != 2)
157             usage();
158
159     makegamtab(GIFGAMMA);
160     filename = argv[optind];
161     imagename = argv[optind+1];
162     if ((infile = fopen(imagename, "rb")) != NULL) {
163         int c;
164         fclose(infile);
165         printf("overwrite %s? ", imagename); fflush(stdout);
166         c = getc(stdin);
167         if (c != 'y' && c != 'Y')
168             return (1);
169     }
170     if ((infile = fopen(filename, "rb")) == NULL) {
171         perror(filename);
172         return (1);
173     }
174     status = convert();
175     fclose(infile);
176     return (status);
177 }
178
179 static int
180 processCompressOptions(char* opt)
181 {
182         if (streq(opt, "none"))
183                 compression = COMPRESSION_NONE;
184         else if (streq(opt, "packbits"))
185                 compression = COMPRESSION_PACKBITS;
186         else if (strneq(opt, "lzw", 3)) {
187                 char* cp = strchr(opt, ':');
188                 if (cp)
189                         predictor = atoi(cp+1);
190                 compression = COMPRESSION_LZW;
191         } else if (strneq(opt, "zip", 3)) {
192                 char* cp = strchr(opt, ':');
193                 if (cp)
194                         predictor = atoi(cp+1);
195                 compression = COMPRESSION_DEFLATE;
196         } else
197                 return (0);
198         return (1);
199 }
200
201 int
202 convert(void)
203 {
204     int ch;
205     char* mode = "w";
206
207     if (!checksignature())
208         return (-1);
209     readscreen();
210     while ((ch = getc(infile)) != ';' && ch != EOF) {
211         switch (ch) {
212             case '\0':  break;  /* this kludge for non-standard files */
213             case ',':   if (!readgifimage(mode))
214                            return (-1);
215                         mode = "a";             /* subsequent images append */
216                         break;
217             case '!':   readextension();
218                         break;
219             default:    fprintf(stderr, "illegal GIF block type\n");
220                         return (-1);
221         }
222     }
223     return (0);
224 }
225
226 int
227 checksignature(void)
228 {
229     char buf[6];
230
231     fread(buf,1,6,infile);
232     if (strncmp(buf,"GIF",3)) {
233         fprintf(stderr, "file is not a GIF file\n");
234         return 0;
235     }
236     if (strncmp(&buf[3],"87a",3)) {
237         fprintf(stderr, "unknown GIF version number\n");
238         return 0;
239     }
240     return 1;
241 }
242
243 /*
244  *      readscreen - 
245  *              Get information which is global to all the images stored 
246  *      in the file
247  */
248 void
249 readscreen(void)
250 {
251     unsigned char buf[7];
252
253     fread(buf,1,7,infile);
254     global = buf[4] & 0x80;
255     if (global) {
256         globalbits = (buf[4] & 0x07) + 1;
257         fread(globalmap,3,((size_t)1)<<globalbits,infile);
258     }
259 }
260
261 int
262 readgifimage(char* mode)
263 {
264     unsigned char buf[9];
265     int local, interleaved;
266     unsigned char localmap[256][3];
267     int localbits;
268     int status;
269
270     if (fread(buf, 1, 9, infile) == 0) {
271         perror(filename);
272         return (0);
273     }
274     width = buf[4] + (buf[5] << 8);
275     height = buf[6] + (buf[7] << 8);
276     local = buf[8] & 0x80;
277     interleaved = buf[8] & 0x40;
278
279     if (local == 0 && global == 0) {
280         fprintf(stderr, "no colormap present for image\n");
281         return (0);
282     }
283     if ((raster = (unsigned char*) _TIFFmalloc(width*height+EXTRAFUDGE)) == NULL) {
284         fprintf(stderr, "not enough memory for image\n");
285         return (0);
286     }
287     if (local) {
288         localbits = (buf[8] & 0x7) + 1;
289
290         fprintf(stderr, "   local colors: %d\n", 1<<localbits);
291
292         fread(localmap, 3, ((size_t)1)<<localbits, infile);
293         initcolors(localmap, 1<<localbits);
294     } else if (global) {
295         initcolors(globalmap, 1<<globalbits);
296     }
297     if ((status = readraster()))
298         rasterize(interleaved, mode);
299     _TIFFfree(raster);
300     return status;
301 }
302
303 /*
304  *      readextension -
305  *              Read a GIF extension block (and do nothing with it).
306  *
307  */
308 void
309 readextension(void)
310 {
311     int count;
312     char buf[255];
313
314     (void) getc(infile);
315     while ((count = getc(infile)))
316         fread(buf, 1, count, infile);
317 }
318
319 /*
320  *      readraster -
321  *              Decode a raster image
322  *
323  */
324 int
325 readraster(void)
326 {
327     unsigned char *fill = raster;
328     unsigned char buf[255];
329     register int bits=0;
330     register unsigned long datum=0;
331     register unsigned char *ch;
332     register int count, code;
333     int status = 1;
334
335     datasize = getc(infile);
336     clear = 1 << datasize;
337     eoi = clear + 1;
338     avail = clear + 2;
339     oldcode = -1;
340     codesize = datasize + 1;
341     codemask = (1 << codesize) - 1;
342     for (code = 0; code < clear; code++) {
343         prefix[code] = 0;
344         suffix[code] = code;
345     }
346     stackp = stack;
347     for (count = getc(infile); count > 0; count = getc(infile)) {
348         fread(buf,1,count,infile);
349         for (ch=buf; count-- > 0; ch++) {
350             datum += (unsigned long) *ch << bits;
351             bits += 8;
352             while (bits >= codesize) {
353                 code = datum & codemask;
354                 datum >>= codesize;
355                 bits -= codesize;
356                 if (code == eoi) {               /* This kludge put in */
357                     goto exitloop;               /* because some GIF files*/
358                 }                                /* aren't standard */
359                 if (!process(code, &fill)) {
360                     status = 0;
361                     goto exitloop;
362                 }
363             }
364         }
365         if (fill >= raster + width*height) {
366             fprintf(stderr, "raster full before eoi code\n");
367             break;
368         }
369     }
370 exitloop:
371     if (fill != raster + width*height)  {
372         fprintf(stderr, "warning: wrong rastersize: %ld bytes\n",
373                                                       (long) (fill-raster));
374         fprintf(stderr, "         instead of %ld bytes\n",
375                                                       (long) width*height);
376     }
377     return status;
378 }
379
380 /*
381  *      process - 
382  *              Process a compression code.  "clear" resets the code table.  
383  *      Otherwise make a new code table entry, and output the bytes 
384  *      associated with the code.
385  */
386 int
387 process(register int code, unsigned char** fill)
388 {
389     int incode;
390     static unsigned char firstchar;
391
392     if (code == clear) {
393         codesize = datasize + 1;
394         codemask = (1 << codesize) - 1;
395         avail = clear + 2;
396         oldcode = -1;
397         return 1;
398     }
399
400     if (oldcode == -1) {
401         *(*fill)++ = suffix[code];
402         firstchar = oldcode = code;
403         return 1;
404     }
405     if (code > avail) {
406         fprintf(stderr, "code %d too large for %d\n", code, avail);
407         return 0; 
408     }
409
410     incode = code;
411     if (code == avail) {      /* the first code is always < avail */
412         *stackp++ = firstchar;
413         code = oldcode;
414     }
415     while (code > clear) {
416         *stackp++ = suffix[code];
417         code = prefix[code];
418     }
419
420     *stackp++ = firstchar = suffix[code];
421     prefix[avail] = oldcode;
422     suffix[avail] = firstchar;
423     avail++;
424
425     if (((avail & codemask) == 0) && (avail < 4096)) {
426         codesize++;
427         codemask += avail;
428     }
429     oldcode = incode;
430     do {
431         *(*fill)++ = *--stackp;
432     } while (stackp > stack);
433     return 1;
434 }
435
436 /*
437  *      initcolors -
438  *              Convert a color map (local or global) to arrays with R, G and B
439  *      values. 
440  *
441  */
442 void
443 initcolors(unsigned char colormap[COLSIZE][3], int ncolors)
444 {
445     register int i;
446
447     for (i = 0; i < ncolors; i++) {
448         red[i]   = gamtab[colormap[i][0]];
449         green[i] = gamtab[colormap[i][1]];
450         blue[i]  = gamtab[colormap[i][2]];
451     }
452 }
453
454 void
455 rasterize(int interleaved, char* mode)
456 {
457     register unsigned long row;
458     unsigned char *newras;
459     unsigned char *ras;
460     TIFF *tif;
461     tstrip_t strip;
462     tsize_t stripsize;
463
464     if ((newras = (unsigned char*) _TIFFmalloc(width*height+EXTRAFUDGE)) == NULL) {
465         fprintf(stderr, "not enough memory for image\n");
466         return;
467     }
468 #define DRAWSEGMENT(offset, step) {                     \
469         for (row = offset; row < height; row += step) { \
470             _TIFFmemcpy(newras + row*width, ras, width);\
471             ras += width;                               \
472         }                                               \
473     }
474     ras = raster;
475     if (interleaved) {
476         DRAWSEGMENT(0, 8);
477         DRAWSEGMENT(4, 8);
478         DRAWSEGMENT(2, 4);
479         DRAWSEGMENT(1, 2);
480     } else 
481         DRAWSEGMENT(0, 1);
482 #undef DRAWSEGMENT
483
484     tif = TIFFOpen(imagename, mode);
485     if (!tif) {
486         TIFFError(imagename,"Can not open output image");
487         exit(-1);
488     }
489     TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (uint32) width);
490     TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (uint32) height);
491     TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
492     TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
493     TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
494     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
495     TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 
496         rowsperstrip = TIFFDefaultStripSize(tif, rowsperstrip));
497     TIFFSetField(tif, TIFFTAG_COMPRESSION, compression);
498     switch (compression) {
499     case COMPRESSION_LZW:
500     case COMPRESSION_DEFLATE:
501             if (predictor != 0)
502                     TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor);
503             break;
504     }
505     TIFFSetField(tif, TIFFTAG_COLORMAP, red, green, blue);
506     TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
507     strip = 0;
508     stripsize = TIFFStripSize(tif);
509     for (row=0; row<height; row += rowsperstrip) {
510         if (rowsperstrip > height-row) {
511             rowsperstrip = height-row;
512             stripsize = TIFFVStripSize(tif, rowsperstrip);
513         }
514         if (TIFFWriteEncodedStrip(tif, strip, newras+row*width, stripsize) < 0)
515             break;
516         strip++;
517     }
518     TIFFClose(tif);
519
520     _TIFFfree(newras);
521 }
522
523 /* vim: set ts=8 sts=8 sw=8 noet: */
524 /*
525  * Local Variables:
526  * mode: c
527  * c-basic-offset: 8
528  * fill-column: 78
529  * End:
530  */