4 * Copyright (c) 1988-1997 Sam Leffler
5 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
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.
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.
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
27 #include "tif_config.h"
40 #define streq(a,b) (strcmp(a,b) == 0)
41 #define strneq(a,b,n) (strncmp(a,b,n) == 0)
43 static void usage(void);
44 static void cpTags(TIFF
* in
, TIFF
* out
);
47 checkcmap(int n
, uint16
* r
, uint16
* g
, uint16
* b
)
50 if (*r
++ >= 256 || *g
++ >= 256 || *b
++ >= 256)
52 fprintf(stderr
, "Warning, assuming 8-bit colormap.\n");
56 #define CopyField(tag, v) \
57 if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
58 #define CopyField3(tag, v1, v2, v3) \
59 if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
61 static uint16 compression
= (uint16
) -1;
62 static uint16 predictor
= 0;
63 static int quality
= 75; /* JPEG quality */
64 static int jpegcolormode
= JPEGCOLORMODE_RGB
;
65 static int processCompressOptions(char*);
68 main(int argc
, char* argv
[])
70 uint16 bitspersample
, shortv
;
71 uint32 imagewidth
, imagelength
;
72 uint16 config
= PLANARCONFIG_CONTIG
;
73 uint32 rowsperstrip
= (uint32
) -1;
74 uint16 photometric
= PHOTOMETRIC_RGB
;
75 uint16
*rmap
, *gmap
, *bmap
;
83 while ((c
= getopt(argc
, argv
, "C:c:p:r:")) != -1)
85 case 'C': /* force colormap interpretation */
88 case 'c': /* compression scheme */
89 if (!processCompressOptions(optarg
))
92 case 'p': /* planar configuration */
93 if (streq(optarg
, "separate"))
94 config
= PLANARCONFIG_SEPARATE
;
95 else if (streq(optarg
, "contig"))
96 config
= PLANARCONFIG_CONTIG
;
100 case 'r': /* rows/strip */
101 rowsperstrip
= atoi(optarg
);
107 if (argc
- optind
!= 2)
109 in
= TIFFOpen(argv
[optind
], "r");
112 if (!TIFFGetField(in
, TIFFTAG_PHOTOMETRIC
, &shortv
) ||
113 shortv
!= PHOTOMETRIC_PALETTE
) {
114 fprintf(stderr
, "%s: Expecting a palette image.\n",
118 if (!TIFFGetField(in
, TIFFTAG_COLORMAP
, &rmap
, &gmap
, &bmap
)) {
120 "%s: No colormap (not a valid palette image).\n",
125 TIFFGetField(in
, TIFFTAG_BITSPERSAMPLE
, &bitspersample
);
126 if (bitspersample
!= 8) {
127 fprintf(stderr
, "%s: Sorry, can only handle 8-bit images.\n",
131 out
= TIFFOpen(argv
[optind
+1], "w");
135 TIFFGetField(in
, TIFFTAG_IMAGEWIDTH
, &imagewidth
);
136 TIFFGetField(in
, TIFFTAG_IMAGELENGTH
, &imagelength
);
137 if (compression
!= (uint16
)-1)
138 TIFFSetField(out
, TIFFTAG_COMPRESSION
, compression
);
140 TIFFGetField(in
, TIFFTAG_COMPRESSION
, &compression
);
141 switch (compression
) {
142 case COMPRESSION_JPEG
:
143 if (jpegcolormode
== JPEGCOLORMODE_RGB
)
144 photometric
= PHOTOMETRIC_YCBCR
;
146 photometric
= PHOTOMETRIC_RGB
;
147 TIFFSetField(out
, TIFFTAG_JPEGQUALITY
, quality
);
148 TIFFSetField(out
, TIFFTAG_JPEGCOLORMODE
, jpegcolormode
);
150 case COMPRESSION_LZW
:
151 case COMPRESSION_DEFLATE
:
153 TIFFSetField(out
, TIFFTAG_PREDICTOR
, predictor
);
156 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
, photometric
);
157 TIFFSetField(out
, TIFFTAG_SAMPLESPERPIXEL
, 3);
158 TIFFSetField(out
, TIFFTAG_PLANARCONFIG
, config
);
159 TIFFSetField(out
, TIFFTAG_ROWSPERSTRIP
,
160 rowsperstrip
= TIFFDefaultStripSize(out
, rowsperstrip
));
161 (void) TIFFGetField(in
, TIFFTAG_PLANARCONFIG
, &shortv
);
163 cmap
= checkcmap(1<<bitspersample
, rmap
, gmap
, bmap
);
166 * Convert 16-bit colormap to 8-bit.
170 for (i
= (1<<bitspersample
)-1; i
>= 0; i
--) {
171 #define CVT(x) (((x) * 255) / ((1L<<16)-1))
172 rmap
[i
] = CVT(rmap
[i
]);
173 gmap
[i
] = CVT(gmap
[i
]);
174 bmap
[i
] = CVT(bmap
[i
]);
177 { unsigned char *ibuf
, *obuf
;
178 register unsigned char* pp
;
180 ibuf
= (unsigned char*)_TIFFmalloc(TIFFScanlineSize(in
));
181 obuf
= (unsigned char*)_TIFFmalloc(TIFFScanlineSize(out
));
183 case PLANARCONFIG_CONTIG
:
184 for (row
= 0; row
< imagelength
; row
++) {
185 if (!TIFFReadScanline(in
, ibuf
, row
, 0))
188 for (x
= 0; x
< imagewidth
; x
++) {
189 *pp
++ = (unsigned char) rmap
[ibuf
[x
]];
190 *pp
++ = (unsigned char) gmap
[ibuf
[x
]];
191 *pp
++ = (unsigned char) bmap
[ibuf
[x
]];
193 if (!TIFFWriteScanline(out
, obuf
, row
, 0))
197 case PLANARCONFIG_SEPARATE
:
198 for (row
= 0; row
< imagelength
; row
++) {
199 if (!TIFFReadScanline(in
, ibuf
, row
, 0))
201 for (pp
= obuf
, x
= 0; x
< imagewidth
; x
++)
202 *pp
++ = (unsigned char) rmap
[ibuf
[x
]];
203 if (!TIFFWriteScanline(out
, obuf
, row
, 0))
205 for (pp
= obuf
, x
= 0; x
< imagewidth
; x
++)
206 *pp
++ = (unsigned char) gmap
[ibuf
[x
]];
207 if (!TIFFWriteScanline(out
, obuf
, row
, 0))
209 for (pp
= obuf
, x
= 0; x
< imagewidth
; x
++)
210 *pp
++ = (unsigned char) bmap
[ibuf
[x
]];
211 if (!TIFFWriteScanline(out
, obuf
, row
, 0))
220 (void) TIFFClose(in
);
221 (void) TIFFClose(out
);
226 processCompressOptions(char* opt
)
228 if (streq(opt
, "none"))
229 compression
= COMPRESSION_NONE
;
230 else if (streq(opt
, "packbits"))
231 compression
= COMPRESSION_PACKBITS
;
232 else if (strneq(opt
, "jpeg", 4)) {
233 char* cp
= strchr(opt
, ':');
235 compression
= COMPRESSION_JPEG
;
238 if (isdigit((int)cp
[1]))
239 quality
= atoi(cp
+1);
240 else if (cp
[1] == 'r' )
241 jpegcolormode
= JPEGCOLORMODE_RAW
;
245 cp
= strchr(cp
+1,':');
247 } else if (strneq(opt
, "lzw", 3)) {
248 char* cp
= strchr(opt
, ':');
250 predictor
= atoi(cp
+1);
251 compression
= COMPRESSION_LZW
;
252 } else if (strneq(opt
, "zip", 3)) {
253 char* cp
= strchr(opt
, ':');
255 predictor
= atoi(cp
+1);
256 compression
= COMPRESSION_DEFLATE
;
262 #define CopyField(tag, v) \
263 if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
264 #define CopyField2(tag, v1, v2) \
265 if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
266 #define CopyField3(tag, v1, v2, v3) \
267 if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
268 #define CopyField4(tag, v1, v2, v3, v4) \
269 if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4)
272 cpTag(TIFF
* in
, TIFF
* out
, uint16 tag
, uint16 count
, TIFFDataType type
)
278 CopyField(tag
, shortv
);
279 } else if (count
== 2) {
280 uint16 shortv1
, shortv2
;
281 CopyField2(tag
, shortv1
, shortv2
);
282 } else if (count
== 4) {
283 uint16
*tr
, *tg
, *tb
, *ta
;
284 CopyField4(tag
, tr
, tg
, tb
, ta
);
285 } else if (count
== (uint16
) -1) {
288 CopyField2(tag
, shortv1
, shortav
);
293 CopyField(tag
, longv
);
299 CopyField(tag
, floatv
);
300 } else if (count
== (uint16
) -1) {
302 CopyField(tag
, floatav
);
307 CopyField(tag
, stringv
);
313 CopyField(tag
, doublev
);
314 } else if (count
== (uint16
) -1) {
316 CopyField(tag
, doubleav
);
320 TIFFError(TIFFFileName(in
),
321 "Data type %d is not supported, tag %d skipped.",
331 static struct cpTag
{
336 { TIFFTAG_IMAGEWIDTH
, 1, TIFF_LONG
},
337 { TIFFTAG_IMAGELENGTH
, 1, TIFF_LONG
},
338 { TIFFTAG_BITSPERSAMPLE
, 1, TIFF_SHORT
},
339 { TIFFTAG_COMPRESSION
, 1, TIFF_SHORT
},
340 { TIFFTAG_FILLORDER
, 1, TIFF_SHORT
},
341 { TIFFTAG_ROWSPERSTRIP
, 1, TIFF_LONG
},
342 { TIFFTAG_GROUP3OPTIONS
, 1, TIFF_LONG
},
343 { TIFFTAG_SUBFILETYPE
, 1, TIFF_LONG
},
344 { TIFFTAG_THRESHHOLDING
, 1, TIFF_SHORT
},
345 { TIFFTAG_DOCUMENTNAME
, 1, TIFF_ASCII
},
346 { TIFFTAG_IMAGEDESCRIPTION
, 1, TIFF_ASCII
},
347 { TIFFTAG_MAKE
, 1, TIFF_ASCII
},
348 { TIFFTAG_MODEL
, 1, TIFF_ASCII
},
349 { TIFFTAG_ORIENTATION
, 1, TIFF_SHORT
},
350 { TIFFTAG_MINSAMPLEVALUE
, 1, TIFF_SHORT
},
351 { TIFFTAG_MAXSAMPLEVALUE
, 1, TIFF_SHORT
},
352 { TIFFTAG_XRESOLUTION
, 1, TIFF_RATIONAL
},
353 { TIFFTAG_YRESOLUTION
, 1, TIFF_RATIONAL
},
354 { TIFFTAG_PAGENAME
, 1, TIFF_ASCII
},
355 { TIFFTAG_XPOSITION
, 1, TIFF_RATIONAL
},
356 { TIFFTAG_YPOSITION
, 1, TIFF_RATIONAL
},
357 { TIFFTAG_GROUP4OPTIONS
, 1, TIFF_LONG
},
358 { TIFFTAG_RESOLUTIONUNIT
, 1, TIFF_SHORT
},
359 { TIFFTAG_PAGENUMBER
, 2, TIFF_SHORT
},
360 { TIFFTAG_SOFTWARE
, 1, TIFF_ASCII
},
361 { TIFFTAG_DATETIME
, 1, TIFF_ASCII
},
362 { TIFFTAG_ARTIST
, 1, TIFF_ASCII
},
363 { TIFFTAG_HOSTCOMPUTER
, 1, TIFF_ASCII
},
364 { TIFFTAG_WHITEPOINT
, 1, TIFF_RATIONAL
},
365 { TIFFTAG_PRIMARYCHROMATICITIES
, (uint16
) -1,TIFF_RATIONAL
},
366 { TIFFTAG_HALFTONEHINTS
, 2, TIFF_SHORT
},
367 { TIFFTAG_BADFAXLINES
, 1, TIFF_LONG
},
368 { TIFFTAG_CLEANFAXDATA
, 1, TIFF_SHORT
},
369 { TIFFTAG_CONSECUTIVEBADFAXLINES
, 1, TIFF_LONG
},
370 { TIFFTAG_INKSET
, 1, TIFF_SHORT
},
371 { TIFFTAG_INKNAMES
, 1, TIFF_ASCII
},
372 { TIFFTAG_DOTRANGE
, 2, TIFF_SHORT
},
373 { TIFFTAG_TARGETPRINTER
, 1, TIFF_ASCII
},
374 { TIFFTAG_SAMPLEFORMAT
, 1, TIFF_SHORT
},
375 { TIFFTAG_YCBCRCOEFFICIENTS
, (uint16
) -1,TIFF_RATIONAL
},
376 { TIFFTAG_YCBCRSUBSAMPLING
, 2, TIFF_SHORT
},
377 { TIFFTAG_YCBCRPOSITIONING
, 1, TIFF_SHORT
},
378 { TIFFTAG_REFERENCEBLACKWHITE
, (uint16
) -1,TIFF_RATIONAL
},
380 #define NTAGS (sizeof (tags) / sizeof (tags[0]))
383 cpTags(TIFF
* in
, TIFF
* out
)
386 for (p
= tags
; p
< &tags
[NTAGS
]; p
++)
387 cpTag(in
, out
, p
->tag
, p
->count
, p
->type
);
392 "usage: pal2rgb [options] input.tif output.tif",
393 "where options are:",
394 " -p contig pack samples contiguously (e.g. RGBRGB...)",
395 " -p separate store samples separately (e.g. RRR...GGG...BBB...)",
396 " -r # make each strip have no more than # rows",
397 " -C 8 assume 8-bit colormap values (instead of 16-bit)",
398 " -C 16 assume 16-bit colormap values",
400 " -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
401 " -c zip[:opts] compress output with deflate encoding",
402 " -c packbits compress output with packbits encoding",
403 " -c none use no compression algorithm on output",
405 "LZW and deflate options:",
406 " # set predictor value",
407 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
418 fprintf(stderr
, "%s\n\n", TIFFGetVersion());
419 for (i
= 0; stuff
[i
] != NULL
; i
++)
420 fprintf(stderr
, "%s\n", stuff
[i
]);
424 /* vim: set ts=8 sts=8 sw=8 noet: */