1
/* $Id: pal2rgb.c,v 1.10.2.2 2010-07-02 12:03:27 dron Exp $ */
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, 2, 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: */