4  * Copyright (c) 1988-1997 Sam Leffler 
   5  * Copyright (c) 1991-1997 Silicon Graphics, Inc. 
   7  *  Revised:  2/18/01 BAR -- added syntax for extracting single images from 
   8  *                          multi-image TIFF files. 
  10  *    New syntax is:  sourceFileName,image# 
  12  * image# ranges from 0..<n-1> where n is the # of images in the file. 
  13  * There may be no white space between the comma and the filename or 
  16  *    Example:   tiffcp source.tif,1 destination.tif 
  18  * Copies the 2nd image in source.tif to the destination. 
  21  * Permission to use, copy, modify, distribute, and sell this software and  
  22  * its documentation for any purpose is hereby granted without fee, provided 
  23  * that (i) the above copyright notices and this permission notice appear in 
  24  * all copies of the software and related documentation, and (ii) the names of 
  25  * Sam Leffler and Silicon Graphics may not be used in any advertising or 
  26  * publicity relating to the software without the specific, prior written 
  27  * permission of Sam Leffler and Silicon Graphics. 
  29  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,  
  30  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY  
  31  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.   
  33  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR 
  34  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, 
  35  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
  36  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF  
  37  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE  
  41 #include "tif_config.h" 
  60 #define streq(a,b)      (strcmp(a,b) == 0) 
  61 #define strneq(a,b,n)   (strncmp(a,b,n) == 0) 
  66 static  int outtiled 
= -1; 
  67 static  uint32 tilewidth
; 
  68 static  uint32 tilelength
; 
  71 static  uint16 compression
; 
  72 static  uint16 predictor
; 
  73 static  uint16 fillorder
; 
  74 static  uint16 orientation
; 
  75 static  uint32 rowsperstrip
; 
  77 static  int ignore 
= FALSE
;             /* if true, ignore read errors */ 
  78 static  uint32 defg3opts 
= (uint32
) -1; 
  79 static  int quality 
= 75;               /* JPEG quality */ 
  80 static  int jpegcolormode 
= JPEGCOLORMODE_RGB
; 
  81 static  uint16 defcompression 
= (uint16
) -1; 
  82 static  uint16 defpredictor 
= (uint16
) -1; 
  84 static  int tiffcp(TIFF
*, TIFF
*); 
  85 static  int processCompressOptions(char*); 
  86 static  void usage(void); 
  88 static char comma 
= ',';  /* (default) comma separator character */ 
  89 static TIFF
* bias 
= NULL
; 
  90 static int pageNum 
