~ubuntu-branches/ubuntu/karmic/tiff/karmic-security

« back to all changes in this revision

Viewing changes to tools/gif2tiff.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabio M. Di Nitto
  • Date: 2004-10-14 07:57:59 UTC
  • Revision ID: james.westby@ubuntu.com-20041014075759-a77e7zuaetya8cp0
Tags: upstream-3.6.1
ImportĀ upstreamĀ versionĀ 3.6.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Header: /cvsroot/osrs/libtiff/tools/gif2tiff.c,v 1.4 2003/03/12 14:05:05 dron 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 <stdio.h>
 
37
#include <stdlib.h>
 
38
#include <string.h>
 
39
#include <math.h>
 
40
 
 
41
#include "tiffio.h"
 
42
 
 
43
#if defined(_WINDOWS) || defined(MSDOS)
 
44
#define BINMODE "b"
 
45
#else
 
46
#define BINMODE
 
47
#endif
 
48
 
 
49
#define GIFGAMMA        (1.5)           /* smaller makes output img brighter */
 
50
#define IMAX            0xffff          /* max intensity value */
 
51
#define EXTRAFUDGE      128             /* some people write BAD .gif files */
 
52
 
 
53
#define streq(a,b)      (strcmp(a,b) == 0)
 
54
#define strneq(a,b,n)   (strncmp(a,b,n) == 0)
 
55
 
 
56
unsigned short gamtab[256];
 
57
 
 
58
void
 
59
makegamtab(float gam)
 
60
{
 
61
    int i;
 
62
 
 
63
    for(i=0; i<256; i++) 
 
64
        gamtab[i] = IMAX*pow(i/255.0,gam)+0.5;
 
65
}
 
66
 
 
67
char* stuff[] = {
 
68
"usage: gif2tiff [options] input.gif output.tif",
 
69
"where options are:",
 
70
" -r #          make each strip have no more than # rows",
 
71
"",
 
72
" -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
 
73
"               (no longer supported by default due to Unisys patent enforcement)", 
 
74
" -c zip[:opts] compress output with deflate encoding",
 
75
" -c packbits   compress output with packbits encoding",
 
76
" -c none       use no compression algorithm on output",
 
77
"",
 
78
"LZW and deflate options:",
 
79
" #             set predictor value",
 
80
"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
 
81
NULL
 
82
};
 
83
 
 
84
static void
 
85
usage(void)
 
86
{
 
87
        char buf[BUFSIZ];
 
88
        int i;
 
89
 
 
90
        setbuf(stderr, buf);
 
91
        fprintf(stderr, "%s\n\n", TIFFGetVersion());
 
92
        for (i = 0; stuff[i] != NULL; i++)
 
93
                fprintf(stderr, "%s\n", stuff[i]);
 
94
        exit(-1);
 
95
}
 
96
 
 
97
#define COLSIZE 256
 
98
 
 
99
unsigned char *stackp;
 
100
unsigned int prefix[4096];
 
101
unsigned char suffix[4096];
 
102
unsigned char stack[4096];
 
103
int datasize,codesize,codemask;     /* Decoder working variables */
 
104
int clear,eoi;                      /* Special code values */
 
105
int avail, oldcode;
 
106
 
 
107
FILE *infile;
 
108
int global;                        /* Is there a global color map? */
 
109
int globalbits;                     /* Number of bits of global colors */
 
110
unsigned char globalmap[COLSIZE][3];/* RGB values for global color map */
 
111
unsigned char *raster;              /* Decoded image data */
 
112
unsigned long width, height;
 
113
unsigned short red[COLSIZE];
 
114
unsigned short green[COLSIZE];
 
115
unsigned short blue[COLSIZE];
 
116
char *filename, *imagename;
 
117
 
 
118
static  uint16 compression = COMPRESSION_PACKBITS;
 
119
static  uint16 predictor = 0;
 
120
static  uint32 rowsperstrip = (uint32) -1;
 
121
static  int processCompressOptions(char*);
 
122
 
 
123
int     convert(void);
 
124
int     checksignature(void);
 
125
void    readscreen(void);
 
126
int     readgifimage(char*);
 
127
void    readextension(void);
 
128
int     readraster(void);
 
129
int     process(int, unsigned char**);
 
130
void    initcolors(unsigned char [COLSIZE][3], int);
 
131
void    rasterize(int, char*);
 
132
 
 
133
int
 
134
main(int argc, char* argv[])
 
