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: */