]>
git.saurik.com Git - wxWidgets.git/blob - src/tiff/tools/gif2tiff.c
3 * Copyright (c) 1990-1997 Sam Leffler
4 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
6 * Permission to use, copy, modify, distribute, and sell this software and
7 * its documentation for any purpose is hereby granted without fee, provided
8 * that (i) the above copyright notices and this permission notice appear in
9 * all copies of the software and related documentation, and (ii) the names of
10 * Sam Leffler and Silicon Graphics may not be used in any advertising or
11 * publicity relating to the software without the specific, prior written
12 * permission of Sam Leffler and Silicon Graphics.
14 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
16 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
19 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
20 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
21 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
22 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
27 * convert a GIF file into a TIFF file.
28 * based on Paul Haeberli's fromgif program which in turn is
29 * based on a GIF file reader by Marcel J.E. Mol March 23 1989
31 * if input is 320 by 200 pixel aspect is probably 1.2
32 * if input is 640 350 pixel aspect is probably 1.37
35 #include "tif_config.h"
52 #define GIFGAMMA (1.5) /* smaller makes output img brighter */
53 #define IMAX 0xffff /* max intensity value */
54 #define EXTRAFUDGE 128 /* some people write BAD .gif files */
56 #define streq(a,b) (strcmp(a,b) == 0)
57 #define strneq(a,b,n) (strncmp(a,b,n) == 0)
59 unsigned short gamtab
[256];
67 gamtab
[i
] = (unsigned short) (IMAX
*pow(i
/255.0,gam
)+0.5);
71 "usage: gif2tiff [options] input.gif output.tif",
73 " -r # make each strip have no more than # rows",
75 " -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
76 " -c zip[:opts] compress output with deflate encoding",
77 " -c packbits compress output with packbits encoding",
78 " -c none use no compression algorithm on output",
80 "LZW and deflate options:",
81 " # set predictor value",
82 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
93 fprintf(stderr
, "%s\n\n", TIFFGetVersion());
94 for (i
= 0; stuff
[i
] != NULL
; i
++)
95 fprintf(stderr
, "%s\n", stuff
[i
]);
101 unsigned char *stackp
;
102 unsigned int prefix
[4096];
103 unsigned char suffix
[4096];
104 unsigned char stack
[4096];
105 int datasize
,codesize
,codemask
; /* Decoder working variables */
106 int clear
,eoi
; /* Special code values */
110 int global
; /* Is there a global color map? */
111 int globalbits
; /* Number of bits of global colors */
112 unsigned char globalmap
[COLSIZE
][3];/* RGB values for global color map */
113 unsigned char *raster
; /* Decoded image data */
114 unsigned long width
, height
;
115 unsigned short red
[COLSIZE
];
116 unsigned short green
[COLSIZE
];
117 unsigned short blue
[COLSIZE
];
118 char *filename
, *imagename
;
120 static uint16 compression
= COMPRESSION_PACKBITS
;
121 static uint16 predictor
= 0;
122 static uint32 rowsperstrip
= (uint32
) -1;
123 static int processCompressOptions(char*);
126 int checksignature(void);
127 void readscreen(void);
128 int readgifimage(char*);
129 void readextension(void);
130 int readraster(void);
131 int process(int, unsigned char**);
132 void initcolors(unsigned char [COLSIZE
][3], int);
133 void rasterize(int, char*);
136 main(int argc
, char* argv
[])
142 while ((c
= getopt(argc
, argv
, "c:r:")) != -1)
144 case 'c': /* compression scheme */
145 if (!processCompressOptions(optarg
))
148 case 'r': /* rows/strip */
149 rowsperstrip
= atoi(optarg
);
155 if (argc
- optind
!= 2)
158 makegamtab(GIFGAMMA
);
159 filename
= argv
[optind
];
160 imagename
= argv
[optind
+1];
161 if ((infile
= fopen(imagename
, "rb")) != NULL
) {
164 printf("overwrite %s? ", imagename
); fflush(stdout
);
166 if (c
!= 'y' && c
!= 'Y')
169 if ((infile
= fopen(filename
, "rb")) == NULL
) {
179 processCompressOptions(char* opt
)
181 if (streq(opt
, "none"))
182 compression
= COMPRESSION_NONE
;
183 else if (streq(opt
, "packbits"))
184 compression
= COMPRESSION_PACKBITS
;
185 else if (strneq(opt
, "lzw", 3)) {
186 char* cp
= strchr(opt
, ':');
188 predictor
= atoi(cp
+1);
189 compression
= COMPRESSION_LZW
;
190 } else if (strneq(opt
, "zip", 3)) {
191 char* cp
= strchr(opt
, ':');
193 predictor
= atoi(cp
+1);
194 compression
= COMPRESSION_DEFLATE
;
206 if (!checksignature())
209 while ((ch
= getc(infile
)) != ';' && ch
!= EOF
) {
211 case '\0': break; /* this kludge for non-standard files */
212 case ',': if (!readgifimage(mode
))
214 mode
= "a"; /* subsequent images append */
216 case '!': readextension();
218 default: fprintf(stderr
, "illegal GIF block type\n");
230 fread(buf
,1,6,infile
);
231 if (strncmp(buf
,"GIF",3)) {
232 fprintf(stderr
, "file is not a GIF file\n");
235 if (strncmp(&buf
[3],"87a",3)) {
236 fprintf(stderr
, "unknown GIF version number\n");
244 * Get information which is global to all the images stored
250 unsigned char buf
[7];
252 fread(buf
,1,7,infile
);
253 global
= buf
[4] & 0x80;
255 globalbits
= (buf
[4] & 0x07) + 1;
256 fread(globalmap
,3,((size_t)1)<<globalbits
,infile
);
261 readgifimage(char* mode
)
263 unsigned char buf
[9];
264 int local
, interleaved
;
265 unsigned char localmap
[256][3];
269 if (fread(buf
, 1, 9, infile
) == 0) {
273 width
= buf
[4] + (buf
[5] << 8);
274 height
= buf
[6] + (buf
[7] << 8);
275 local
= buf
[8] & 0x80;
276 interleaved
= buf
[8] & 0x40;
278 if (local
== 0 && global
== 0) {
279 fprintf(stderr
, "no colormap present for image\n");
282 if ((raster
= (unsigned char*) _TIFFmalloc(width
*height
+EXTRAFUDGE
)) == NULL
) {
283 fprintf(stderr
, "not enough memory for image\n");
287 localbits
= (buf
[8] & 0x7) + 1;
289 fprintf(stderr
, " local colors: %d\n", 1<<localbits
);
291 fread(localmap
, 3, ((size_t)1)<<localbits
, infile
);
292 initcolors(localmap
, 1<<localbits
);
294 initcolors(globalmap
, 1<<globalbits
);
296 if ((status
= readraster()))
297 rasterize(interleaved
, mode
);
304 * Read a GIF extension block (and do nothing with it).
314 while ((count
= getc(infile
)))
315 fread(buf
, 1, count
, infile
);
320 * Decode a raster image
326 unsigned char *fill
= raster
;
327 unsigned char buf
[255];
329 register unsigned long datum
=0;
330 register unsigned char *ch
;
331 register int count
, code
;
334 datasize
= getc(infile
);
335 clear
= 1 << datasize
;
339 codesize
= datasize
+ 1;
340 codemask
= (1 << codesize
) - 1;
341 for (code
= 0; code
< clear
; code
++) {
346 for (count
= getc(infile
); count
> 0; count
= getc(infile
)) {
347 fread(buf
,1,count
,infile
);
348 for (ch
=buf
; count
-- > 0; ch
++) {
349 datum
+= (unsigned long) *ch
<< bits
;
351 while (bits
>= codesize
) {
352 code
= datum
& codemask
;
355 if (code
== eoi
) { /* This kludge put in */
356 goto exitloop
; /* because some GIF files*/
357 } /* aren't standard */
358 if (!process(code
, &fill
)) {
364 if (fill
>= raster
+ width
*height
) {
365 fprintf(stderr
, "raster full before eoi code\n");
370 if (fill
!= raster
+ width
*height
) {
371 fprintf(stderr
, "warning: wrong rastersize: %ld bytes\n",
372 (long) (fill
-raster
));
373 fprintf(stderr
, " instead of %ld bytes\n",
374 (long) width
*height
);
381 * Process a compression code. "clear" resets the code table.
382 * Otherwise make a new code table entry, and output the bytes
383 * associated with the code.
386 process(register int code
, unsigned char** fill
)
389 static unsigned char firstchar
;
392 codesize
= datasize
+ 1;
393 codemask
= (1 << codesize
) - 1;
400 *(*fill
)++ = suffix
[code
];
401 firstchar
= oldcode
= code
;
405 fprintf(stderr
, "code %d too large for %d\n", code
, avail
);
410 if (code
== avail
) { /* the first code is always < avail */
411 *stackp
++ = firstchar
;
414 while (code
> clear
) {
415 *stackp
++ = suffix
[code
];
419 *stackp
++ = firstchar
= suffix
[code
];
420 prefix
[avail
] = oldcode
;
421 suffix
[avail
] = firstchar
;
424 if (((avail
& codemask
) == 0) && (avail
< 4096)) {
430 *(*fill
)++ = *--stackp
;
431 } while (stackp
> stack
);
437 * Convert a color map (local or global) to arrays with R, G and B
442 initcolors(unsigned char colormap
[COLSIZE
][3], int ncolors
)
446 for (i
= 0; i
< ncolors
; i
++) {
447 red
[i
] = gamtab
[colormap
[i
][0]];
448 green
[i
] = gamtab
[colormap
[i
][1]];
449 blue
[i
] = gamtab
[colormap
[i
][2]];
454 rasterize(int interleaved
, char* mode
)
456 register unsigned long row
;
457 unsigned char *newras
;
463 if ((newras
= (unsigned char*) _TIFFmalloc(width
*height
+EXTRAFUDGE
)) == NULL
) {
464 fprintf(stderr
, "not enough memory for image\n");
467 #define DRAWSEGMENT(offset, step) { \
468 for (row = offset; row < height; row += step) { \
469 _TIFFmemcpy(newras + row*width, ras, width);\
483 tif
= TIFFOpen(imagename
, mode
);
485 TIFFError(imagename
,"Can not open output image");
488 TIFFSetField(tif
, TIFFTAG_IMAGEWIDTH
, (uint32
) width
);
489 TIFFSetField(tif
, TIFFTAG_IMAGELENGTH
, (uint32
) height
);
490 TIFFSetField(tif
, TIFFTAG_PHOTOMETRIC
, PHOTOMETRIC_PALETTE
);
491 TIFFSetField(tif
, TIFFTAG_PLANARCONFIG
, PLANARCONFIG_CONTIG
);
492 TIFFSetField(tif
, TIFFTAG_SAMPLESPERPIXEL
, 1);
493 TIFFSetField(tif
, TIFFTAG_BITSPERSAMPLE
, 8);
494 TIFFSetField(tif
, TIFFTAG_ROWSPERSTRIP
,
495 rowsperstrip
= TIFFDefaultStripSize(tif
, rowsperstrip
));
496 TIFFSetField(tif
, TIFFTAG_COMPRESSION
, compression
);
497 switch (compression
) {
498 case COMPRESSION_LZW
:
499 case COMPRESSION_DEFLATE
:
501 TIFFSetField(tif
, TIFFTAG_PREDICTOR
, predictor
);
504 TIFFSetField(tif
, TIFFTAG_COLORMAP
, red
, green
, blue
);
505 TIFFSetField(tif
, TIFFTAG_ORIENTATION
, ORIENTATION_TOPLEFT
);
507 stripsize
= TIFFStripSize(tif
);
508 for (row
=0; row
<height
; row
+= rowsperstrip
) {
509 if (rowsperstrip
> height
-row
) {
510 rowsperstrip
= height
-row
;
511 stripsize
= TIFFVStripSize(tif
, rowsperstrip
);
513 if (TIFFWriteEncodedStrip(tif
, strip
, newras
+row
*width
, stripsize
) < 0)
522 /* vim: set ts=8 sts=8 sw=8 noet: */