~ubuntu-branches/ubuntu/precise/tiff/precise-security

« back to all changes in this revision

Viewing changes to .pc/CVE-2014-81xx-7.patch/tools/thumbnail.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2015-03-30 08:11:18 UTC
  • Revision ID: package-import@ubuntu.com-20150330081118-bvaoaii1act27voq
Tags: 3.9.5-2ubuntu1.7
* SECURITY UPDATE: Fix multiple security issues
  - debian/patches/CVE-2014-81xx-1.patch to CVE-2014-81xx-11.patch
  - debian/patches/CVE-2014-8128-5.patch
  - debian/patches/CVE-2014-9655-1.patch to CVE-2014-9655-3.patch
  - debian/patches/read_overrun.patch
  - debian/patches/CVE-2014-8130.patch
  - CVE-2014-8127 (partially)
  - CVE-2014-8128
  - CVE-2014-8129
  - CVE-2014-8130
  - CVE-2014-9330
  - CVE-2014-9655

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: thumbnail.c,v 1.9.2.2 2010-07-02 12:03:27 dron Exp $ */
 
2
 
 
3
/*
 
4
 * Copyright (c) 1994-1997 Sam Leffler
 
5
 * Copyright (c) 1994-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
#include "tif_config.h"
 
28
 
 
29
#include <stdio.h>
 
30
#include <stdlib.h>
 
31
#include <string.h>
 
32
#include <math.h>
 
33
 
 
34
#ifdef HAVE_UNISTD_H
 
35
# include <unistd.h>
 
36
#endif
 
37
 
 
38
#include "tiffio.h"
 
39
 
 
40
#ifndef HAVE_GETOPT
 
41
extern int getopt(int, char**, char*);
 
42
#endif
 
43
 
 
44
#define streq(a,b)      (strcmp(a,b) == 0)
 
45
 
 
46
#ifndef TIFFhowmany8
 
47
# define TIFFhowmany8(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3)
 
48
#endif
 
49
 
 
50
typedef enum {
 
51
    EXP50,
 
52
    EXP60,
 
53
    EXP70,
 
54
    EXP80,
 
55
    EXP90,
 
56
    EXP,
 
57
    LINEAR
 
58
} Contrast;
 
59
 
 
60
static  uint32 tnw = 216;               /* thumbnail width */
 
61
static  uint32 tnh = 274;               /* thumbnail height */
 
62
static  Contrast contrast = LINEAR;     /* current contrast */
 
63
static  uint8* thumbnail;
 
64
 
 
65
static  int cpIFD(TIFF*, TIFF*);
 
66
static  int generateThumbnail(TIFF*, TIFF*);
 
67
static  void initScale();
 
68
static  void usage(void);
 
69
 
 
70
extern  char* optarg;
 
71
extern  int optind;
 
72
 
 
73
int
 
74
main(int argc, char* argv[])
 
75
{
 
76
    TIFF* in;
 
77
    TIFF* out;
 
78
    int c;
 
79
 
 
80
    while ((c = getopt(argc, argv, "w:h:c:")) != -1) {
 
81
        switch (c) {
 
82
        case 'w':       tnw = strtoul(optarg, NULL, 0); break;
 
83
        case 'h':       tnh = strtoul(optarg, NULL, 0); break;
 
84
        case 'c':       contrast = streq(optarg, "exp50") ? EXP50 :
 
85
                                   streq(optarg, "exp60") ? EXP60 :
 
86
                                   streq(optarg, "exp70") ? EXP70 :
 
87
                                   streq(optarg, "exp80") ? EXP80 :
 
88
                                   streq(optarg, "exp90") ? EXP90 :
 
89
                                   streq(optarg, "exp")   ? EXP :
 
90
                                   streq(optarg, "linear")? LINEAR :
 
91
                                                            EXP;
 
92
                        break;
 
93
        default:        usage();
 
94
        }
 
95
    }
 
96
    if (argc-optind != 2)
 
97
        usage();
 
98
 
 
99
    out = TIFFOpen(argv[optind+1], "w");
 
100
    if (out == NULL)
 
101
        return 2;
 
102
    in = TIFFOpen(argv[optind], "r");
 
103
 
 
104
    thumbnail = (uint8*) _TIFFmalloc(tnw * tnh);
 
105
    if (!thumbnail) {
 
106
            TIFFError(TIFFFileName(in),
 
107
                      "Can't allocate space for thumbnail buffer.");
 
108
            return 1;
 
109
    }
 
110
 
 
111
    if (in != NULL) {
 
112
        initScale();
 
113
        do {
 
114
            if (!generateThumbnail(in, out))
 
115
                goto bad;
 
116
            if (!cpIFD(in, out) || !TIFFWriteDirectory(out))
 
117
                goto bad;
 
118
        } while (TIFFReadDirectory(in));
 
119
        (void) TIFFClose(in);
 
120
    }
 
121
    (void) TIFFClose(out);
 
122
    return 0;
 
123
bad:
 
124
    (void) TIFFClose(out);
 
125
    return 1;
 
126
}
 