135
{
 
136
    extern int optind;
 
137
    extern char *optarg;
 
138
    int c, status;
 
139
 
 
140
    while ((c = getopt(argc, argv, "c:r:")) != -1)
 
141
            switch (c) {
 
142
            case 'c':           /* compression scheme */
 
143
                    if (!processCompressOptions(optarg))
 
144
                            usage();
 
145
                    break;
 
146
            case 'r':           /* rows/strip */
 
147
                    rowsperstrip = atoi(optarg);
 
148
                    break;
 
149
            case '?':
 
150
                    usage();
 
151
                    /*NOTREACHED*/
 
152
            }
 
153
    if (argc - optind != 2)
 
154
            usage();
 
155
 
 
156
    makegamtab(GIFGAMMA);
 
157
    filename = argv[optind];
 
158
    imagename = argv[optind+1];
 
159
    if ((infile = fopen(imagename, "r" BINMODE)) != NULL) {
 
160
        int c;
 
161
        fclose(infile);
 
162
        printf("overwrite %s? ", imagename); fflush(stdout);
 
163
        c = getc(stdin);
 
164
        if (c != 'y' && c != 'Y')
 
165
            return (1);
 
166
    }
 
167
    if ((infile = fopen(filename, "r" BINMODE)) == NULL) {
 
168
        perror(filename);
 
169
        return (1);
 
170
    }
 
171
    status = convert();
 
172
    fclose(infile);
 
173
    return (status);
 
174
}
 
175
 
 
176
static int
 
177
processCompressOptions(char* opt)
 
178
{
 
179
        if (streq(opt, "none"))
 
180
                compression = COMPRESSION_NONE;
 
181
        else if (streq(opt, "packbits"))
 
182
                compression = COMPRESSION_PACKBITS;
 
183
        else if (strneq(opt, "lzw", 3)) {
 
184
                char* cp = strchr(opt, ':');
 
185
                if (cp)
 
186
                        predictor = atoi(cp+1);
 
187
                compression = COMPRESSION_LZW;
 
188
        } else if (strneq(opt, "zip", 3)) {
 
189
                char* cp = strchr(opt, ':');
 
190
                if (cp)
 
191
                        predictor = atoi(cp+1);
 
192
                compression = COMPRESSION_DEFLATE;
 
193
        } else
 
194
                return (0);
 
195
        return (1);
 
196
}
 
197
 
 
198
int
 
199
convert(void)
 
200
{
 
201
    int ch;
 
202
    char* mode = "w";
 
203
 
 
204
    if (!checksignature())
 
205
        return (-1);
 
206
    readscreen();
 
207
    while ((ch = getc(infile)) != ';' && ch != EOF) {
 
208
        switch (ch) {
 
209
            case '\0':  break;  /* this kludge for non-standard files */
 
210
            case ',':   if (!readgifimage(mode))
 
211
                           return (-1);
 
212
                        mode = "a";             /* subsequent images append */
 
213
                        break;
 
214
            case '!':   readextension();
 
215
                        break;
 
216
            default:    fprintf(stderr, "illegal GIF block type\n");
 
217
                        return (-1);
 
218
        }
 
219
    }
 
220
    return (0);
 
221
}
 
222
 
 
223
int
 
224
checksignature(void)
 
225
{
 
226
    char buf[6];
 
227
 
 
228
    fread(buf,1,6,infile);
 
229
    if (strncmp(buf,"GIF",3)) {
 
230
        fprintf(stderr, "file is not a GIF file\n");
 
231
        return 0;
 
232
    }
 
233
    if (strncmp(&buf[3],"87a",3)) {
 
234
        fprintf(stderr, "unknown GIF version number\n");
 
235
        return 0;
 
236
    }
 
237
    return 1;
 
238
}
 
239
 
 
240
/*
 
241
 *      readscreen - 
 
242
 *              Get information which is global to all the images stored 
 
243
 *      in the file
 
244
 */
 
245
void
 
246
readscreen(void)
 
247
{
 
248
    unsigned char buf[7];
 
249
 
 
250
    fread(buf,1,7,infile);
 
251
    global = buf[4] & 0x80;
 
252
    if (global) {
 
253
        globalbits = (buf[4] & 0x07) + 1;
 
254
        fread(globalmap,3,1<<globalbits,infile);
 
255
    }
 
256
}
 
257
 
 
258
int
 
259
readgifimage(char* mode)
 
