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"
44 #define streq(a,b) (strcmp(a,b) == 0)
45 #define strneq(a,b,n) (strncmp(a,b,n) == 0)
47 static void usage(void);
48 static void cpTags(TIFF
* in
, TIFF
* out
);
51 checkcmap(int n
, uint16
* r
, uint16
* g
, uint16
* b
)
54 if (*r
++ >= 256 || *g
++ >= 256 || *b
++ >= 256)
56 fprintf(stderr
, "Warning, assuming 8-bit colormap.\n");
60 #define CopyField(tag, v) \
61 if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
62 #define CopyField3(tag, v1, v2, v3) \
63 if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
65 static uint16 compression
= (uint16
) -1;
66 static uint16 predictor
= 0;
67 static int quality
= 75; /* JPEG quality */
68 static int jpegcolormode
= JPEGCOLORMODE_RGB
;
69 static int processCompressOptions(char*);
72 main(int argc
, char* argv
[])
74 uint16 bitspersample
, shortv
;
75 uint32 imagewidth
, imagelength
;
76 uint16 config
= PLANARCONFIG_CONTIG
;
77 uint32 rowsperstrip
= (uint32
) -1;
78 uint16 photometric
= PHOTOMETRIC_RGB
;
79 uint16
*rmap
, *gmap
, *bmap
;
87 while ((c
= getopt(argc
, argv
, "C:c:p:r:")) != -1)
89 case 'C': /* force colormap interpretation */
92 case 'c': /* compression scheme */
93 if (!processCompressOptions(optarg
))
96 case 'p': /* planar configuration */
97 if (streq(optarg
, "separate"))
98 config
= PLANARCONFIG_SEPARATE
;
99 else if (streq(optarg
, "contig"))
100 config
= PLANARCONFIG_CONTIG
;
104 case 'r': /* rows/strip */
105 rowsperstrip
= atoi(optarg
);
111 if (argc
- optind
!= 2)
113 in
= TIFFOpen(argv
[optind
], "r");
116 if (!TIFFGetField(in
, TIFFTAG_PHOTOMETRIC
, &shortv
) ||
117 shortv
!= PHOTOMETRIC_PALETTE
) {
118 fprintf(stderr
, "%s: Expecting a palette image.\n",
122 if (!TIFFGetField(in
, TIFFTAG_COLORMAP
, &rmap
, &gmap
, &bmap
)) {
124 "%s: No colormap (not a valid palette image).\n",
129 TIFFGetField(in
, TIFFTAG_BITSPERSAMPLE
, &bitspersample
);
130 if (bitspersample
!= 8) {
131 fprintf(stderr
, "%s: Sorry, can only handle 8-bit images.\n",
135 out
= TIFFOpen(argv
[optind
+1], "w");
139 TIFFGetField(in
, TIFFTAG_IMAGEWIDTH
, &imagewidth
);
140 TIFFGetField(in
, TIFFTAG_IMAGELENGTH
, &imagelength
);
141 if (compression
!= (uint16
)-1)
142 TIFFSetField(out
, TIFFTAG_COMPRESSION
, compression
);
144 TIFFGetField(in
, TIFFTAG_COMPRESSION
, &compression
);
145 switch (compression
) {
146 case COMPRESSION_JPEG
:
147 if (jpegcolormode
== JPEGCOLORMODE_RGB
)
148 photometric
= PHOTOMETRIC_YCBCR
;
150 photometric
= PHOTOMETRIC_RGB
;
151 TIFFSetField(out
, TIFFTAG_JPEGQUALITY
, quality
);
152 TIFFSetField(out
, TIFFTAG_JPEGCOLORMODE
, jpegcolormode
);
154 case COMPRESSION_LZW
:
155 case COMPRESSION_DEFLATE
:
157 TIFFSetField(out
, TIFFTAG_PREDICTOR
, predictor
);
160 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
, photometric
);
161 TIFFSetField(out
, TIFFTAG_SAMPLESPERPIXEL
, 3);
162 TIFFSetField(out
, TIFFTAG_PLANARCONFIG
, config
);
163 TIFFSetField(out
, TIFFTAG_ROWSPERSTRIP
,
164 rowsperstrip
= TIFFDefaultStripSize(out
, rowsperstrip
));
165 (void) TIFFGetField(in
, TIFFTAG_PLANARCONFIG
, &shortv
);
167 cmap
= checkcmap(1<<bitspersample
, rmap
, gmap
, bmap
);
170 * Convert 16-bit colormap to 8-bit.
174 for (i
= (1<<bitspersample
)-1; i
>= 0; i
--) {
175 #define CVT(x) (((x) * 255) / ((1L<<16)-1))
176 rmap
[i
] = CVT(rmap
[i
]);
177 gmap
[i
] = CVT(gmap
[i
]);
178 bmap
[i
] = CVT(bmap
[i
]);
181 { unsigned char *ibuf
, *obuf
;
182 register unsigned char* pp
;
184 ibuf
= (unsigned char*)_TIFFmalloc(TIFFScanlineSize(in
));
185 obuf
= (unsigned char*)_TIFFmalloc(TIFFScanlineSize(out
));
187 case PLANARCONFIG_CONTIG
:
188 for (row
= 0; row
< imagelength
; row
++) {
189 if (!TIFFReadScanline(in
, ibuf
, row
, 0))
192 for (x
= 0; x
< imagewidth
; x
++) {
193 *pp
++ = (unsigned char) rmap
[ibuf
[x
]];
194 *pp
++ = (unsigned char) gmap
[ibuf
[x
]];
195 *pp
++ = (unsigned char) bmap
[ibuf
[x
]];
197 if (!TIFFWriteScanline(out
, obuf
, row
, 0))
201 case PLANARCONFIG_SEPARATE
:
202 for (row
= 0; row
< imagelength
; row
++) {
203 if (!TIFFReadScanline(in
, ibuf
, row
, 0))
205 for (pp
= obuf
, x
= 0; x
< imagewidth
; x
++)
206 *pp
++ = (unsigned char) rmap
[ibuf
[x
]];
207 if (!TIFFWriteScanline(out
, obuf
, row
, 0))
209 for (pp
= obuf
, x
= 0; x
< imagewidth
; x
++)
210 *pp
++ = (unsigned char) gmap
[ibuf
[x
]];
211 if (!TIFFWriteScanline(out
, obuf
, row
, 0))
213 for (pp
= obuf
, x
= 0; x
< imagewidth
; x
++)
214 *pp
++ = (unsigned char) bmap
[ibuf
[x
]];
215 if (!TIFFWriteScanline(out
, obuf
, row
, 0))
224 (void) TIFFClose(in
);
225 (void) TIFFClose(out
);
230 processCompressOptions(char* opt
)
232 if (streq(opt
, "none"))
233 compression
= COMPRESSION_NONE
;
234 else if (streq(opt
, "packbits"))
235 compression
= COMPRESSION_PACKBITS
;
236 else if (strneq(opt
, "jpeg", 4)) {
237 char* cp
= strchr(opt
, ':');
239 compression
= COMPRESSION_JPEG
;
242 if (isdigit((int)cp
[1]))
243 quality
= atoi(cp
+1);
244 else if (cp
[1] == 'r' )
245 jpegcolormode
= JPEGCOLORMODE_RAW
;
249 cp
= strchr(cp
+1,':');
251 } else if (strneq(opt
, "lzw", 3)) {
252 char* cp
= strchr(opt
, ':');
254 predictor
= atoi(cp
+1);
255 compression
= COMPRESSION_LZW
;
256 } else if (strneq(opt
, "zip", 3)) {
257 char* cp
= strchr(opt
, ':');
259 predictor
= atoi(cp
+1);
260 compression
= COMPRESSION_DEFLATE
;
266 #define CopyField(tag, v) \
267 if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
268 #define CopyField2(tag, v1, v2) \
269 if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
270 #define CopyField3(tag, v1, v2, v3) \
271 if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
272 #define CopyField4(tag, v1, v2, v3, v4) \
273 if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4)
276 cpTag(TIFF
* in
, TIFF
* out
, uint16 tag
, uint16 count
, TIFFDataType type
)
282 CopyField(tag
, shortv
);
283 } else if (count
== 2) {
284 uint16 shortv1
, shortv2
;
285 CopyField2(tag
, shortv1
, shortv2
);
286 } else if (count
== 4) {
287 uint16
*tr
, *tg
, *tb
, *ta
;
288 CopyField4(tag
, tr
, tg
, tb
, ta
);
289 } else if (count
== (uint16
) -1) {
292 CopyField2(tag
, shortv1
, shortav
);
297 CopyField(tag
, longv
);
303 CopyField(tag
, floatv
);
304 } else if (count
== (uint16
) -1) {
306 CopyField(tag
, floatav
);
311 CopyField(tag
, stringv
);
317 CopyField(tag
, doublev
);
318 } else if (count
== (uint16
) -1) {
320 CopyField(tag
, doubleav
);
324 TIFFError(TIFFFileName(in
),
325 "Data type %d is not supported, tag %d skipped.",
335 static struct cpTag
{
340 { TIFFTAG_IMAGEWIDTH
, 1, TIFF_LONG
},
341 { TIFFTAG_IMAGELENGTH
, 1, TIFF_LONG
},
342 { TIFFTAG_BITSPERSAMPLE
, 1, TIFF_SHORT
},
343 { TIFFTAG_COMPRESSION
, 1, TIFF_SHORT
},
344 { TIFFTAG_FILLORDER
, 1, TIFF_SHORT
},
345 { TIFFTAG_ROWSPERSTRIP
, 1, TIFF_LONG
},
346 { TIFFTAG_GROUP3OPTIONS
, 1, TIFF_LONG
},
347 { TIFFTAG_SUBFILETYPE
, 1, TIFF_LONG
},
348 { TIFFTAG_THRESHHOLDING
, 1, TIFF_SHORT
},
349 { TIFFTAG_DOCUMENTNAME
, 1, TIFF_ASCII
},
350 { TIFFTAG_IMAGEDESCRIPTION
, 1, TIFF_ASCII
},
351 { TIFFTAG_MAKE
, 1, TIFF_ASCII
},
352 { TIFFTAG_MODEL
, 1, TIFF_ASCII
},
353 { TIFFTAG_ORIENTATION
, 1, TIFF_SHORT
},
354 { TIFFTAG_MINSAMPLEVALUE
, 1, TIFF_SHORT
},
355 { TIFFTAG_MAXSAMPLEVALUE
, 1, TIFF_SHORT
},
356 { TIFFTAG_XRESOLUTION
, 1, TIFF_RATIONAL
},
357 { TIFFTAG_YRESOLUTION
, 1, TIFF_RATIONAL
},
358 { TIFFTAG_PAGENAME
, 1, TIFF_ASCII
},
359 { TIFFTAG_XPOSITION
, 1, TIFF_RATIONAL
},
360 { TIFFTAG_YPOSITION
, 1, TIFF_RATIONAL
},
361 { TIFFTAG_GROUP4OPTIONS
, 1, TIFF_LONG
},
362 { TIFFTAG_RESOLUTIONUNIT
, 1, TIFF_SHORT
},
363 { TIFFTAG_PAGENUMBER
, 2, TIFF_SHORT
},
364 { TIFFTAG_SOFTWARE
, 1, TIFF_ASCII
},
365 { TIFFTAG_DATETIME
, 1, TIFF_ASCII
},
366 { TIFFTAG_ARTIST
, 1, TIFF_ASCII
},
367 { TIFFTAG_HOSTCOMPUTER
, 1, TIFF_ASCII
},
368 { TIFFTAG_WHITEPOINT
, 2, TIFF_RATIONAL
},
369 { TIFFTAG_PRIMARYCHROMATICITIES
, (uint16
) -1,TIFF_RATIONAL
},
370 { TIFFTAG_HALFTONEHINTS
, 2, TIFF_SHORT
},
371 { TIFFTAG_BADFAXLINES
, 1, TIFF_LONG
},
372 { TIFFTAG_CLEANFAXDATA
, 1, TIFF_SHORT
},
373 { TIFFTAG_CONSECUTIVEBADFAXLINES
, 1, TIFF_LONG
},
374 { TIFFTAG_INKSET
, 1, TIFF_SHORT
},
375 { TIFFTAG_INKNAMES
, 1, TIFF_ASCII
},
376 { TIFFTAG_DOTRANGE
, 2, TIFF_SHORT
},
377 { TIFFTAG_TARGETPRINTER
, 1, TIFF_ASCII
},
378 { TIFFTAG_SAMPLEFORMAT
, 1, TIFF_SHORT
},
379 { TIFFTAG_YCBCRCOEFFICIENTS
, (uint16
) -1,TIFF_RATIONAL
},
380 { TIFFTAG_YCBCRSUBSAMPLING
, 2, TIFF_SHORT
},
381 { TIFFTAG_YCBCRPOSITIONING
, 1, TIFF_SHORT
},
382 { TIFFTAG_REFERENCEBLACKWHITE
, (uint16
) -1,TIFF_RATIONAL
},
384 #define NTAGS (sizeof (tags) / sizeof (tags[0]))
387 cpTags(TIFF
* in
, TIFF
* out
)
390 for (p
= tags
; p
< &tags
[NTAGS
]; p
++)
391 cpTag(in
, out
, p
->tag
, p
->count
, p
->type
);
396 "usage: pal2rgb [options] input.tif output.tif",
397 "where options are:",
398 " -p contig pack samples contiguously (e.g. RGBRGB...)",
399 " -p separate store samples separately (e.g. RRR...GGG...BBB...)",
400 " -r # make each strip have no more than # rows",
401 " -C 8 assume 8-bit colormap values (instead of 16-bit)",
402 " -C 16 assume 16-bit colormap values",
404 " -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
405 " -c zip[:opts] compress output with deflate encoding",
406 " -c packbits compress output with packbits encoding",
407 " -c none use no compression algorithm on output",
409 "LZW and deflate options:",
410 " # set predictor value",
411 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
422 fprintf(stderr
, "%s\n\n", TIFFGetVersion());
423 for (i
= 0; stuff
[i
] != NULL
; i
++)
424 fprintf(stderr
, "%s\n", stuff
[i
]);
428 /* vim: set ts=8 sts=8 sw=8 noet: */