127
 
 
128
#define CopyField(tag, v) \
 
129
    if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
 
130
#define CopyField2(tag, v1, v2) \
 
131
    if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
 
132
#define CopyField3(tag, v1, v2, v3) \
 
133
    if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
 
134
#define CopyField4(tag, v1, v2, v3, v4) \
 
135
    if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4)
 
136
 
 
137
static void
 
138
cpTag(TIFF* in, TIFF* out, uint16 tag, uint16 count, TIFFDataType type)
 
139
{
 
140
        switch (type) {
 
141
        case TIFF_SHORT:
 
142
                if (count == 1) {
 
143
                        uint16 shortv;
 
144
                        CopyField(tag, shortv);
 
145
                } else if (count == 2) {
 
146
                        uint16 shortv1, shortv2;
 
147
                        CopyField2(tag, shortv1, shortv2);
 
148
                } else if (count == 4) {
 
149
                        uint16 *tr, *tg, *tb, *ta;
 
150
                        CopyField4(tag, tr, tg, tb, ta);
 
151
                } else if (count == (uint16) -1) {
 
152
                        uint16 shortv1;
 
153
                        uint16* shortav;
 
154
                        CopyField2(tag, shortv1, shortav);
 
155
                }
 
156
                break;
 
157
        case TIFF_LONG:
 
158
                { uint32 longv;
 
159
                  CopyField(tag, longv);
 
160
                }
 
161
                break;
 
162
        case TIFF_RATIONAL:
 
163
                if (count == 1) {
 
164
                        float floatv;
 
165
                        CopyField(tag, floatv);
 
166
                } else if (count == (uint16) -1) {
 
167
                        float* floatav;
 
168
                        CopyField(tag, floatav);
 
169
                }
 
170
                break;
 
171
        case TIFF_ASCII:
 
172
                { char* stringv;
 
173
                  CopyField(tag, stringv);
 
174
                }
 
175
                break;
 
176
        case TIFF_DOUBLE:
 
177
                if (count == 1) {
 
178
                        double doublev;
 
179
                        CopyField(tag, doublev);
 
180
                } else if (count == (uint16) -1) {
 
181
                        double* doubleav;
 
182
                        CopyField(tag, doubleav);
 
183
                }
 
184
                break;
 
185
          default:
 
186
                TIFFError(TIFFFileName(in),
 
187
                          "Data type %d is not supported, tag %d skipped.",
 
188
                          tag, type);
 
189
        }
 
190
}
 
191
 
 
192
#undef CopyField4
 
193
#undef CopyField3
 
194
#undef CopyField2
 
195
#undef CopyField
 
