~ubuntu-branches/ubuntu/dapper/tiff/dapper-updates

« back to all changes in this revision

Viewing changes to tools/gif2tiff.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2005-11-09 18:21:15 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20051109182115-v0fd3zcbrq2sq6u4
Tags: 3.7.4-1ubuntu1
* Synchronize to Debian.
* Only change left: xlibmesa-gl-dev -> libgl1-mesa-dev build dependency
  change.

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