260
{
 
261
    unsigned char buf[9];
 
262
    int local, interleaved;
 
263
    unsigned char localmap[256][3];
 
264
    int localbits;
 
265
    int status;
 
266
 
 
267
    if (fread(buf, 1, 9, infile) == 0) {
 
268
        perror(filename);
 
269
        return (0);
 
270
    }
 
271
    width = buf[4] + (buf[5] << 8);
 
272
    height = buf[6] + (buf[7] << 8);
 
273
    local = buf[8] & 0x80;
 
274
    interleaved = buf[8] & 0x40;
 
275
 
 
276
    if (local == 0 && global == 0) {
 
277
        fprintf(stderr, "no colormap present for image\n");
 
278
        return (0);
 
279
    }
 
280
    if ((raster = (unsigned char*) _TIFFmalloc(width*height+EXTRAFUDGE)) == NULL) {
 
281
        fprintf(stderr, "not enough memory for image\n");
 
282
        return (0);
 
283
    }
 
284
    if (local) {
 
285
        localbits = (buf[8] & 0x7) + 1;
 
286
 
 
287
        fprintf(stderr, "   local colors: %d\n", 1<<localbits);
 
288
 
 
289
        fread(localmap, 3, 1<<localbits, infile);
 
290
        initcolors(localmap, 1<<localbits);
 
291
    } else if (global) {
 
292
        initcolors(globalmap, 1<<globalbits);
 
293
    }
 
294
    if (status = readraster())
 
295
        rasterize(interleaved, mode);
 
296
    _TIFFfree(raster);
 
297
    return status;
 
298
}
 
299
 
 
300
/*
 
301
 *      readextension -
 
302
 *              Read a GIF extension block (and do nothing with it).
 
303
 *
 
304
 */
 
305
void
 
306
readextension(void)
 
307
{
 
308
    int count;
 
309
    char buf[255];
 
310
 
 
311
    (void) getc(infile);
 
312
    while (count = getc(infile))
 
313
        fread(buf, 1, count, infile);
 
314
}
 
315
 
 
316
/*
 
317
 *      readraster -
 
318
 *              Decode a raster image
 
319
 *
 
320
 */
 
321
int
 
322
readraster(void)
 
323
{
 
324
    unsigned char *fill = raster;
 
325
    unsigned char buf[255];
 
326
    register int bits=0;
 
327
    register unsigned long datum=0;
 
328
    register unsigned char *ch;
 
329
    register int count, code;
 
330
    int status = 1;
 
331
 
 
332
    datasize = getc(infile);
 
333
    clear = 1 << datasize;
 
334
    eoi = clear + 1;
 
335
    avail = clear + 2;
 
336
    oldcode = -1;
 
337
    codesize = datasize + 1;
 
338
    codemask = (1 << codesize) - 1;
 
339
    for (code = 0; code < clear; code++) {
 
340
        prefix[code] = 0;
 
341
        suffix[code] = code;
 
342
    }
 
343
    stackp = stack;
 
344
    for (count = getc(infile); count > 0; count = getc(infile)) {
 
345
        fread(buf,1,count,infile);
 
346
        for (ch=buf; count-- > 0; ch++) {
 
347
            datum += (unsigned long) *ch << bits;
 
348
            bits += 8;
 
349
            while (bits >= codesize) {
 
350
                code = datum & codemask;
 
351
                datum >>= codesize;
 
352
                bits -= codesize;
 
353
                if (code == eoi) {               /* This kludge put in */
 
354
                    goto exitloop;               /* because some GIF files*/
 
355
                }                                /* aren't standard */
 
356
                if (!process(code, &fill)) {
 
357
                    status = 0;
 
358
                    goto exitloop;
 
359
                }
 
360
            }
 
361
        }
 
362
        if (fill >= raster + width*height) {
 
363
            fprintf(stderr, "raster full before eoi code\n");
 
364
            break;
 
365
        }
 
366
    }
 
367
exitloop:
 
368
    if (fill != raster + width*height)  {
 
369
        fprintf(stderr, "warning: wrong rastersize: %ld bytes\n",
 
370
                                                      (long) (fill-raster));
 
371
        fprintf(stderr, "         instead of %ld bytes\n",
 
372
                                                      (long) width*height);
 
373
    }
 
374
    return status;
 
375
}
 
376
 
 
377
/*
 
378
 *      process - 
 
379
 *              Process a compression code.  "clear" resets the code table.  
 
380
 *      Otherwise make a new code table entry, and output the bytes 
 
381
 *      associated with the code.
 
382
 */
 
383
int
 
384
process(register int code, unsigned char** fill)
 