196
 
 
197
static struct cpTag {
 
198
    uint16      tag;
 
199
    uint16      count;
 
200
    TIFFDataType type;
 
201
} tags[] = {
 
202
    { TIFFTAG_IMAGEWIDTH,               1, TIFF_LONG },
 
203
    { TIFFTAG_IMAGELENGTH,              1, TIFF_LONG },
 
204
    { TIFFTAG_BITSPERSAMPLE,            1, TIFF_SHORT },
 
205
    { TIFFTAG_COMPRESSION,              1, TIFF_SHORT },
 
206
    { TIFFTAG_FILLORDER,                1, TIFF_SHORT },
 
207
    { TIFFTAG_SAMPLESPERPIXEL,          1, TIFF_SHORT },
 
208
    { TIFFTAG_ROWSPERSTRIP,             1, TIFF_LONG },
 
209
    { TIFFTAG_PLANARCONFIG,             1, TIFF_SHORT },
 
210
    { TIFFTAG_GROUP3OPTIONS,            1, TIFF_LONG },
 
211
    { TIFFTAG_SUBFILETYPE,              1, TIFF_LONG },
 
212
    { TIFFTAG_PHOTOMETRIC,              1, TIFF_SHORT },
 
213
    { TIFFTAG_THRESHHOLDING,            1, TIFF_SHORT },
 
214
    { TIFFTAG_DOCUMENTNAME,             1, TIFF_ASCII },
 
215
    { TIFFTAG_IMAGEDESCRIPTION,         1, TIFF_ASCII },
 
216
    { TIFFTAG_MAKE,                     1, TIFF_ASCII },
 
217
    { TIFFTAG_MODEL,                    1, TIFF_ASCII },
 
218
    { TIFFTAG_ORIENTATION,              1, TIFF_SHORT },
 
219
    { TIFFTAG_MINSAMPLEVALUE,           1, TIFF_SHORT },
 
220
    { TIFFTAG_MAXSAMPLEVALUE,           1, TIFF_SHORT },
 
221
    { TIFFTAG_XRESOLUTION,              1, TIFF_RATIONAL },
 
222
    { TIFFTAG_YRESOLUTION,              1, TIFF_RATIONAL },
 
223
    { TIFFTAG_PAGENAME,                 1, TIFF_ASCII },
 
224
    { TIFFTAG_XPOSITION,                1, TIFF_RATIONAL },
 
225
    { TIFFTAG_YPOSITION,                1, TIFF_RATIONAL },
 
226
    { TIFFTAG_GROUP4OPTIONS,            1, TIFF_LONG },
 
227
    { TIFFTAG_RESOLUTIONUNIT,           1, TIFF_SHORT },
 
228
    { TIFFTAG_PAGENUMBER,               2, TIFF_SHORT },
 
229
    { TIFFTAG_SOFTWARE,                 1, TIFF_ASCII },
 
230
    { TIFFTAG_DATETIME,                 1, TIFF_ASCII },
 
231
    { TIFFTAG_ARTIST,                   1, TIFF_ASCII },
 
232
    { TIFFTAG_HOSTCOMPUTER,             1, TIFF_ASCII },
 
233
    { TIFFTAG_WHITEPOINT,               2, TIFF_RATIONAL },
 
234
    { TIFFTAG_PRIMARYCHROMATICITIES,    (uint16) -1,TIFF_RATIONAL },
 
235
    { TIFFTAG_HALFTONEHINTS,            2, TIFF_SHORT },
 
236
    { TIFFTAG_BADFAXLINES,              1, TIFF_LONG },
 
237
    { TIFFTAG_CLEANFAXDATA,             1, TIFF_SHORT },
 
238
    { TIFFTAG_CONSECUTIVEBADFAXLINES,   1, TIFF_LONG },
 
239
    { TIFFTAG_INKSET,                   1, TIFF_SHORT },
 
240
    { TIFFTAG_INKNAMES,                 1, TIFF_ASCII },
 
241
    { TIFFTAG_DOTRANGE,                 2, TIFF_SHORT },
 
242
    { TIFFTAG_TARGETPRINTER,            1, TIFF_ASCII },
 
243
    { TIFFTAG_SAMPLEFORMAT,             1, TIFF_SHORT },
 
244
    { TIFFTAG_YCBCRCOEFFICIENTS,        (uint16) -1,TIFF_RATIONAL },
 
245
    { TIFFTAG_YCBCRSUBSAMPLING,         2, TIFF_SHORT },
 
246
    { TIFFTAG_YCBCRPOSITIONING,         1, TIFF_SHORT },
 
247
    { TIFFTAG_REFERENCEBLACKWHITE,      (uint16) -1,TIFF_RATIONAL },
 
248
    { TIFFTAG_EXTRASAMPLES,             (uint16) -1, TIFF_SHORT },
 
249
};
 
250
#define NTAGS   (sizeof (tags) / sizeof (tags[0]))
 
251
 
 
252
static void
 
253
cpTags(TIFF* in, TIFF* out)
 