= 0; 
  92 static int nextSrcImage (TIFF 
*tif
, char **imageSpec
) 
  94   seek to the next image specified in *imageSpec 
  95   returns 1 if success, 0 if no more images to process 
  96   *imageSpec=NULL if subsequent images should be processed in sequence 
  99   if (**imageSpec 
== comma
) {  /* if not @comma, we've done all images */ 
 100     char *start 
= *imageSpec 
+ 1; 
 101     tdir_t nextImage 
= (tdir_t
)strtol(start
, imageSpec
, 0); 
 102     if (start 
== *imageSpec
) nextImage 
= TIFFCurrentDirectory (tif
); 
 105       if (**imageSpec 
== comma
) {   
 106         /* a trailing comma denotes remaining images in sequence */ 
 107         if ((*imageSpec
)[1] == '\0') *imageSpec 
= NULL
; 
 110           "Expected a %c separated image # list after %s\n", 
 111           comma
, TIFFFileName (tif
)); 
 112         exit (-4);   /* syntax error */ 
 115     if (TIFFSetDirectory (tif
, nextImage
)) return 1;   
 116     fprintf (stderr
, "%s%c%d not found!\n",  
 117              TIFFFileName(tif
), comma
, (int) nextImage
);  
 123 static TIFF
* openSrcImage (char **imageSpec
) 
 125   imageSpec points to a pointer to a filename followed by optional ,image#'s 
 126   Open the TIFF file and assign *imageSpec to either NULL if there are 
 127   no images specified, or a pointer to the next image number text 
 131     char *fn 
= *imageSpec
; 
 132     *imageSpec 
= strchr (fn
, comma
); 
 133     if (*imageSpec
) {  /* there is at least one image number specifier */ 
 135         tif 
= TIFFOpen (fn
, "r"); 
 136         /* but, ignore any single trailing comma */ 
 137         if (!(*imageSpec
)[1]) {*imageSpec 
= NULL
; return tif
;} 
 139             **imageSpec 
= comma
;  /* replace the comma */ 
 140             if (!nextSrcImage(tif
, imageSpec
)) { 
 146         tif 
= TIFFOpen (fn
, "r"); 
 152 main(int argc
, char* argv
[]) 
 154         uint16 defconfig 
= (uint16
) -1; 
 155         uint16 deffillorder 
= 0; 
 156         uint32 deftilewidth 
= (uint32
) -1; 
 157         uint32 deftilelength 
= (uint32
) -1; 
 158         uint32 defrowsperstrip 
= (uint32
) 0; 
 170         while ((c 
= getopt(argc
, argv
, ",:b:c:f:l:o:z:p:r:w:aistBLMC")) != -1) 
 173                         if (optarg
[0] != '=') usage(); 
 176                 case 'b':   /* this file is bias image subtracted from others */ 
 178                           fputs ("Only 1 bias image may be specified\n", stderr
); 
 182                           uint16    samples 
= (uint16
) -1; 
 183                           char **biasFn 
= &optarg
; 
 184                           bias 
= openSrcImage (biasFn
); 
 185                           if (!bias
) exit (-5); 
 186                           if (TIFFIsTiled (bias
)) { 
 187                      fputs ("Bias image must be organized in strips\n", stderr
); 
 190                           TIFFGetField(bias
, TIFFTAG_SAMPLESPERPIXEL
, &samples
); 
 192                      fputs ("Bias image must be monochrome\n", stderr
); 
 197                 case 'a':               /* append to output */ 
 200                 case 'c':               /* compression scheme */ 
 201                         if (!processCompressOptions(optarg
)) 
 204                 case 'f':               /* fill order */ 
 205                         if (streq(optarg
, "lsb2msb")) 
 206                                 deffillorder 
= FILLORDER_LSB2MSB
; 
 207                         else if (streq(optarg
, "msb2lsb")) 
 208                                 deffillorder 
= FILLORDER_MSB2LSB
; 
 212                 case 'i':               /* ignore errors */ 
 215                 case 'l':               /* tile length */ 
 217                         deftilelength 
= atoi(optarg
); 
 219                 case 'o':               /* initial directory offset */ 
 220                         diroff 
= strtoul(optarg
, NULL
, 0); 
 222                 case 'p':               /* planar configuration */ 
 223                         if (streq(optarg
, "separate")) 
 224                                 defconfig 
= PLANARCONFIG_SEPARATE
; 
 225                         else if (streq(optarg
, "contig")) 
 226                                 defconfig 
= PLANARCONFIG_CONTIG
; 
 230                 case 'r':               /* rows/strip */ 
 231                         defrowsperstrip 
= atol(optarg
); 
 233                 case 's':               /* generate stripped output */ 
 236                 case 't':               /* generate tiled output */ 
 239                 case 'w':               /* tile width */ 
 241                         deftilewidth 
= atoi(optarg
); 
 244                         *mp
++ = 'b'; *mp 
= '\0'; 
 247                         *mp
++ = 'l'; *mp 
= '\0'; 
 250                         *mp
++ = 'm'; *mp 
= '\0'; 
 253                         *mp
++ = 'c'; *mp 
= '\0'; 
 259         if (argc 
- optind 
< 2) 
 261         out 
= TIFFOpen(argv
[argc
-1], mode
); 
 264         if ((argc 
- optind
) == 2) 
 266         for (; optind 
< argc
-1 ; optind
++) { 
 267                 char *imageCursor 
= argv
[optind
]; 
 268                 in 
= openSrcImage (&imageCursor
); 
 271                 if (diroff 
!= 0 && !TIFFSetSubDirectory(in
, diroff
)) { 
 272                         TIFFError(TIFFFileName(in
), 
 273                             "Error, setting subdirectory at %#x", diroff
); 
 274                         (void) TIFFClose(out
); 
 279                    compression 
= defcompression
; 
 280                    predictor 
= defpredictor
; 
 281                    fillorder 
= deffillorder
; 
 282                    rowsperstrip 
= defrowsperstrip
; 
 283                    tilewidth 
= deftilewidth
; 
 284                    tilelength 
= deftilelength
; 
 286                    if (!tiffcp(in
, out
) || !TIFFWriteDirectory(out
)) { 
 290                    if (imageCursor
) { /* seek next image directory */ 
 291                         if (!nextSrcImage(in
, &imageCursor
)) break; 
 293                         if (!TIFFReadDirectory(in
)) break; 
 304 processG3Options(char* cp
) 
 306         if( (cp 
= strchr(cp
, ':')) ) { 
 307                 if (defg3opts 
== (uint32
) -1) 
 311                         if (strneq(cp
, "1d", 2)) 
 312                                 defg3opts 
&= ~GROUP3OPT_2DENCODING
; 
 313                         else if (strneq(cp
, "2d", 2)) 
 314                                 defg3opts 
|= GROUP3OPT_2DENCODING
; 
 315                         else if (strneq(cp
, "fill", 4)) 
 316                                 defg3opts 
|= GROUP3OPT_FILLBITS
; 
 319                 } while( (cp 
= strchr(cp
, ':')) ); 
 324 processCompressOptions(char* opt
) 
 326         if (streq(opt
, "none")) { 
 327                 defcompression 
= COMPRESSION_NONE
; 
 328         } else if (streq(opt
, "packbits")) { 
 329                 defcompression 
= COMPRESSION_PACKBITS
; 
 330         } else if (strneq(opt
, "jpeg", 4)) { 
 331                 char* cp 
= strchr(opt
, ':'); 
 333                 defcompression 
= COMPRESSION_JPEG
; 
 336                     if (isdigit((int)cp
[1])) 
 337                         quality 
= atoi(cp
+1); 
 338                     else if (cp
[1] == 'r' ) 
 339                         jpegcolormode 
= JPEGCOLORMODE_RAW
; 
 343                     cp 
= strchr(cp
+1,':'); 
 345         } else if (strneq(opt
, "g3", 2)) { 
 346                 processG3Options(opt
); 
 347                 defcompression 
= COMPRESSION_CCITTFAX3
; 
 348         } else if (streq(opt
, "g4")) { 
 349                 defcompression 
= COMPRESSION_CCITTFAX4
; 
 350         } else if (strneq(opt
, "lzw", 3)) { 
 351                 char* cp 
= strchr(opt
, ':'); 
 353                         defpredictor 
= atoi(cp
+1); 
 354                 defcompression 
= COMPRESSION_LZW
; 
 355         } else if (strneq(opt
, "zip", 3)) { 
 356                 char* cp 
= strchr(opt
, ':'); 
 358                         defpredictor 
= atoi(cp
+1); 
 359                 defcompression 
= COMPRESSION_ADOBE_DEFLATE
; 
 366 "usage: tiffcp [options] input... output", 
 367 "where options are:", 
 368 " -a            append to output instead of overwriting", 
 369 " -o offset     set initial directory offset", 
 370 " -p contig     pack samples contiguously (e.g. RGBRGB...)", 
 371 " -p separate   store samples separately (e.g. RRR...GGG...BBB...)", 
 372 " -s            write output in strips", 
 373 " -t            write output in tiles", 
 374 " -i            ignore read errors", 
 375 " -b file[,#]   bias (dark) monochrome image to be subtracted from all others", 
 376 " -,=%          use % rather than , to separate image #'s (per Note below)",            
 378 " -r #          make each strip have no more than # rows", 
 379 " -w #          set output tile width (pixels)", 
 380 " -l #          set output tile length (pixels)", 
 382 " -f lsb2msb    force lsb-to-msb FillOrder for output", 
 383 " -f msb2lsb    force msb-to-lsb FillOrder for output", 
 385 " -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding", 
 386 " -c zip[:opts] compress output with deflate encoding", 
 387 " -c jpeg[:opts]        compress output with JPEG encoding", 
 388 " -c packbits   compress output with packbits encoding", 
 389 " -c g3[:opts]  compress output with CCITT Group 3 encoding", 
 390 " -c g4         compress output with CCITT Group 4 encoding", 
 391 " -c none       use no compression algorithm on output", 
 394 " 1d            use default CCITT Group 3 1D-encoding", 
 395 " 2d            use optional CCITT Group 3 2D-encoding", 
 396 " fill          byte-align EOL codes", 
 397 "For example, -c g3:2d:fill to get G3-2D-encoded data with byte-aligned EOLs", 
 400 " #             set compression quality level (0-100, default 75)", 
 401 " r             output color image as RGB rather than YCbCr", 
 402 "For example, -c jpeg:r:50 to get JPEG-encoded RGB data with 50% comp. quality", 
 404 "LZW and deflate options:", 
 405 " #             set predictor value", 
 406 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing", 
 408 "Note that input filenames may be of the form filename,x,y,z", 
 409 "where x, y, and z specify image numbers in the filename to copy.", 
 410 "example:  tiffcp -c none -b esp.tif,1 esp.tif,0 test.tif", 
 411 "  subtract 2nd image in esp.tif from 1st yielding uncompressed result test.tif", 
 422         fprintf(stderr
, "%s\n\n", TIFFGetVersion()); 
 423         for (i 
= 0; stuff
[i
] != NULL
; i
++) 
 424                 fprintf(stderr
, "%s\n", stuff
[i
]); 
 428 #define CopyField(tag, v) \ 
 429     if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v) 
 430 #define CopyField2(tag, v1, v2) \ 
 431     if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2) 
 432 #define CopyField3(tag, v1, v2, v3) \ 
 433     if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3) 
 434 #define CopyField4(tag, v1, v2, v3, v4) \ 
 435     if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4) 
 438 cpTag(TIFF
* in
, TIFF
* out
, uint16 tag
, uint16 count
, TIFFDataType type
) 
 444                         CopyField(tag
, shortv
); 
 445                 } else if (count 
== 2) { 
 446                         uint16 shortv1
, shortv2
; 
 447                         CopyField2(tag
, shortv1
, shortv2
); 
 448                 } else if (count 
== 4) { 
 449                         uint16 
*tr
, *tg
, *tb
, *ta
; 
 450                         CopyField4(tag
, tr
, tg
, tb
, ta
); 
 451                 } else if (count 
== (uint16
) -1) { 
 454                         CopyField2(tag
, shortv1
, shortav
); 
 459                   CopyField(tag
, longv
); 
 465                         CopyField(tag
, floatv
); 
 466                 } else if (count 
== (uint16
) -1) { 
 468                         CopyField(tag
, floatav
); 
 473                   CopyField(tag
, stringv
); 
 479                         CopyField(tag
, doublev
); 
 480                 } else if (count 
== (uint16
) -1) { 
 482                         CopyField(tag
, doubleav
); 
 486                 TIFFError(TIFFFileName(in
), 
 487                           "Data type %d is not supported, tag %d skipped.", 
 492 static struct cpTag 
{ 
 497         { TIFFTAG_SUBFILETYPE
,          1, TIFF_LONG 
}, 
 498         { TIFFTAG_THRESHHOLDING
,        1, TIFF_SHORT 
}, 
 499         { TIFFTAG_DOCUMENTNAME
,         1, TIFF_ASCII 
}, 
 500         { TIFFTAG_IMAGEDESCRIPTION
,     1, TIFF_ASCII 
}, 
 501         { TIFFTAG_MAKE
,                 1, TIFF_ASCII 
}, 
 502         { TIFFTAG_MODEL
,                1, TIFF_ASCII 
}, 
 503         { TIFFTAG_MINSAMPLEVALUE
,       1, TIFF_SHORT 
}, 
 504         { TIFFTAG_MAXSAMPLEVALUE
,       1, TIFF_SHORT 
}, 
 505         { TIFFTAG_XRESOLUTION
,          1, TIFF_RATIONAL 
}, 
 506         { TIFFTAG_YRESOLUTION
,          1, TIFF_RATIONAL 
}, 
 507         { TIFFTAG_PAGENAME
,             1, TIFF_ASCII 
}, 
 508         { TIFFTAG_XPOSITION
,            1, TIFF_RATIONAL 
}, 
 509         { TIFFTAG_YPOSITION
,            1, TIFF_RATIONAL 
}, 
 510         { TIFFTAG_RESOLUTIONUNIT
,       1, TIFF_SHORT 
}, 
 511         { TIFFTAG_SOFTWARE
,             1, TIFF_ASCII 
}, 
 512         { TIFFTAG_DATETIME
,             1, TIFF_ASCII 
}, 
 513         { TIFFTAG_ARTIST
,               1, TIFF_ASCII 
}, 
 514         { TIFFTAG_HOSTCOMPUTER
,         1, TIFF_ASCII 
}, 
 515         { TIFFTAG_WHITEPOINT
,           (uint16
) -1, TIFF_RATIONAL 
}, 
 516         { TIFFTAG_PRIMARYCHROMATICITIES
,(uint16
) -1,TIFF_RATIONAL 
}, 
 517         { TIFFTAG_HALFTONEHINTS
,        2, TIFF_SHORT 
}, 
 518         { TIFFTAG_INKSET
,               1, TIFF_SHORT 
}, 
 519         { TIFFTAG_DOTRANGE
,             2, TIFF_SHORT 
}, 
 520         { TIFFTAG_TARGETPRINTER
,        1, TIFF_ASCII 
}, 
 521         { TIFFTAG_SAMPLEFORMAT
,         1, TIFF_SHORT 
}, 
 522         { TIFFTAG_YCBCRCOEFFICIENTS
,    (uint16
) -1,TIFF_RATIONAL 
}, 
 523         { TIFFTAG_YCBCRSUBSAMPLING
,     2, TIFF_SHORT 
}, 
 524         { TIFFTAG_YCBCRPOSITIONING
,     1, TIFF_SHORT 
}, 
 525         { TIFFTAG_REFERENCEBLACKWHITE
,  (uint16
) -1,TIFF_RATIONAL 
}, 
 526         { TIFFTAG_EXTRASAMPLES
,         (uint16
) -1, TIFF_SHORT 
}, 
 527         { TIFFTAG_SMINSAMPLEVALUE
,      1, TIFF_DOUBLE 
}, 
 528         { TIFFTAG_SMAXSAMPLEVALUE
,      1, TIFF_DOUBLE 
}, 
 529         { TIFFTAG_STONITS
,              1, TIFF_DOUBLE 
}, 
 531 #define NTAGS   (sizeof (tags) / sizeof (tags[0])) 
 533 #define CopyTag(tag, count, type)       cpTag(in, out, tag, count, type) 
 535 typedef int (*copyFunc
) 
 536     (TIFF
* in
, TIFF
* out
, uint32 l
, uint32 w
, uint16 samplesperpixel
); 
 537 static  copyFunc 
pickCopyFunc(TIFF
*, TIFF
*, uint16
, uint16
); 
 540 tiffcp(TIFF
* in
, TIFF
* out
) 
 542         uint16 bitspersample
, samplesperpixel
; 
 544         uint32 width
, length
; 
 547         CopyField(TIFFTAG_IMAGEWIDTH
, width
); 
 548         CopyField(TIFFTAG_IMAGELENGTH
, length
); 
 549         CopyField(TIFFTAG_BITSPERSAMPLE
, bitspersample
); 
 550         CopyField(TIFFTAG_SAMPLESPERPIXEL
, samplesperpixel
); 
 551         if (compression 
!= (uint16
)-1) 
 552                 TIFFSetField(out
, TIFFTAG_COMPRESSION
, compression
); 
 554                 CopyField(TIFFTAG_COMPRESSION
, compression
); 
 555         if (compression 
== COMPRESSION_JPEG
) { 
 556             uint16 input_compression
, input_photometric
; 
 558             if (TIFFGetField(in
, TIFFTAG_COMPRESSION
, &input_compression
) 
 559                  && input_compression 
== COMPRESSION_JPEG
) { 
 560                 TIFFSetField(in
, TIFFTAG_JPEGCOLORMODE
, JPEGCOLORMODE_RGB
); 
 562             if (TIFFGetField(in
, TIFFTAG_PHOTOMETRIC
, &input_photometric
)) { 
 563                 if(input_photometric 
== PHOTOMETRIC_RGB
) { 
 564                         if (jpegcolormode 
== JPEGCOLORMODE_RGB
) 
 565                                 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
, 
 568                                 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
, 
 571                         TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
, 
 575         else if (compression 
== COMPRESSION_SGILOG
 
 576                  || compression 
== COMPRESSION_SGILOG24
) 
 577                 TIFFSetField(out
, TIFFTAG_PHOTOMETRIC
, 
 578                     samplesperpixel 
== 1 ? 
 579                         PHOTOMETRIC_LOGL 
: PHOTOMETRIC_LOGLUV
); 
 581                 CopyTag(TIFFTAG_PHOTOMETRIC
, 1, TIFF_SHORT
); 
 583                 TIFFSetField(out
, TIFFTAG_FILLORDER
, fillorder
); 
 585                 CopyTag(TIFFTAG_FILLORDER
, 1, TIFF_SHORT
); 
 587          * Will copy `Orientation' tag from input image 
 589         TIFFGetFieldDefaulted(in
, TIFFTAG_ORIENTATION
, &orientation
); 
 590         switch (orientation
) { 
 591                 case ORIENTATION_BOTRIGHT
: 
 592                 case ORIENTATION_RIGHTBOT
:      /* XXX */ 
 593                         TIFFWarning(TIFFFileName(in
), "using bottom-left orientation"); 
 594                         orientation 
= ORIENTATION_BOTLEFT
; 
 596                 case ORIENTATION_LEFTBOT
:       /* XXX */ 
 597                 case ORIENTATION_BOTLEFT
: 
 599                 case ORIENTATION_TOPRIGHT
: 
 600                 case ORIENTATION_RIGHTTOP
:      /* XXX */ 
 602                         TIFFWarning(TIFFFileName(in
), "using top-left orientation"); 
 603                         orientation 
= ORIENTATION_TOPLEFT
; 
 605                 case ORIENTATION_LEFTTOP
:       /* XXX */ 
 606                 case ORIENTATION_TOPLEFT
: 
 609         TIFFSetField(out
, TIFFTAG_ORIENTATION
, orientation
); 
 611          * Choose tiles/strip for the output image according to 
 612          * the command line arguments (-tiles, -strips) and the 
 613          * structure of the input image. 
 616                 outtiled 
= TIFFIsTiled(in
); 
 619                  * Setup output file's tile width&height.  If either 
 620                  * is not specified, use either the value from the 
 621                  * input image or, if nothing is defined, use the 
 624                 if (tilewidth 
== (uint32
) -1) 
 625                         TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tilewidth
); 
 626                 if (tilelength 
== (uint32
) -1) 
 627                         TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tilelength
); 
 628                 TIFFDefaultTileSize(out
, &tilewidth
, &tilelength
); 
 629                 TIFFSetField(out
, TIFFTAG_TILEWIDTH
, tilewidth
); 
 630                 TIFFSetField(out
, TIFFTAG_TILELENGTH
, tilelength
); 
 633                  * RowsPerStrip is left unspecified: use either the 
 634                  * value from the input image or, if nothing is defined, 
 635                  * use the library default. 
 637                 if (rowsperstrip 
== (uint32
) 0) { 
 638                         if (!TIFFGetField(in
, TIFFTAG_ROWSPERSTRIP
, 
 641                                         TIFFDefaultStripSize(out
, rowsperstrip
); 
 643                         if (rowsperstrip 
> length
) 
 644                                 rowsperstrip 
= length
; 
 646                 else if (rowsperstrip 
== (uint32
) -1) 
 647                         rowsperstrip 
= length
; 
 648                 TIFFSetField(out
, TIFFTAG_ROWSPERSTRIP
, rowsperstrip
); 
 650         if (config 
!= (uint16
) -1) 
 651                 TIFFSetField(out
, TIFFTAG_PLANARCONFIG
, config
); 
 653                 CopyField(TIFFTAG_PLANARCONFIG
, config
); 
 654         if (samplesperpixel 
<= 4) 
 655                 CopyTag(TIFFTAG_TRANSFERFUNCTION
, 4, TIFF_SHORT
); 
 656         CopyTag(TIFFTAG_COLORMAP
, 4, TIFF_SHORT
); 
 657 /* SMinSampleValue & SMaxSampleValue */ 
 658         switch (compression
) { 
 659         case COMPRESSION_JPEG
: 
 660                 TIFFSetField(out
, TIFFTAG_JPEGQUALITY
, quality
); 
 661                 TIFFSetField(out
, TIFFTAG_JPEGCOLORMODE
, jpegcolormode
); 
 663         case COMPRESSION_LZW
: 
 664         case COMPRESSION_ADOBE_DEFLATE
: 
 665         case COMPRESSION_DEFLATE
: 
 666                 if (predictor 
!= (uint16
)-1) 
 667                         TIFFSetField(out
, TIFFTAG_PREDICTOR
, predictor
); 
 669                         CopyField(TIFFTAG_PREDICTOR
, predictor
); 
 671         case COMPRESSION_CCITTFAX3
: 
 672         case COMPRESSION_CCITTFAX4
: 
 673                 if (compression 
== COMPRESSION_CCITTFAX3
) { 
 674                         if (g3opts 
!= (uint32
) -1) 
 675                                 TIFFSetField(out
, TIFFTAG_GROUP3OPTIONS
, 
 678                                 CopyField(TIFFTAG_GROUP3OPTIONS
, g3opts
); 
 680                         CopyTag(TIFFTAG_GROUP4OPTIONS
, 1, TIFF_LONG
); 
 681                 CopyTag(TIFFTAG_BADFAXLINES
, 1, TIFF_LONG
); 
 682                 CopyTag(TIFFTAG_CLEANFAXDATA
, 1, TIFF_LONG
); 
 683                 CopyTag(TIFFTAG_CONSECUTIVEBADFAXLINES
, 1, TIFF_LONG
); 
 684                 CopyTag(TIFFTAG_FAXRECVPARAMS
, 1, TIFF_LONG
); 
 685                 CopyTag(TIFFTAG_FAXRECVTIME
, 1, TIFF_LONG
); 
 686                 CopyTag(TIFFTAG_FAXSUBADDRESS
, 1, TIFF_ASCII
); 
 691           if (TIFFGetField(in
, TIFFTAG_ICCPROFILE
, &len32
, &data
)) 
 692                 TIFFSetField(out
, TIFFTAG_ICCPROFILE
, len32
, data
); 
 695           const char* inknames
; 
 696           if (TIFFGetField(in
, TIFFTAG_NUMBEROFINKS
, &ninks
)) { 
 697                 TIFFSetField(out
, TIFFTAG_NUMBEROFINKS
, ninks
); 
 698                 if (TIFFGetField(in
, TIFFTAG_INKNAMES
, &inknames
)) { 
 699                     int inknameslen 
= strlen(inknames
) + 1; 
 700                     const char* cp 
= inknames
; 
 702                             cp 
= strchr(cp
, '\0'); 
 705                                     inknameslen 
+= (strlen(cp
) + 1); 
 709                     TIFFSetField(out
, TIFFTAG_INKNAMES
, inknameslen
, inknames
); 
 714           unsigned short pg0
, pg1
; 
 715           if (TIFFGetField(in
, TIFFTAG_PAGENUMBER
, &pg0
, &pg1
)) { 
 716                 if (pageNum 
< 0) /* only one input file */ 
 717                         TIFFSetField(out
, TIFFTAG_PAGENUMBER
, pg0
, pg1
); 
 719                         TIFFSetField(out
, TIFFTAG_PAGENUMBER
, pageNum
++, 0); 
 723         for (p 
= tags
; p 
< &tags
[NTAGS
]; p
++) 
 724                 CopyTag(p
->tag
, p
->count
, p
->type
); 
 726         cf 
= pickCopyFunc(in
, out
, bitspersample
, samplesperpixel
); 
 727         return (cf 
? (*cf
)(in
, out
, length
, width
, samplesperpixel
) : FALSE
); 
 733 #define DECLAREcpFunc(x) \ 
 734 static int x(TIFF* in, TIFF* out, \ 
 735     uint32 imagelength, uint32 imagewidth, tsample_t spp) 
 737 #define DECLAREreadFunc(x) \ 
 738 static int x(TIFF* in, \ 
 739     uint8* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp) 
 740 typedef int (*readFunc
)(TIFF
*, uint8
*, uint32
, uint32
, tsample_t
); 
 742 #define DECLAREwriteFunc(x) \ 
 743 static int x(TIFF* out, \ 
 744     uint8* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp) 
 745 typedef int (*writeFunc
)(TIFF
*, uint8
*, uint32
, uint32
, tsample_t
); 
 748  * Contig -> contig by scanline for rows/strip change. 
 750 DECLAREcpFunc(cpContig2ContigByRow
) 
 752         tdata_t buf 
= _TIFFmalloc(TIFFScanlineSize(in
)); 
 755         (void) imagewidth
; (void) spp
; 
 756         for (row 
= 0; row 
< imagelength
; row
++) { 
 757                 if (TIFFReadScanline(in
, buf
, row
, 0) < 0 && !ignore
) { 
 758                         TIFFError(TIFFFileName(in
), 
 759                                   "Error, can't read scanline %lu", 
 760                                   (unsigned long) row
); 
 763                 if (TIFFWriteScanline(out
, buf
, row
, 0) < 0) { 
 764                         TIFFError(TIFFFileName(out
), 
 765                                   "Error, can't write scanline %lu", 
 766                                   (unsigned long) row
); 
 778 typedef void biasFn (void *image
, void *bias
, uint32 pixels
); 
 780 #define subtract(bits) \ 
 781 static void subtract##bits (void *i, void *b, uint32 pixels)\ 
 783    uint##bits *image = i;\ 
 784    uint##bits *bias = b;\ 
 786      *image = *image > *bias ? *image-*bias : 0;\ 
 795 static biasFn 
*lineSubtractFn (unsigned bits
) 
 798       case  8:  return subtract8
; 
 799       case 16:  return subtract16
; 
 800       case 32:  return subtract32
; 
 806  * Contig -> contig by scanline while subtracting a bias image. 
 808 DECLAREcpFunc(cpBiasedContig2Contig
) 
 811           tsize_t biasSize 
= TIFFScanlineSize(bias
); 
 812           tsize_t bufSize 
= TIFFScanlineSize(in
); 
 813           tdata_t buf
, biasBuf
; 
 814           uint32 biasWidth 
= 0, biasLength 
= 0; 
 815           TIFFGetField(bias
, TIFFTAG_IMAGEWIDTH
, &biasWidth
); 
 816           TIFFGetField(bias
, TIFFTAG_IMAGELENGTH
, &biasLength
); 
 817           if (biasSize 
== bufSize 
&&  
 818               imagelength 
== biasLength 
&& imagewidth 
== biasWidth
) { 
 819                 uint16 sampleBits 
= 0; 
 820                 biasFn 
*subtractLine
; 
 821                 TIFFGetField(in
, TIFFTAG_BITSPERSAMPLE
, &sampleBits
); 
 822                 subtractLine 
= lineSubtractFn (sampleBits
); 
 825                         buf 
= _TIFFmalloc(bufSize
); 
 826                         biasBuf 
= _TIFFmalloc(bufSize
); 
 827                         for (row 
= 0; row 
< imagelength
; row
++) { 
 828                                 if (TIFFReadScanline(in
, buf
, row
, 0) < 0 
 830                                         TIFFError(TIFFFileName(in
), 
 831                                         "Error, can't read scanline %lu", 
 832                                         (unsigned long) row
); 
 835                                 if (TIFFReadScanline(bias
, biasBuf
, row
, 0) < 0 
 837                                         TIFFError(TIFFFileName(in
), 
 838                                         "Error, can't read biased scanline %lu", 
 839                                         (unsigned long) row
); 
 842                                 subtractLine (buf
, biasBuf
, imagewidth
); 
 843                                 if (TIFFWriteScanline(out
, buf
, row
, 0) < 0) { 
 844                                         TIFFError(TIFFFileName(out
), 
 845                                         "Error, can't write scanline %lu", 
 846                                         (unsigned long) row
); 
 853                         TIFFSetDirectory(bias
, 
 854                                 TIFFCurrentDirectory(bias
)); /* rewind */ 
 861               TIFFError(TIFFFileName(in
), 
 862                         "No support for biasing %d bit pixels\n", 
 867           TIFFError(TIFFFileName(in
), 
 868                     "Bias image %s,%d\nis not the same size as %s,%d\n", 
 869                     TIFFFileName(bias
), TIFFCurrentDirectory(bias
), 
 870                     TIFFFileName(in
), TIFFCurrentDirectory(in
)); 
 873           TIFFError(TIFFFileName(in
), 
 874                     "Can't bias %s,%d as it has >1 Sample/Pixel\n", 
 875                     TIFFFileName(in
), TIFFCurrentDirectory(in
)); 
 883  * Strip -> strip for change in encoding. 
 885 DECLAREcpFunc(cpDecodedStrips
) 
 887         tsize_t stripsize  
= TIFFStripSize(in
); 
 888         tdata_t buf 
= _TIFFmalloc(stripsize
); 
 890         (void) imagewidth
; (void) spp
; 
 892                 tstrip_t s
, ns 
= TIFFNumberOfStrips(in
); 
 894                 for (s 
= 0; s 
< ns
; s
++) { 
 895                         tsize_t cc 
= (row 
+ rowsperstrip 
> imagelength
) ? 
 896                             TIFFVStripSize(in
, imagelength 
- row
) : stripsize
; 
 897                         if (TIFFReadEncodedStrip(in
, s
, buf
, cc
) < 0 
 899                                 TIFFError(TIFFFileName(in
), 
 900                                           "Error, can't read strip %lu", 
 904                         if (TIFFWriteEncodedStrip(out
, s
, buf
, cc
) < 0) { 
 905                                 TIFFError(TIFFFileName(out
), 
 906                                           "Error, can't write strip %lu", 
 915                 TIFFError(TIFFFileName(in
), 
 916                           "Error, can't allocate memory buffer of size %lu " 
 917                           "to read strips", (unsigned long) stripsize
); 
 927  * Separate -> separate by row for rows/strip change. 
 929 DECLAREcpFunc(cpSeparate2SeparateByRow
) 
 931         tdata_t buf 
= _TIFFmalloc(TIFFScanlineSize(in
)); 
 936         for (s 
= 0; s 
< spp
; s
++) { 
 937                 for (row 
= 0; row 
< imagelength
; row
++) { 
 938                         if (TIFFReadScanline(in
, buf
, row
, s
) < 0 && !ignore
) { 
 939                                 TIFFError(TIFFFileName(in
), 
 940                                           "Error, can't read scanline %lu", 
 941                                           (unsigned long) row
); 
 944                         if (TIFFWriteScanline(out
, buf
, row
, s
) < 0) { 
 945                                 TIFFError(TIFFFileName(out
), 
 946                                           "Error, can't write scanline %lu", 
 947                                           (unsigned long) row
); 
 960  * Contig -> separate by row. 
 962 DECLAREcpFunc(cpContig2SeparateByRow
) 
 964         tdata_t inbuf 
= _TIFFmalloc(TIFFScanlineSize(in
)); 
 965         tdata_t outbuf 
= _TIFFmalloc(TIFFScanlineSize(out
)); 
 966         register uint8 
*inp
, *outp
; 
 971         /* unpack channels */ 
 972         for (s 
= 0; s 
< spp
; s
++) { 
 973                 for (row 
= 0; row 
< imagelength
; row
++) { 
 974                         if (TIFFReadScanline(in
, inbuf
, row
, 0) < 0 
 976                                 TIFFError(TIFFFileName(in
), 
 977                                           "Error, can't read scanline %lu", 
 978                                           (unsigned long) row
); 
 981                         inp 
= ((uint8
*)inbuf
) + s
; 
 982                         outp 
= (uint8
*)outbuf
; 
 983                         for (n 
= imagewidth
; n
-- > 0;) { 
 987                         if (TIFFWriteScanline(out
, outbuf
, row
, s
) < 0) { 
 988                                 TIFFError(TIFFFileName(out
), 
 989                                           "Error, can't write scanline %lu", 
 990                                           (unsigned long) row
); 
 995         if (inbuf
) _TIFFfree(inbuf
); 
 996         if (outbuf
) _TIFFfree(outbuf
); 
 999         if (inbuf
) _TIFFfree(inbuf
); 
1000         if (outbuf
) _TIFFfree(outbuf
); 
1005  * Separate -> contig by row. 
1007 DECLAREcpFunc(cpSeparate2ContigByRow
) 
1009         tdata_t inbuf 
= _TIFFmalloc(TIFFScanlineSize(in
)); 
1010         tdata_t outbuf 
= _TIFFmalloc(TIFFScanlineSize(out
)); 
1011         register uint8 
*inp
, *outp
; 
1016         for (row 
= 0; row 
< imagelength
; row
++) { 
1017                 /* merge channels */ 
1018                 for (s 
= 0; s 
< spp
; s
++) { 
1019                         if (TIFFReadScanline(in
, inbuf
, row
, s
) < 0 
1021                                 TIFFError(TIFFFileName(in
), 
1022                                           "Error, can't read scanline %lu", 
1023                                           (unsigned long) row
); 
1026                         inp 
= (uint8
*)inbuf
; 
1027                         outp 
= ((uint8
*)outbuf
) + s
; 
1028                         for (n 
= imagewidth
; n
-- > 0;) { 
1033                 if (TIFFWriteScanline(out
, outbuf
, row
, 0) < 0) { 
1034                         TIFFError(TIFFFileName(out
), 
1035                                   "Error, can't write scanline %lu", 
1036                                   (unsigned long) row
); 
1040         if (inbuf
) _TIFFfree(inbuf
); 
1041         if (outbuf
) _TIFFfree(outbuf
); 
1044         if (inbuf
) _TIFFfree(inbuf
); 
1045         if (outbuf
) _TIFFfree(outbuf
); 
1050 cpStripToTile(uint8
* out
, uint8
* in
, 
1051         uint32 rows
, uint32 cols
, int outskew
, int inskew
) 
1053         while (rows
-- > 0) { 
1063 cpContigBufToSeparateBuf(uint8
* out
, uint8
* in
, 
1064            uint32 rows
, uint32 cols
, int outskew
, int inskew
, tsample_t spp
, 
1065            int bytes_per_sample 
) 
1067         while (rows
-- > 0) { 
1071                         int n 
= bytes_per_sample
; 
1076                         in 
+= (spp
-1) * bytes_per_sample
; 
1084 cpSeparateBufToContigBuf(uint8
* out
, uint8
* in
, 
1085         uint32 rows
, uint32 cols
, int outskew
, int inskew
, tsample_t spp
, 
1086                          int bytes_per_sample
) 
1088         while (rows
-- > 0) { 
1091                         int n 
= bytes_per_sample
; 
1096                         out 
+= (spp
-1)*bytes_per_sample
; 
1104 cpImage(TIFF
* in
, TIFF
* out
, readFunc fin
, writeFunc fout
, 
1105         uint32 imagelength
, uint32 imagewidth
, tsample_t spp
) 
1109         tsize_t scanlinesize 
= TIFFRasterScanlineSize(in
); 
1110         tsize_t bytes 
= scanlinesize 
* (tsize_t
)imagelength
;                                       
1112          * XXX: Check for integer overflow. 
1116             && bytes 
/ (tsize_t
)imagelength 
== scanlinesize
) { 
1117                 buf 
= _TIFFmalloc(bytes
); 
1119                         if ((*fin
)(in
, (uint8
*)buf
, imagelength
,  
1121                                 status 
= (*fout
)(out
, (uint8
*)buf
, 
1122                                                  imagelength
, imagewidth
, spp
); 
1126                         TIFFError(TIFFFileName(in
), 
1127                                 "Error, can't allocate space for image buffer"); 
1130                 TIFFError(TIFFFileName(in
), "Error, no space for image buffer"); 
1136 DECLAREreadFunc(readContigStripsIntoBuffer
) 
1138         tsize_t scanlinesize 
= TIFFScanlineSize(in
); 
1142         (void) imagewidth
; (void) spp
; 
1143         for (row 
= 0; row 
< imagelength
; row
++) { 
1144                 if (TIFFReadScanline(in
, (tdata_t
) bufp
, row
, 0) < 0 
1146                         TIFFError(TIFFFileName(in
), 
1147                                   "Error, can't read scanline %lu", 
1148                                   (unsigned long) row
); 
1151                 bufp 
+= scanlinesize
; 
1157 DECLAREreadFunc(readSeparateStripsIntoBuffer
) 
1160         tsize_t scanlinesize 
= TIFFScanlineSize(in
); 
1161         tdata_t scanline 
= _TIFFmalloc(scanlinesize
); 
1167                 uint8
* bufp 
= (uint8
*) buf
; 
1170                 for (row 
= 0; row 
< imagelength
; row
++) { 
1171                         /* merge channels */ 
1172                         for (s 
= 0; s 
< spp
; s
++) { 
1173                                 uint8
* bp 
= bufp 
+ s
; 
1174                                 tsize_t n 
= scanlinesize
; 
1175                                 uint8
* sbuf 
= scanline
; 
1177                                 if (TIFFReadScanline(in
, scanline
, row
, s
) < 0 
1179                                         TIFFError(TIFFFileName(in
), 
1180                                         "Error, can't read scanline %lu", 
1181                                         (unsigned long) row
); 
1186                                         *bp 
= *sbuf
++, bp 
+= spp
; 
1188                         bufp 
+= scanlinesize 
* spp
; 
1193         _TIFFfree(scanline
); 
1197 DECLAREreadFunc(readContigTilesIntoBuffer
) 
1200         tdata_t tilebuf 
= _TIFFmalloc(TIFFTileSize(in
)); 
1201         uint32 imagew 
= TIFFScanlineSize(in
); 
1202         uint32 tilew  
= TIFFTileRowSize(in
); 
1203         int iskew 
= imagew 
- tilew
; 
1204         uint8
* bufp 
= (uint8
*) buf
; 
1211         (void) TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tw
); 
1212         (void) TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tl
); 
1214         for (row 
= 0; row 
< imagelength
; row 
+= tl
) { 
1215                 uint32 nrow 
= (row
+tl 
> imagelength
) ? imagelength
-row 
: tl
; 
1219                 for (col 
= 0; col 
< imagewidth
; col 
+= tw
) { 
1220                         if (TIFFReadTile(in
, tilebuf
, col
, row
, 0, 0) < 0 
1222                                 TIFFError(TIFFFileName(in
), 
1223                                           "Error, can't read tile at %lu %lu", 
1224                                           (unsigned long) col
, 
1225                                           (unsigned long) row
); 
1229                         if (colb 
+ tilew 
> imagew
) { 
1230                                 uint32 width 
= imagew 
- colb
; 
1231                                 uint32 oskew 
= tilew 
- width
; 
1232                                 cpStripToTile(bufp 
+ colb
, 
1233                                               tilebuf
, nrow
, width
, 
1234                                               oskew 
+ iskew
, oskew 
); 
1236                                 cpStripToTile(bufp 
+ colb
, 
1237                                               tilebuf
, nrow
, tilew
, 
1241                 bufp 
+= imagew 
* nrow
; 
1248 DECLAREreadFunc(readSeparateTilesIntoBuffer
) 
1251         uint32 imagew 
= TIFFRasterScanlineSize(in
); 
1252         uint32 tilew 
= TIFFTileRowSize(in
); 
1253         int iskew  
= imagew 
- tilew
*spp
; 
1254         tdata_t tilebuf 
= _TIFFmalloc(TIFFTileSize(in
)); 
1255         uint8
* bufp 
= (uint8
*) buf
; 
1258         uint16 bps
, bytes_per_sample
; 
1262         (void) TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tw
); 
1263         (void) TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tl
); 
1264         (void) TIFFGetField(in
, TIFFTAG_BITSPERSAMPLE
, &bps
); 
1265         assert( bps 
% 8 == 0 ); 
1266         bytes_per_sample 
= bps
/8; 
1268         for (row 
= 0; row 
< imagelength
; row 
+= tl
) { 
1269                 uint32 nrow 
= (row
+tl 
> imagelength
) ? imagelength
-row 
: tl
; 
1273                 for (col 
= 0; col 
< imagewidth
; col 
+= tw
) { 
1276                         for (s 
= 0; s 
< spp
; s
++) { 
1277                                 if (TIFFReadTile(in
, tilebuf
, col
, row
, 0, s
) < 0 
1279                                         TIFFError(TIFFFileName(in
), 
1280                                           "Error, can't read tile at %lu %lu, " 
1282                                           (unsigned long) col
, 
1283                                           (unsigned long) row
, 
1289                                  * Tile is clipped horizontally.  Calculate 
1290                                  * visible portion and skewing factors. 
1292                                 if (colb 
+ tilew
*spp 
> imagew
) { 
1293                                         uint32 width 
= imagew 
- colb
; 
1294                                         int oskew 
= tilew
*spp 
- width
; 
1295                                         cpSeparateBufToContigBuf( 
1296                                             bufp
+colb
+s
*bytes_per_sample
, 
1298                                             width
/(spp
*bytes_per_sample
), 
1303                                         cpSeparateBufToContigBuf( 
1304                                             bufp
+colb
+s
*bytes_per_sample
, 
1311                 bufp 
+= imagew 
* nrow
; 
1318 DECLAREwriteFunc(writeBufferToContigStrips
) 
1320         uint32 row
, rowsperstrip
; 
1323         (void) imagewidth
; (void) spp
; 
1324         (void) TIFFGetFieldDefaulted(out
, TIFFTAG_ROWSPERSTRIP
, &rowsperstrip
); 
1325         for (row 
= 0; row 
< imagelength
; row 
+= rowsperstrip
) { 
1326                 uint32 nrows 
= (row
+rowsperstrip 
> imagelength
) ? 
1327                     imagelength
-row 
: rowsperstrip
; 
1328                 tsize_t stripsize 
= TIFFVStripSize(out
, nrows
); 
1329                 if (TIFFWriteEncodedStrip(out
, strip
++, buf
, stripsize
) < 0) { 
1330                         TIFFError(TIFFFileName(out
), 
1331                                   "Error, can't write strip %lu", strip 
- 1); 
1339 DECLAREwriteFunc(writeBufferToSeparateStrips
) 
1341         uint32 rowsize 
= imagewidth 
* spp
; 
1342         uint32 rowsperstrip
; 
1343         tdata_t obuf 
= _TIFFmalloc(TIFFStripSize(out
)); 
1349         (void) TIFFGetFieldDefaulted(out
, TIFFTAG_ROWSPERSTRIP
, &rowsperstrip
); 
1350         for (s 
= 0; s 
< spp
; s
++) { 
1352                 for (row 
= 0; row 
< imagelength
; row 
+= rowsperstrip
) { 
1353                         uint32 nrows 
= (row
+rowsperstrip 
> imagelength
) ? 
1354                             imagelength
-row 
: rowsperstrip
; 
1355                         tsize_t stripsize 
= TIFFVStripSize(out
, nrows
); 
1357                         cpContigBufToSeparateBuf( 
1358                             obuf
, (uint8
*) buf 
+ row
*rowsize 
+ s
,  
1359                             nrows
, imagewidth
, 0, 0, spp
, 1); 
1360                         if (TIFFWriteEncodedStrip(out
, strip
++, obuf
, stripsize
) < 0) { 
1361                                 TIFFError(TIFFFileName(out
), 
1362                                           "Error, can't write strip %lu", 
1374 DECLAREwriteFunc(writeBufferToContigTiles
) 
1376         uint32 imagew 
= TIFFScanlineSize(out
); 
1377         uint32 tilew  
= TIFFTileRowSize(out
); 
1378         int iskew 
= imagew 
- tilew
; 
1379         tdata_t obuf 
= _TIFFmalloc(TIFFTileSize(out
)); 
1380         uint8
* bufp 
= (uint8
*) buf
; 
1387         (void) TIFFGetField(out
, TIFFTAG_TILELENGTH
, &tl
); 
1388         (void) TIFFGetField(out
, TIFFTAG_TILEWIDTH
, &tw
); 
1389         for (row 
= 0; row 
< imagelength
; row 
+= tilelength
) { 
1390                 uint32 nrow 
= (row
+tl 
> imagelength
) ? imagelength
-row 
: tl
; 
1394                 for (col 
= 0; col 
< imagewidth
; col 
+= tw
) { 
1396                          * Tile is clipped horizontally.  Calculate 
1397                          * visible portion and skewing factors. 
1399                         if (colb 
+ tilew 
> imagew
) { 
1400                                 uint32 width 
= imagew 
- colb
; 
1401                                 int oskew 
= tilew 
- width
; 
1402                                 cpStripToTile(obuf
, bufp 
+ colb
, nrow
, width
, 
1403                                     oskew
, oskew 
+ iskew
); 
1405                                 cpStripToTile(obuf
, bufp 
+ colb
, nrow
, tilew
, 
1407                         if (TIFFWriteTile(out
, obuf
, col
, row
, 0, 0) < 0) { 
1408                                 TIFFError(TIFFFileName(out
), 
1409                                           "Error, can't write tile at %lu %lu", 
1410                                           (unsigned long) col
, 
1411                                           (unsigned long) row
); 
1417                 bufp 
+= nrow 
* imagew
; 
1423 DECLAREwriteFunc(writeBufferToSeparateTiles
) 
1425         uint32 imagew 
= TIFFScanlineSize(out
); 
1426         tsize_t tilew  
= TIFFTileRowSize(out
); 
1427         uint32 iimagew 
= TIFFRasterScanlineSize(out
); 
1428         int iskew 
= iimagew 
- tilew
*spp
; 
1429         tdata_t obuf 
= _TIFFmalloc(TIFFTileSize(out
)); 
1430         uint8
* bufp 
= (uint8
*) buf
; 
1433         uint16 bps
, bytes_per_sample
; 
1437         (void) TIFFGetField(out
, TIFFTAG_TILELENGTH
, &tl
); 
1438         (void) TIFFGetField(out
, TIFFTAG_TILEWIDTH
, &tw
); 
1439         (void) TIFFGetField(out
, TIFFTAG_BITSPERSAMPLE
, &bps
); 
1440         assert( bps 
% 8 == 0 ); 
1441         bytes_per_sample 
= bps
/8; 
1443         for (row 
= 0; row 
< imagelength
; row 
+= tl
) { 
1444                 uint32 nrow 
= (row
+tl 
> imagelength
) ? imagelength
-row 
: tl
; 
1448                 for (col 
= 0; col 
< imagewidth
; col 
+= tw
) { 
1450                         for (s 
= 0; s 
< spp
; s
++) { 
1452                                  * Tile is clipped horizontally.  Calculate 
1453                                  * visible portion and skewing factors. 
1455                                 if (colb 
+ tilew 
> imagew
) { 
1456                                         uint32 width 
= (imagew 
- colb
); 
1457                                         int oskew 
= tilew 
- width
; 
1459                                         cpContigBufToSeparateBuf(obuf
, 
1460                                             bufp 
+ (colb
*spp
) + s
, 
1461                                             nrow
, width
/bytes_per_sample
, 
1462                                             oskew
, (oskew
*spp
)+iskew
, spp
, 
1465                                         cpContigBufToSeparateBuf(obuf
, 
1466                                             bufp 
+ (colb
*spp
) + s
, 
1470                                 if (TIFFWriteTile(out
, obuf
, col
, row
, 0, s
) < 0) { 
1471                                         TIFFError(TIFFFileName(out
), 
1472                                         "Error, can't write tile at %lu %lu " 
1474                                         (unsigned long) col
, 
1475                                         (unsigned long) row
, 
1483                 bufp 
+= nrow 
* iimagew
; 
1490  * Contig strips -> contig tiles. 
1492 DECLAREcpFunc(cpContigStrips2ContigTiles
) 
1494         return cpImage(in
, out
, 
1495             readContigStripsIntoBuffer
, 
1496             writeBufferToContigTiles
, 
1497             imagelength
, imagewidth
, spp
); 
1501  * Contig strips -> separate tiles. 
1503 DECLAREcpFunc(cpContigStrips2SeparateTiles
) 
1505         return cpImage(in
, out
, 
1506             readContigStripsIntoBuffer
, 
1507             writeBufferToSeparateTiles
, 
1508             imagelength
, imagewidth
, spp
); 
1512  * Separate strips -> contig tiles. 
1514 DECLAREcpFunc(cpSeparateStrips2ContigTiles
) 
1516         return cpImage(in
, out
, 
1517             readSeparateStripsIntoBuffer
, 
1518             writeBufferToContigTiles
, 
1519             imagelength
, imagewidth
, spp
); 
1523  * Separate strips -> separate tiles. 
1525 DECLAREcpFunc(cpSeparateStrips2SeparateTiles
) 
1527         return cpImage(in
, out
, 
1528             readSeparateStripsIntoBuffer
, 
1529             writeBufferToSeparateTiles
, 
1530             imagelength
, imagewidth
, spp
); 
1534  * Contig strips -> contig tiles. 
1536 DECLAREcpFunc(cpContigTiles2ContigTiles
) 
1538         return cpImage(in
, out
, 
1539             readContigTilesIntoBuffer
, 
1540             writeBufferToContigTiles
, 
1541             imagelength
, imagewidth
, spp
); 
1545  * Contig tiles -> separate tiles. 
1547 DECLAREcpFunc(cpContigTiles2SeparateTiles
) 
1549         return cpImage(in
, out
, 
1550             readContigTilesIntoBuffer
, 
1551             writeBufferToSeparateTiles
, 
1552             imagelength
, imagewidth
, spp
); 
1556  * Separate tiles -> contig tiles. 
1558 DECLAREcpFunc(cpSeparateTiles2ContigTiles
) 
1560         return cpImage(in
, out
, 
1561             readSeparateTilesIntoBuffer
, 
1562             writeBufferToContigTiles
, 
1563             imagelength
, imagewidth
, spp
); 
1567  * Separate tiles -> separate tiles (tile dimension change). 
1569 DECLAREcpFunc(cpSeparateTiles2SeparateTiles
) 
1571         return cpImage(in
, out
, 
1572             readSeparateTilesIntoBuffer
, 
1573             writeBufferToSeparateTiles
, 
1574             imagelength
, imagewidth
, spp
); 
1578  * Contig tiles -> contig tiles (tile dimension change). 
1580 DECLAREcpFunc(cpContigTiles2ContigStrips
) 
1582         return cpImage(in
, out
, 
1583             readContigTilesIntoBuffer
, 
1584             writeBufferToContigStrips
, 
1585             imagelength
, imagewidth
, spp
); 
1589  * Contig tiles -> separate strips. 
1591 DECLAREcpFunc(cpContigTiles2SeparateStrips
) 
1593         return cpImage(in
, out
, 
1594             readContigTilesIntoBuffer
, 
1595             writeBufferToSeparateStrips
, 
1596             imagelength
, imagewidth
, spp
); 
1600  * Separate tiles -> contig strips. 
1602 DECLAREcpFunc(cpSeparateTiles2ContigStrips
) 
1604         return cpImage(in
, out
, 
1605             readSeparateTilesIntoBuffer
, 
1606             writeBufferToContigStrips
, 
1607             imagelength
, imagewidth
, spp
); 
1611  * Separate tiles -> separate strips. 
1613 DECLAREcpFunc(cpSeparateTiles2SeparateStrips
) 
1615         return cpImage(in
, out
, 
1616             readSeparateTilesIntoBuffer
, 
1617             writeBufferToSeparateStrips
, 
1618             imagelength
, imagewidth
, spp
); 
1622  * Select the appropriate copy function to use. 
1625 pickCopyFunc(TIFF
* in
, TIFF
* out
, uint16 bitspersample
, uint16 samplesperpixel
) 
1628         uint32 w
, l
, tw
, tl
; 
1631         (void) TIFFGetField(in
, TIFFTAG_PLANARCONFIG
, &shortv
); 
1632         if (shortv 
!= config 
&& bitspersample 
!= 8 && samplesperpixel 
> 1) { 
1634 "%s: Cannot handle different planar configuration w/ bits/sample != 8\n", 
1638         TIFFGetField(in
, TIFFTAG_IMAGEWIDTH
, &w
); 
1639         TIFFGetField(in
, TIFFTAG_IMAGELENGTH
, &l
); 
1640         if (!(TIFFIsTiled(out
) || TIFFIsTiled(in
))) { 
1641             uint32 irps 
= (uint32
) -1L; 
1642             TIFFGetField(in
, TIFFTAG_ROWSPERSTRIP
, &irps
); 
1643             /* if biased, force decoded copying to allow image subtraction */ 
1644             bychunk 
= !bias 
&& (rowsperstrip 
== irps
); 
1645         }else{  /* either in or out is tiled */ 
1648 "%s: Cannot handle tiled configuration w/bias image\n", 
1652             if (TIFFIsTiled(out
)) { 
1653                 if (!TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tw
)) 
1655                 if (!TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tl
)) 
1657                 bychunk 
= (tw 
== tilewidth 
&& tl 
== tilelength
); 
1658             } else {  /* out's not, so in must be tiled */ 
1659                 TIFFGetField(in
, TIFFTAG_TILEWIDTH
, &tw
); 
1660                 TIFFGetField(in
, TIFFTAG_TILELENGTH
, &tl
); 
1661                 bychunk 
= (tw 
== w 
&& tl 
== rowsperstrip
); 
1666 #define pack(a,b,c,d,e) ((long)(((a)<<11)|((b)<<3)|((c)<<2)|((d)<<1)|(e))) 
1667         switch(pack(shortv
,config
,TIFFIsTiled(in
),TIFFIsTiled(out
),bychunk
)) { 
1668 /* Strips -> Tiles */ 
1669         case pack(PLANARCONFIG_CONTIG
,   PLANARCONFIG_CONTIG
,   F
,T
,F
): 
1670         case pack(PLANARCONFIG_CONTIG
,   PLANARCONFIG_CONTIG
,   F
,T
,T
): 
1671                 return cpContigStrips2ContigTiles
; 
1672         case pack(PLANARCONFIG_CONTIG
,   PLANARCONFIG_SEPARATE
, F
,T
,F
): 
1673         case pack(PLANARCONFIG_CONTIG
,   PLANARCONFIG_SEPARATE
, F
,T
,T
): 
1674                 return cpContigStrips2SeparateTiles
; 
1675         case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
,   F
,T
,F
): 
1676         case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
,   F
,T
,T
): 
1677                 return cpSeparateStrips2ContigTiles
; 
1678         case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, F
,T
,F
): 
1679         case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, F
,T
,T
): 
1680                 return cpSeparateStrips2SeparateTiles
; 
1681 /* Tiles -> Tiles */ 
1682         case pack(PLANARCONFIG_CONTIG
,   PLANARCONFIG_CONTIG
,   T
,T
,F
): 
1683         case pack(PLANARCONFIG_CONTIG
,   PLANARCONFIG_CONTIG
,   T
,T
,T
): 
1684                 return cpContigTiles2ContigTiles
; 
1685         case pack(PLANARCONFIG_CONTIG
,   PLANARCONFIG_SEPARATE
, T
,T
,F
): 
1686         case pack(PLANARCONFIG_CONTIG
,   PLANARCONFIG_SEPARATE
, T
,T
,T
): 
1687                 return cpContigTiles2SeparateTiles
; 
1688         case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
,   T
,T
,F
): 
1689         case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
,   T
,T
,T
): 
1690                 return cpSeparateTiles2ContigTiles
; 
1691         case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, T
,T
,F
): 
1692         case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, T
,T
,T
): 
1693                 return cpSeparateTiles2SeparateTiles
; 
1694 /* Tiles -> Strips */ 
1695         case pack(PLANARCONFIG_CONTIG
,   PLANARCONFIG_CONTIG
,   T
,F
,F
): 
1696         case pack(PLANARCONFIG_CONTIG
,   PLANARCONFIG_CONTIG
,   T
,F
,T
): 
1697                 return cpContigTiles2ContigStrips
; 
1698         case pack(PLANARCONFIG_CONTIG
,   PLANARCONFIG_SEPARATE
, T
,F
,F
): 
1699         case pack(PLANARCONFIG_CONTIG
,   PLANARCONFIG_SEPARATE
, T
,F
,T
): 
1700                 return cpContigTiles2SeparateStrips
; 
1701         case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
,   T
,F
,F
): 
1702         case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
,   T
,F
,T
): 
1703                 return cpSeparateTiles2ContigStrips
; 
1704         case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, T
,F
,F
): 
1705         case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, T
,F
,T
): 
1706                 return cpSeparateTiles2SeparateStrips
; 
1707 /* Strips -> Strips */ 
1708         case pack(PLANARCONFIG_CONTIG
,   PLANARCONFIG_CONTIG
,   F
,F
,F
): 
1709                 return bias 
? cpBiasedContig2Contig 
: cpContig2ContigByRow
; 
1710         case pack(PLANARCONFIG_CONTIG
,   PLANARCONFIG_CONTIG
,   F
,F
,T
): 
1711                 return cpDecodedStrips
; 
1712         case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
,   F
,F
,F
): 
1713         case pack(PLANARCONFIG_CONTIG
, PLANARCONFIG_SEPARATE
,   F
,F
,T
): 
1714                 return cpContig2SeparateByRow
; 
1715         case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
,   F
,F
,F
): 
1716         case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_CONTIG
,   F
,F
,T
): 
1717                 return cpSeparate2ContigByRow
; 
1718         case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, F
,F
,F
): 
1719         case pack(PLANARCONFIG_SEPARATE
, PLANARCONFIG_SEPARATE
, F
,F
,T
): 
1720                 return cpSeparate2SeparateByRow
; 
1725         fprintf(stderr
, "tiffcp: %s: Don't know how to copy/convert image.\n", 
1730 /* vim: set ts=8 sts=8 sw=8 noet: */