385
{
 
386
    int incode;
 
387
    static unsigned char firstchar;
 
388
 
 
389
    if (code == clear) {
 
390
        codesize = datasize + 1;
 
391
        codemask = (1 << codesize) - 1;
 
392
        avail = clear + 2;
 
393
        oldcode = -1;
 
394
        return 1;
 
395
    }
 
396
 
 
397
    if (oldcode == -1) {
 
398
        *(*fill)++ = suffix[code];
 
399
        firstchar = oldcode = code;
 
400
        return 1;
 
401
    }
 
402
    if (code > avail) {
 
403
        fprintf(stderr, "code %d too large for %d\n", code, avail);
 
404
        return 0; 
 
405
    }
 
406
 
 
407
    incode = code;
 
408
    if (code == avail) {      /* the first code is always < avail */
 
409
        *stackp++ = firstchar;
 
410
        code = oldcode;
 
411
    }
 
412
    while (code > clear) {
 
413
        *stackp++ = suffix[code];
 
414
        code = prefix[code];
 
415
    }
 
416
 
 
417
    *stackp++ = firstchar = suffix[code];
 
418
    prefix[avail] = oldcode;
 
419
    suffix[avail] = firstchar;
 
420
    avail++;
 
421
 
 
422
    if (((avail & codemask) == 0) && (avail < 4096)) {
 
423
        codesize++;
 
424
        codemask += avail;
 
425
    }
 
426
    oldcode = incode;
 
427
    do {
 
428
        *(*fill)++ = *--stackp;
 
429
    } while (stackp > stack);
 
430
    return 1;
 
431
}
 
432
 
 
433
/*
 
434
 *      initcolors -
 
435
 *              Convert a color map (local or global) to arrays with R, G and B
 
436
 *      values. 
 
437
 *
 
438
 */
 
439
void
 
440
initcolors(unsigned char colormap[COLSIZE][3], int ncolors)
 
441
{
 
442
    register int i;
 
443
 
 
444
    for (i = 0; i < ncolors; i++) {
 
445
        red[i]   = gamtab[colormap[i][0]];
 
446
        green[i] = gamtab[colormap[i][1]];
 
447
        blue[i]  = gamtab[colormap[i][2]];
 
448
    }
 
449
}
 
450
 
 
451
void
 
452
rasterize(int interleaved, char* mode)
 
453
{
 
454
    register long row;
 
455
    unsigned char *newras;
 
456
    unsigned char *ras;
 
457
    TIFF *tif;
 
458
    tstrip_t strip;
 
459
    tsize_t stripsize;
 
460
 
 
461
    if ((newras = (unsigned char*) _TIFFmalloc(width*height+EXTRAFUDGE)) == NULL) {
 
462
        fprintf(stderr, "not enough memory for image\n");
 
463
        return;
 
464
    }
 
465
#define DRAWSEGMENT(offset, step) {                     \
 
466
        for (row = offset; row < height; row += step) { \
 
467
            _TIFFmemcpy(newras + row*width, ras, width);\
 
468
            ras += width;                               \
 
469
        }                                               \
 
470
    }
 
471
    ras = raster;
 
472
    if (interleaved) {
 
473
        DRAWSEGMENT(0, 8);
 
474
        DRAWSEGMENT(4, 8);
 
475
        DRAWSEGMENT(2, 4);
 
476
        DRAWSEGMENT(1, 2);
 
477
    } else 
 
478
        DRAWSEGMENT(0, 1);
 
479
#undef DRAWSEGMENT
 
480
 
 
481
    tif = TIFFOpen(imagename, mode);
 
482
    if (!tif) {
 
483
        TIFFError(imagename,"Can not open output image");
 
484
        exit(-1);
 
485
    }
 
486
    TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (uint32) width);
 
487
    TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (uint32) height);
 
488
    TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
 
489
    TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
 
490
    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
 
491
    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
 
492
    TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 
 
493
        rowsperstrip = TIFFDefaultStripSize(tif, rowsperstrip));
 
494
    TIFFSetField(tif, TIFFTAG_COMPRESSION, compression);
 
495
    switch (compression) {
 
496
    case COMPRESSION_LZW:
 
497
    case COMPRESSION_DEFLATE:
 
498
            if (predictor != 0)
 
499
                    TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor);
 
500
            break;
 
501
    }
 
502
    TIFFSetField(tif, TIFFTAG_COLORMAP, red, green, blue);
 
503
    TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
 
504
    strip = 0;
 
505
    stripsize = TIFFStripSize(tif);
 
506
    for (row=0; row<height; row += rowsperstrip) {
 
507
        if (TIFFWriteEncodedStrip(tif, strip, newras+row*width, stripsize) < 0)
 
508
            break;
 
509
        strip++;
 
510
    }
 
511
    TIFFClose(tif);
 
512
 
 
513
    _TIFFfree(newras);
 
514