254
{
 
255
    struct cpTag *p;
 
256
    for (p = tags; p < &tags[NTAGS]; p++)
 
257
        {
 
258
                /* Horrible: but TIFFGetField() expects 2 arguments to be passed */
 
259
                /* if we request a tag that is defined in a codec, but that codec */
 
260
                /* isn't used */
 
261
                if( p->tag == TIFFTAG_GROUP3OPTIONS )
 
262
                {
 
263
                        uint16 compression;
 
264
                        if( !TIFFGetField(in, TIFFTAG_COMPRESSION, &compression) ||
 
265
                                compression != COMPRESSION_CCITTFAX3 )
 
266
                                continue;
 
267
                }
 
268
                if( p->tag == TIFFTAG_GROUP4OPTIONS )
 
269
                {
 
270
                        uint16 compression;
 
271
                        if( !TIFFGetField(in, TIFFTAG_COMPRESSION, &compression) ||
 
272
                                compression != COMPRESSION_CCITTFAX4 )
 
273
                                continue;
 
274
                }
 
275
                cpTag(in, out, p->tag, p->count, p->type);
 
276
        }
 
277
}
 
278
#undef NTAGS
 
279
 
 
280
static int
 
281
cpStrips(TIFF* in, TIFF* out)
 
282
{
 
283
    tsize_t bufsize  = TIFFStripSize(in);
 
284
    unsigned char *buf = (unsigned char *)_TIFFmalloc(bufsize);
 
285
 
 
286
    if (buf) {
 
287
        tstrip_t s, ns = TIFFNumberOfStrips(in);
 
288
        tsize_t *bytecounts;
 
289
 
 
290
        TIFFGetField(in, TIFFTAG_STRIPBYTECOUNTS, &bytecounts);
 
291
        for (s = 0; s < ns; s++) {
 
292
            if (bytecounts[s] > bufsize) {
 
293
                buf = (unsigned char *)_TIFFrealloc(buf, bytecounts[s]);
 
294
                if (!buf)
 
295
                    goto bad;
 
296
                bufsize = bytecounts[s];
 
297
            }
 
298
            if (TIFFReadRawStrip(in, s, buf, bytecounts[s]) < 0 ||
 
299
                TIFFWriteRawStrip(out, s, buf, bytecounts[s]) < 0) {
 
300
                _TIFFfree(buf);
 
301
                return 0;
 
302
            }
 
303
        }
 
304
        _TIFFfree(buf);
 
305
        return 1;
 
306
    }
 
307
 
 
308
bad:
 
309
        TIFFError(TIFFFileName(in),
 
310
                  "Can't allocate space for strip buffer.");
 
311
        return 0;
 
312
}
 
313
 
 
314
static int
 
315
cpTiles(TIFF* in, TIFF* out)
 
316
{
 
317
    tsize_t bufsize = TIFFTileSize(in);
 
318
    unsigned char *buf = (unsigned char *)_TIFFmalloc(bufsize);
 
319
 
 
320
    if (buf) {
 
321
        ttile_t t, nt = TIFFNumberOfTiles(in);
 
322
        tsize_t *bytecounts;
 
323
 
 
324
        TIFFGetField(in, TIFFTAG_TILEBYTECOUNTS, &bytecounts);
 
325
        for (t = 0; t < nt; t++) {
 
326
            if (bytecounts[t] > bufsize) {
 
327
                buf = (unsigned char *)_TIFFrealloc(buf, bytecounts[t]);
 
328
                if (!buf)
 
329
                    goto bad;
 
330
                bufsize = bytecounts[t];
 
331
            }
 
332
            if (TIFFReadRawTile(in, t, buf, bytecounts[t]) < 0 ||
 
333
                TIFFWriteRawTile(out, t, buf, bytecounts[t]) < 0) {
 
334
                _TIFFfree(buf);
 
335
                return 0;
 
336
            }
 
337
        }
 
338
        _TIFFfree(buf);
 
339
        return 1;
 
340
    }
 
341
 
 
342
bad:
 
343
    TIFFError(TIFFFileName(in),
 
344
                  "Can't allocate space for tile buffer.");
 
345
        return (0);
 
346
}
 
347
 
 
348
static int
 
349
cpIFD(TIFF* in, TIFF* out)
 
350
{
 
351
    cpTags(in, out);
 
352
    if (TIFFIsTiled(in)) {
 
353
        if (!cpTiles(in, out))
 
354
            return (0);
 
355
    } else {
 
356
        if (!cpStrips(in, out))
 
357
            return (0);
 
358
    }
 
359
    return (1);
 
360
}
 
361
 
 
362
static  uint16  photometric;            /* current photometric of raster */
 
363
static  uint16  filterWidth;            /* filter width in pixels */
 
364
static  uint32  stepSrcWidth;           /* src image stepping width */
 
365
static  uint32  stepDstWidth;           /* dest stepping width */
 
