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