366
static  uint8* src0;                    /* horizontal bit stepping (start) */
 
367
static  uint8* src1;                    /* horizontal bit stepping (middle) */
 
368
static  uint8* src2;                    /* horizontal bit stepping (end) */
 
369
static  uint32* rowoff;                 /* row offset for stepping */
 
370
static  uint8 cmap[256];                /* colormap indexes */
 
371
static  uint8 bits[256];                /* count of bits set */
 
372
 
 
373
static void
 
374
setupBitsTables()
 
375
{
 
376
    int i;
 
377
    for (i = 0; i < 256; i++) {
 
378
        int n = 0;
 
379
        if (i&0x01) n++;
 
380
        if (i&0x02) n++;
 
381
        if (i&0x04) n++;
 
382
        if (i&0x08) n++;
 
383
        if (i&0x10) n++;
 
384
        if (i&0x20) n++;
 
385
        if (i&0x40) n++;
 
386
        if (i&0x80) n++;
 
387
        bits[i] = n;
 
388
    }
 
389
}
 
390
 
 
391
static int clamp(float v, int low, int high)
 
392
    { return (v < low ? low : v > high ? high : (int)v); }
 
393
 
 
394
#ifndef M_E
 
395
#define M_E             2.7182818284590452354
 
396
#endif
 
397
 
 
398
static void
 
399
expFill(float pct[], uint32 p, uint32 n)
 
400
{
 
401
    uint32 i;
 
402
    uint32 c = (p * n) / 100;
 
403
    for (i = 1; i < c; i++)
 
404
        pct[i] = (float) (1-exp(i/((double)(n-1)))/ M_E);
 
405
    for (; i < n; i++)
 
406
        pct[i] = 0.;
 
407
}
 
408
 
 
409
static void
 
410
setupCmap()
 
411
{
 
412
    float pct[256];                     /* known to be large enough */
 
413
    uint32 i;
 
414
    pct[0] = 1;                         /* force white */
 
415
    switch (contrast) {
 
416
    case EXP50: expFill(pct, 50, 256); break;
 
417
    case EXP60: expFill(pct, 60, 256); break;
 
418
    case EXP70: expFill(pct, 70, 256); break;
 
419
    case EXP80: expFill(pct, 80, 256); break;
 
420
    case EXP90: expFill(pct, 90, 256); break;
 
421
    case EXP:   expFill(pct, 100, 256); break;
 
422
    case LINEAR:
 
423
        for (i = 1; i < 256; i++)
 
424
            pct[i] = 1-((float)i)/(256-1);
 
425
        break;
 
426
    }
 
427
    switch (photometric) {
 
428
    case PHOTOMETRIC_MINISWHITE:
 
429
        for (i = 0; i < 256; i++)
 
430
            cmap[i] = clamp(255*pct[(256-1)-i], 0, 255);
 
431
        break;
 
432
    case PHOTOMETRIC_MINISBLACK:
 
433
        for (i = 0; i < 256; i++)
 
434
            cmap[i] = clamp(255*pct[i], 0, 255);
 
435
        break;
 
436
    }
 
437
}
 
438
 
 
439
static void
 
440
initScale()
 
441
{
 
442
    src0 = (uint8*) _TIFFmalloc(sizeof (uint8) * tnw);
 
443
    src1 = (uint8*) _TIFFmalloc(sizeof (uint8) * tnw);
 
444
    src2 = (uint8*) _TIFFmalloc(sizeof (uint8) * tnw);
 
445
    rowoff = (uint32*) _TIFFmalloc(sizeof (uint32) * tnw);
 
446
    filterWidth = 0;
 
447
    stepDstWidth = stepSrcWidth = 0;
 
448
    setupBitsTables();
 
449
}
 
450
 
 
451
/*
 
452
 * Calculate the horizontal accumulation parameteres
 
453
 * according to the widths of the src and dst images.
 
454
 */
 
455
static void
 
456
setupStepTables(uint32 sw)
 
457
{
 
458
    if (stepSrcWidth != sw || stepDstWidth != tnw) {
 
459
        int step = sw;
 
460
        int limit = tnw;
 
461
        int err = 0;
 
462
        uint32 sx = 0;
 
463
        uint32 x;
 
464
        int fw;
 
465
        uint8 b;
 
466
        for (x = 0; x < tnw; x++) {
 
467
            uint32 sx0 = sx;
 
468
            err += step;
 
469
            while (err >= limit) {
 
470
                err -= limit;
 
471
                sx++;
 
472
            }
 
473
            rowoff[x] = sx0 >> 3;
 
474
            fw = sx - sx0;              /* width */
 
475
            b = (fw < 8) ? 0xff<<(8-fw) : 0xff;
 
476
            src0[x] = b >> (sx0&7);
 
477
            fw -= 8 - (sx0&7);
 
478
            if (fw < 0)
 
479
                fw = 0;
 
480
            src1[x] = fw >> 3;
 
481
            fw -= (fw>>3)<<3;
 
482
            src2[x] = 0xff << (8-fw);
 
483
        }
 
484
        stepSrcWidth = sw;
 
485
        stepDstWidth = tnw;
 
486
    }
 
487
}
 
488
 
 
489
static void
 
490
setrow(uint8* row, uint32 nrows, const uint8* rows[])
 
491
{
 
492
    uint32 x;
 
493
    uint32 area = nrows * filterWidth;
 
494
    for (x = 0; x < tnw; x++) {
 
495
        uint32 mask0 = src0[x];
 
496
        uint32 fw = src1[x];
 
497
        uint32 mask1 = src1[x];
 
498
        uint32 off = rowoff[x];
 
499
        uint32 acc = 0;
 
500
        uint32 y, i;
 
501
        for (y = 0; y < nrows; y++) {
 
502
            const uint8* src = rows[y] + off;
 
503
            acc += bits[*src++ & mask0];
 
504
            switch (fw) {
 
505
            default:
 
506
                for (i = fw; i > 8; i--)
 
507
                    acc += bits[*src++];
 
508
                /* fall thru... */
 
509
            case 8: acc += bits[*src++];
 
510
            case 7: acc += bits[*src++];
 
511
            case 6: acc += bits[*src++];
 
512
            case 5: acc += bits[*src++];
 
513
            case 4: acc += bits[*src++];
 
514
            case 3: acc += bits[*src++];
 
515
            case 2: acc += bits[*src++];
 
516
            case 1: acc += bits[*src++];
 
517
            case 0: break;
 
518
            }
 
519
            acc += bits[*src & mask1];
 
520
        }
 
521
        *row++ = cmap[(255*acc)/area];
 
522
    }
 
523
}
 
524
 
 
525
/*
 
526
 * Install the specified image.  The
 
527
 * image is resized to fit the display page using
 
528
 * a box filter.  The resultant pixels are mapped
 
529
 * with a user-selectable contrast curve.
 
530
 */
 
531
static void
 
532
setImage1(const uint8* br, uint32 rw, uint32 rh)
 
533
{
 
534
    int step = rh;
 
535
    int limit = tnh;
 
536
    int err = 0;
 
537
    int bpr = TIFFhowmany8(rw);
 
538
    int sy = 0;
 
539
    uint8* row = thumbnail;
 
540
    uint32 dy;
 
541
    for (dy = 0; dy < tnh; dy++) {
 
542
        const uint8* rows[256];
 
543
        uint32 nrows = 1;
 
544
        fprintf(stderr, "bpr=%d, sy=%d, bpr*sy=%d\n", bpr, sy, bpr*sy);
 
545
        rows[0] = br + bpr*sy;
 
546
        err += step;
 
547
        while (err >= limit) {
 
548
            err -= limit;
 
549
            sy++;
 
550
            if (err >= limit)
 
551
                {
 
552
                        /* We should perhaps error loudly, but I can't make sense of that */
 
553
                        /* code... */
 
554
                        if( nrows == 256 )
 
555
                                break;
 
556
                        rows[nrows++] = br + bpr*sy;
 
557
                }
 
558
        }
 
559
        setrow(row, nrows, rows);
 
560
        row += tnw;
 
561
    }
 
562
}
 
563
 
 
564
static void
 
565
setImage(const uint8* br, uint32 rw, uint32 rh)
 
566
{
 
567
    filterWidth = (uint16) ceil((double) rw / (double) tnw);
 
568
    setupStepTables(rw);
 
569
    setImage1(br, rw, rh);
 
570
}
 
571
 
 
572
static int
 
573
generateThumbnail(TIFF* in, TIFF* out)
 
574
{
 
575
    unsigned char* raster;
 
576
    unsigned char* rp;
 
577
    uint32 sw, sh, rps;
 
578
    uint16 bps, spp;
 
579
    tsize_t rowsize, rastersize;
 
580
    tstrip_t s, ns = TIFFNumberOfStrips(in);
 
581
    uint32 diroff[1];
 
582
 
 
583
    TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &sw);
 
584
    TIFFGetField(in, TIFFTAG_IMAGELENGTH, &sh);
 
585
    TIFFGetFieldDefaulted(in, TIFFTAG_BITSPERSAMPLE, &bps);
 
586
    TIFFGetFieldDefaulted(in, TIFFTAG_SAMPLESPERPIXEL, &spp);
 
587
    TIFFGetFieldDefaulted(in, TIFFTAG_ROWSPERSTRIP, &rps);
 
588
    if (spp != 1 || bps != 1)
 
589
        return 0;
 
590
    rowsize = TIFFScanlineSize(in);
 
591
    rastersize = sh * rowsize;
 
592
    fprintf(stderr, "rastersize=%u\n", (unsigned int)rastersize);
 
593
    raster = (unsigned char*)_TIFFmalloc(rastersize);
 
594
    if (!raster) {
 
595
            TIFFError(TIFFFileName(in),
 
596
                      "Can't allocate space for raster buffer.");
 
597
            return 0;
 
598
    }
 
599
    rp = raster;
 
600
    for (s = 0; s < ns; s++) {
 
601
        (void) TIFFReadEncodedStrip(in, s, rp, -1);
 
602
        rp += rps * rowsize;
 
603
    }
 
604
    TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &photometric);
 
605
    setupCmap();
 
606
    setImage(raster, sw, sh);
 
607
    _TIFFfree(raster);
 
608
 
 
609
    TIFFSetField(out, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE);
 
610
    TIFFSetField(out, TIFFTAG_IMAGEWIDTH, (uint32) tnw);
 
611
    TIFFSetField(out, TIFFTAG_IMAGELENGTH, (uint32) tnh);
 
612
    TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, (uint16) 8);
 
613
    TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, (uint16) 1);
 
614
    TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_PACKBITS);
 
615
    TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);
 
616
    TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
 
617
    TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
 
618
    cpTag(in, out, TIFFTAG_SOFTWARE,            (uint16) -1, TIFF_ASCII);
 
619
    cpTag(in, out, TIFFTAG_IMAGEDESCRIPTION,    (uint16) -1, TIFF_ASCII);
 
620
    cpTag(in, out, TIFFTAG_DATETIME,            (uint16) -1, TIFF_ASCII);
 
621
    cpTag(in, out, TIFFTAG_HOSTCOMPUTER,        (uint16) -1, TIFF_ASCII);
 
622
    diroff[0] = 0;
 
623
    TIFFSetField(out, TIFFTAG_SUBIFD, 1, diroff);
 
624
    return (TIFFWriteEncodedStrip(out, 0, thumbnail, tnw*tnh) != -1 &&
 
625
            TIFFWriteDirectory(out) != -1);
 
626
}
 
627
 
 
628
char* stuff[] = {
 
629
"usage: thumbnail [options] input.tif output.tif",
 
630
"where options are:",
 
631
" -h #          specify thumbnail image height (default is 274)",
 
632
" -w #          specify thumbnail image width (default is 216)",
 
633
"",
 
634
" -c linear     use linear contrast curve",
 
635
" -c exp50      use 50% exponential contrast curve",
 
636
" -c exp60      use 60% exponential contrast curve",
 
637
" -c exp70      use 70% exponential contrast curve",
 
638
" -c exp80      use 80% exponential contrast curve",
 
639
" -c exp90      use 90% exponential contrast curve",
 
640
" -c exp                use pure exponential contrast curve",
 
641
NULL
 
642
};
 
643
 
 
644
static void
 
645
usage(void)
 
646
{
 
647
        char buf[BUFSIZ];
 
648
        int i;
 
649
 
 
650
        setbuf(stderr, buf);
 
651
        fprintf(stderr, "%s\n\n", TIFFGetVersion());
 
652
        for (i = 0; stuff[i] != NULL; i++)
 
653
                fprintf(stderr, "%s\n", stuff[i]);
 
654
        exit(-1);
 
655
}
 
656
 
 
657
/* vim: set ts=8 sts=8 sw=8 noet: */
 
658
/*
 
659
 * Local Variables:
 
660
 * mode: c
 
661
 * c-basic-offset: 8
 
662
 * fill-column: 78
 
663
 * End:
 
664
 */