New comit of SDL2
[supertux.git] / src / SDL2 / external / tiff-4.0.3 / tools / tiffcp.c
1 /* $Id: tiffcp.c,v 1.49 2010-12-23 13:38:47 dron Exp $ */
2
3 /*
4  * Copyright (c) 1988-1997 Sam Leffler
5  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
6  *
7  *  Revised:  2/18/01 BAR -- added syntax for extracting single images from
8  *                          multi-image TIFF files.
9  *
10  *    New syntax is:  sourceFileName,image#
11  *
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
14  * image number.
15  *
16  *    Example:   tiffcp source.tif,1 destination.tif
17  *
18  * Copies the 2nd image in source.tif to the destination.
19  *
20  *****
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.
28  * 
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.  
32  * 
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 
38  * OF THIS SOFTWARE.
39  */
40
41 #include "tif_config.h"
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46
47 #include <ctype.h>
48 #include <assert.h>
49
50 #ifdef HAVE_UNISTD_H
51 # include <unistd.h>
52 #endif
53
54 #include "tiffio.h"
55
56 #ifndef HAVE_GETOPT
57 extern int getopt(int, char**, char*);
58 #endif
59
60 #if defined(VMS)
61 # define unlink delete
62 #endif
63
64 #define streq(a,b)      (strcmp(a,b) == 0)
65 #define strneq(a,b,n)   (strncmp(a,b,n) == 0)
66
67 #define TRUE    1
68 #define FALSE   0
69
70 static int outtiled = -1;
71 static uint32 tilewidth;
72 static uint32 tilelength;
73
74 static uint16 config;
75 static uint16 compression;
76 static uint16 predictor;
77 static int preset;
78 static uint16 fillorder;
79 static uint16 orientation;
80 static uint32 rowsperstrip;
81 static uint32 g3opts;
82 static int ignore = FALSE;              /* if true, ignore read errors */
83 static uint32 defg3opts = (uint32) -1;
84 static int quality = 75;                /* JPEG quality */
85 static int jpegcolormode = JPEGCOLORMODE_RGB;
86 static uint16 defcompression = (uint16) -1;
87 static uint16 defpredictor = (uint16) -1;
88 static int defpreset =  -1;
89
90 static int tiffcp(TIFF*, TIFF*);
91 static int processCompressOptions(char*);
92 static void usage(void);
93
94 static char comma = ',';  /* (default) comma separator character */
95 static TIFF* bias = NULL;
96 static int pageNum = 0;
97 static int pageInSeq = 0;
98
99 static int nextSrcImage (TIFF *tif, char **imageSpec)
100 /*
101   seek to the next image specified in *imageSpec
102   returns 1 if success, 0 if no more images to process
103   *imageSpec=NULL if subsequent images should be processed in sequence
104 */
105 {
106         if (**imageSpec == comma) {  /* if not @comma, we've done all images */
107                 char *start = *imageSpec + 1;
108                 tdir_t nextImage = (tdir_t)strtol(start, imageSpec, 0);
109                 if (start == *imageSpec) nextImage = TIFFCurrentDirectory (tif);
110                 if (**imageSpec)
111                 {
112                         if (**imageSpec == comma) {
113                                 /* a trailing comma denotes remaining images in sequence */
114                                 if ((*imageSpec)[1] == '\0') *imageSpec = NULL;
115                         }else{
116                                 fprintf (stderr,
117                                     "Expected a %c separated image # list after %s\n",
118                                     comma, TIFFFileName (tif));
119                                 exit (-4);   /* syntax error */
120                         }
121                 }
122                 if (TIFFSetDirectory (tif, nextImage)) return 1;
123                 fprintf (stderr, "%s%c%d not found!\n",
124                     TIFFFileName(tif), comma, (int) nextImage);
125         }
126         return 0;
127 }
128
129   
130 static TIFF* openSrcImage (char **imageSpec)
131 /*
132   imageSpec points to a pointer to a filename followed by optional ,image#'s
133   Open the TIFF file and assign *imageSpec to either NULL if there are
134   no images specified, or a pointer to the next image number text
135 */
136 {
137         TIFF *tif;
138         char *fn = *imageSpec;
139         *imageSpec = strchr (fn, comma);
140         if (*imageSpec) {  /* there is at least one image number specifier */
141                 **imageSpec = '\0';
142                 tif = TIFFOpen (fn, "r");
143                 /* but, ignore any single trailing comma */
144                 if (!(*imageSpec)[1]) {*imageSpec = NULL; return tif;}
145                 if (tif) {
146                         **imageSpec = comma;  /* replace the comma */
147                         if (!nextSrcImage(tif, imageSpec)) {
148                                 TIFFClose (tif);
149                                 tif = NULL;
150                         }
151                 }
152         }else
153                 tif = TIFFOpen (fn, "r");
154         return tif;
155 }
156
157 int
158 main(int argc, char* argv[])
159 {
160         uint16 defconfig = (uint16) -1;
161         uint16 deffillorder = 0;
162         uint32 deftilewidth = (uint32) -1;
163         uint32 deftilelength = (uint32) -1;
164         uint32 defrowsperstrip = (uint32) 0;
165         uint64 diroff = 0;
166         TIFF* in;
167         TIFF* out;
168         char mode[10];
169         char* mp = mode;
170         int c;
171         extern int optind;
172         extern char* optarg;
173
174         *mp++ = 'w';
175         *mp = '\0';
176         while ((c = getopt(argc, argv, ",:b:c:f:l:o:z:p:r:w:aistBLMC8x")) != -1)
177                 switch (c) {
178                 case ',':
179                         if (optarg[0] != '=') usage();
180                         comma = optarg[1];
181                         break;
182                 case 'b':   /* this file is bias image subtracted from others */
183                         if (bias) {
184                                 fputs ("Only 1 bias image may be specified\n", stderr);
185                                 exit (-2);
186                         }
187                         {
188                                 uint16 samples = (uint16) -1;
189                                 char **biasFn = &optarg;
190                                 bias = openSrcImage (biasFn);
191                                 if (!bias) exit (-5);
192                                 if (TIFFIsTiled (bias)) {
193                                         fputs ("Bias image must be organized in strips\n", stderr);
194                                         exit (-7);
195                                 }
196                                 TIFFGetField(bias, TIFFTAG_SAMPLESPERPIXEL, &samples);
197                                 if (samples != 1) {
198                                         fputs ("Bias image must be monochrome\n", stderr);
199                                         exit (-7);
200                                 }
201                         }
202                         break;
203                 case 'a':   /* append to output */
204                         mode[0] = 'a';
205                         break;
206                 case 'c':   /* compression scheme */
207                         if (!processCompressOptions(optarg))
208                                 usage();
209                         break;
210                 case 'f':   /* fill order */
211                         if (streq(optarg, "lsb2msb"))
212                                 deffillorder = FILLORDER_LSB2MSB;
213                         else if (streq(optarg, "msb2lsb"))
214                                 deffillorder = FILLORDER_MSB2LSB;
215                         else
216                                 usage();
217                         break;
218                 case 'i':   /* ignore errors */
219                         ignore = TRUE;
220                         break;
221                 case 'l':   /* tile length */
222                         outtiled = TRUE;
223                         deftilelength = atoi(optarg);
224                         break;
225                 case 'o':   /* initial directory offset */
226                         diroff = strtoul(optarg, NULL, 0);
227                         break;
228                 case 'p':   /* planar configuration */
229                         if (streq(optarg, "separate"))
230                                 defconfig = PLANARCONFIG_SEPARATE;
231                         else if (streq(optarg, "contig"))
232                                 defconfig = PLANARCONFIG_CONTIG;
233                         else
234                                 usage();
235                         break;
236                 case 'r':   /* rows/strip */
237                         defrowsperstrip = atol(optarg);
238                         break;
239                 case 's':   /* generate stripped output */
240                         outtiled = FALSE;
241                         break;
242                 case 't':   /* generate tiled output */
243                         outtiled = TRUE;
244                         break;
245                 case 'w':   /* tile width */
246                         outtiled = TRUE;
247                         deftilewidth = atoi(optarg);
248                         break;
249                 case 'B':
250                         *mp++ = 'b'; *mp = '\0';
251                         break;
252                 case 'L':
253                         *mp++ = 'l'; *mp = '\0';
254                         break;
255                 case 'M':
256                         *mp++ = 'm'; *mp = '\0';
257                         break;
258                 case 'C':
259                         *mp++ = 'c'; *mp = '\0';
260                         break;
261                 case '8':
262                         *mp++ = '8'; *mp = '\0';
263                         break;
264                 case 'x':
265                         pageInSeq = 1;
266                         break;
267                 case '?':
268                         usage();
269                         /*NOTREACHED*/
270                 }
271         if (argc - optind < 2)
272                 usage();
273         out = TIFFOpen(argv[argc-1], mode);
274         if (out == NULL)
275                 return (-2);
276         if ((argc - optind) == 2)
277                 pageNum = -1;
278         for (; optind < argc-1 ; optind++) {
279                 char *imageCursor = argv[optind];
280                 in = openSrcImage (&imageCursor);
281                 if (in == NULL) {
282                         (void) TIFFClose(out);
283                         return (-3);
284                 }
285                 if (diroff != 0 && !TIFFSetSubDirectory(in, diroff)) {
286                         TIFFError(TIFFFileName(in),
287                             "Error, setting subdirectory at " TIFF_UINT64_FORMAT, diroff);
288                         (void) TIFFClose(in);
289                         (void) TIFFClose(out);
290                         return (1);
291                 }
292                 for (;;) {
293                         config = defconfig;
294                         compression = defcompression;
295                         predictor = defpredictor;
296                         preset = defpreset;
297                         fillorder = deffillorder;
298                         rowsperstrip = defrowsperstrip;
299                         tilewidth = deftilewidth;
300                         tilelength = deftilelength;
301                         g3opts = defg3opts;
302                         if (!tiffcp(in, out) || !TIFFWriteDirectory(out)) {
303                                 (void) TIFFClose(in);
304                                 (void) TIFFClose(out);
305                                 return (1);
306                         }
307                         if (imageCursor) { /* seek next image directory */
308                                 if (!nextSrcImage(in, &imageCursor)) break;
309                         }else
310                                 if (!TIFFReadDirectory(in)) break;
311                 }
312                 (void) TIFFClose(in);
313         }
314
315         (void) TIFFClose(out);
316         return (0);
317 }
318
319 static void
320 processZIPOptions(char* cp)
321 {
322         if ( (cp = strchr(cp, ':')) ) {
323                 do {
324                         cp++;
325                         if (isdigit((int)*cp))
326                                 defpredictor = atoi(cp);
327                         else if (*cp == 'p')
328                                 defpreset = atoi(++cp);
329                         else
330                                 usage();
331                 } while( (cp = strchr(cp, ':')) );
332         }
333 }
334
335 static void
336 processG3Options(char* cp)
337 {
338         if( (cp = strchr(cp, ':')) ) {
339                 if (defg3opts == (uint32) -1)
340                         defg3opts = 0;
341                 do {
342                         cp++;
343                         if (strneq(cp, "1d", 2))
344                                 defg3opts &= ~GROUP3OPT_2DENCODING;
345                         else if (strneq(cp, "2d", 2))
346                                 defg3opts |= GROUP3OPT_2DENCODING;
347                         else if (strneq(cp, "fill", 4))
348                                 defg3opts |= GROUP3OPT_FILLBITS;
349                         else
350                                 usage();
351                 } while( (cp = strchr(cp, ':')) );
352         }
353 }
354
355 static int
356 processCompressOptions(char* opt)
357 {
358         if (streq(opt, "none")) {
359                 defcompression = COMPRESSION_NONE;
360         } else if (streq(opt, "packbits")) {
361                 defcompression = COMPRESSION_PACKBITS;
362         } else if (strneq(opt, "jpeg", 4)) {
363                 char* cp = strchr(opt, ':');
364
365                 defcompression = COMPRESSION_JPEG;
366                 while( cp )
367                 {
368                         if (isdigit((int)cp[1]))
369                                 quality = atoi(cp+1);
370                         else if (cp[1] == 'r' )
371                                 jpegcolormode = JPEGCOLORMODE_RAW;
372                         else
373                                 usage();
374
375                         cp = strchr(cp+1,':');
376                 }
377         } else if (strneq(opt, "g3", 2)) {
378                 processG3Options(opt);
379                 defcompression = COMPRESSION_CCITTFAX3;
380         } else if (streq(opt, "g4")) {
381                 defcompression = COMPRESSION_CCITTFAX4;
382         } else if (strneq(opt, "lzw", 3)) {
383                 char* cp = strchr(opt, ':');
384                 if (cp)
385                         defpredictor = atoi(cp+1);
386                 defcompression = COMPRESSION_LZW;
387         } else if (strneq(opt, "zip", 3)) {
388                 processZIPOptions(opt);
389                 defcompression = COMPRESSION_ADOBE_DEFLATE;
390         } else if (strneq(opt, "lzma", 4)) {
391                 processZIPOptions(opt);
392                 defcompression = COMPRESSION_LZMA;
393         } else if (strneq(opt, "jbig", 4)) {
394                 defcompression = COMPRESSION_JBIG;
395         } else if (strneq(opt, "sgilog", 6)) {
396                 defcompression = COMPRESSION_SGILOG;
397         } else
398                 return (0);
399         return (1);
400 }
401
402 char* stuff[] = {
403 "usage: tiffcp [options] input... output",
404 "where options are:",
405 " -a              append to output instead of overwriting",
406 " -o offset       set initial directory offset",
407 " -p contig       pack samples contiguously (e.g. RGBRGB...)",
408 " -p separate     store samples separately (e.g. RRR...GGG...BBB...)",
409 " -s              write output in strips",
410 " -t              write output in tiles",
411 " -8              write BigTIFF instead of default ClassicTIFF",
412 " -i              ignore read errors",
413 " -b file[,#]     bias (dark) monochrome image to be subtracted from all others",
414 " -,=%            use % rather than , to separate image #'s (per Note below)",
415 "",
416 " -r #            make each strip have no more than # rows",
417 " -w #            set output tile width (pixels)",
418 " -l #            set output tile length (pixels)",
419 "",
420 " -f lsb2msb      force lsb-to-msb FillOrder for output",
421 " -f msb2lsb      force msb-to-lsb FillOrder for output",
422 "",
423 " -c lzw[:opts]   compress output with Lempel-Ziv & Welch encoding",
424 " -c zip[:opts]   compress output with deflate encoding",
425 " -c lzma[:opts]  compress output with LZMA2 encoding",
426 " -c jpeg[:opts]  compress output with JPEG encoding",
427 " -c jbig         compress output with ISO JBIG encoding",
428 " -c packbits     compress output with packbits encoding",
429 " -c g3[:opts]    compress output with CCITT Group 3 encoding",
430 " -c g4           compress output with CCITT Group 4 encoding",
431 " -c sgilog       compress output with SGILOG encoding",
432 " -c none         use no compression algorithm on output",
433 " -x              force the merged tiff pages in sequence",
434 "",
435 "Group 3 options:",
436 " 1d              use default CCITT Group 3 1D-encoding",
437 " 2d              use optional CCITT Group 3 2D-encoding",
438 " fill            byte-align EOL codes",
439 "For example, -c g3:2d:fill to get G3-2D-encoded data with byte-aligned EOLs",
440 "",
441 "JPEG options:",
442 " #               set compression quality level (0-100, default 75)",
443 " r               output color image as RGB rather than YCbCr",
444 "For example, -c jpeg:r:50 to get JPEG-encoded RGB data with 50% comp. quality",
445 "",
446 "LZW, Deflate (ZIP) and LZMA2 options:",
447 " #               set predictor value",
448 " p#              set compression level (preset)",
449 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing,",
450 "-c zip:3:p9 for Deflate encoding with maximum compression level and floating",
451 "point predictor.",
452 "",
453 "Note that input filenames may be of the form filename,x,y,z",
454 "where x, y, and z specify image numbers in the filename to copy.",
455 "example:  tiffcp -c none -b esp.tif,1 esp.tif,0 test.tif",
456 "  subtract 2nd image in esp.tif from 1st yielding uncompressed result test.tif",
457 NULL
458 };
459
460 static void
461 usage(void)
462 {
463         char buf[BUFSIZ];
464         int i;
465
466         setbuf(stderr, buf);
467         fprintf(stderr, "%s\n\n", TIFFGetVersion());
468         for (i = 0; stuff[i] != NULL; i++)
469                 fprintf(stderr, "%s\n", stuff[i]);
470         exit(-1);
471 }
472
473 #define CopyField(tag, v) \
474     if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
475 #define CopyField2(tag, v1, v2) \
476     if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
477 #define CopyField3(tag, v1, v2, v3) \
478     if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
479 #define CopyField4(tag, v1, v2, v3, v4) \
480     if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4)
481
482 static void
483 cpTag(TIFF* in, TIFF* out, uint16 tag, uint16 count, TIFFDataType type)
484 {
485         switch (type) {
486         case TIFF_SHORT:
487                 if (count == 1) {
488                         uint16 shortv;
489                         CopyField(tag, shortv);
490                 } else if (count == 2) {
491                         uint16 shortv1, shortv2;
492                         CopyField2(tag, shortv1, shortv2);
493                 } else if (count == 4) {
494                         uint16 *tr, *tg, *tb, *ta;
495                         CopyField4(tag, tr, tg, tb, ta);
496                 } else if (count == (uint16) -1) {
497                         uint16 shortv1;
498                         uint16* shortav;
499                         CopyField2(tag, shortv1, shortav);
500                 }
501                 break;
502         case TIFF_LONG:
503                 { uint32 longv;
504                   CopyField(tag, longv);
505                 }
506                 break;
507         case TIFF_RATIONAL:
508                 if (count == 1) {
509                         float floatv;
510                         CopyField(tag, floatv);
511                 } else if (count == (uint16) -1) {
512                         float* floatav;
513                         CopyField(tag, floatav);
514                 }
515                 break;
516         case TIFF_ASCII:
517                 { char* stringv;
518                   CopyField(tag, stringv);
519                 }
520                 break;
521         case TIFF_DOUBLE:
522                 if (count == 1) {
523                         double doublev;
524                         CopyField(tag, doublev);
525                 } else if (count == (uint16) -1) {
526                         double* doubleav;
527                         CopyField(tag, doubleav);
528                 }
529                 break;
530         default:
531                 TIFFError(TIFFFileName(in),
532                     "Data type %d is not supported, tag %d skipped.",
533                     tag, type);
534         }
535 }
536
537 static struct cpTag {
538         uint16 tag;
539         uint16 count;
540         TIFFDataType type;
541 } tags[] = {
542         { TIFFTAG_SUBFILETYPE,          1, TIFF_LONG },
543         { TIFFTAG_THRESHHOLDING,        1, TIFF_SHORT },
544         { TIFFTAG_DOCUMENTNAME,         1, TIFF_ASCII },
545         { TIFFTAG_IMAGEDESCRIPTION,     1, TIFF_ASCII },
546         { TIFFTAG_MAKE,                 1, TIFF_ASCII },
547         { TIFFTAG_MODEL,                1, TIFF_ASCII },
548         { TIFFTAG_MINSAMPLEVALUE,       1, TIFF_SHORT },
549         { TIFFTAG_MAXSAMPLEVALUE,       1, TIFF_SHORT },
550         { TIFFTAG_XRESOLUTION,          1, TIFF_RATIONAL },
551         { TIFFTAG_YRESOLUTION,          1, TIFF_RATIONAL },
552         { TIFFTAG_PAGENAME,             1, TIFF_ASCII },
553         { TIFFTAG_XPOSITION,            1, TIFF_RATIONAL },
554         { TIFFTAG_YPOSITION,            1, TIFF_RATIONAL },
555         { TIFFTAG_RESOLUTIONUNIT,       1, TIFF_SHORT },
556         { TIFFTAG_SOFTWARE,             1, TIFF_ASCII },
557         { TIFFTAG_DATETIME,             1, TIFF_ASCII },
558         { TIFFTAG_ARTIST,               1, TIFF_ASCII },
559         { TIFFTAG_HOSTCOMPUTER,         1, TIFF_ASCII },
560         { TIFFTAG_WHITEPOINT,           (uint16) -1, TIFF_RATIONAL },
561         { TIFFTAG_PRIMARYCHROMATICITIES,(uint16) -1,TIFF_RATIONAL },
562         { TIFFTAG_HALFTONEHINTS,        2, TIFF_SHORT },
563         { TIFFTAG_INKSET,               1, TIFF_SHORT },
564         { TIFFTAG_DOTRANGE,             2, TIFF_SHORT },
565         { TIFFTAG_TARGETPRINTER,        1, TIFF_ASCII },
566         { TIFFTAG_SAMPLEFORMAT,         1, TIFF_SHORT },
567         { TIFFTAG_YCBCRCOEFFICIENTS,    (uint16) -1,TIFF_RATIONAL },
568         { TIFFTAG_YCBCRSUBSAMPLING,     2, TIFF_SHORT },
569         { TIFFTAG_YCBCRPOSITIONING,     1, TIFF_SHORT },
570         { TIFFTAG_REFERENCEBLACKWHITE,  (uint16) -1,TIFF_RATIONAL },
571         { TIFFTAG_EXTRASAMPLES,         (uint16) -1, TIFF_SHORT },
572         { TIFFTAG_SMINSAMPLEVALUE,      1, TIFF_DOUBLE },
573         { TIFFTAG_SMAXSAMPLEVALUE,      1, TIFF_DOUBLE },
574         { TIFFTAG_STONITS,              1, TIFF_DOUBLE },
575 };
576 #define NTAGS   (sizeof (tags) / sizeof (tags[0]))
577
578 #define CopyTag(tag, count, type)       cpTag(in, out, tag, count, type)
579
580 typedef int (*copyFunc)
581     (TIFF* in, TIFF* out, uint32 l, uint32 w, uint16 samplesperpixel);
582 static  copyFunc pickCopyFunc(TIFF*, TIFF*, uint16, uint16);
583
584 /* PODD */
585
586 static int
587 tiffcp(TIFF* in, TIFF* out)
588 {
589         uint16 bitspersample, samplesperpixel;
590         uint16 input_compression, input_photometric;
591         copyFunc cf;
592         uint32 width, length;
593         struct cpTag* p;
594
595         CopyField(TIFFTAG_IMAGEWIDTH, width);
596         CopyField(TIFFTAG_IMAGELENGTH, length);
597         CopyField(TIFFTAG_BITSPERSAMPLE, bitspersample);
598         CopyField(TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
599         if (compression != (uint16)-1)
600                 TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
601         else
602                 CopyField(TIFFTAG_COMPRESSION, compression);
603         TIFFGetFieldDefaulted(in, TIFFTAG_COMPRESSION, &input_compression);
604         TIFFGetFieldDefaulted(in, TIFFTAG_PHOTOMETRIC, &input_photometric);
605         if (input_compression == COMPRESSION_JPEG) {
606                 /* Force conversion to RGB */
607                 TIFFSetField(in, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
608         } else if (input_photometric == PHOTOMETRIC_YCBCR) {
609                 /* Otherwise, can't handle subsampled input */
610                 uint16 subsamplinghor,subsamplingver;
611
612                 TIFFGetFieldDefaulted(in, TIFFTAG_YCBCRSUBSAMPLING,
613                                       &subsamplinghor, &subsamplingver);
614                 if (subsamplinghor!=1 || subsamplingver!=1) {
615                         fprintf(stderr, "tiffcp: %s: Can't copy/convert subsampled image.\n",
616                                 TIFFFileName(in));
617                         return FALSE;
618                 }
619         }
620         if (compression == COMPRESSION_JPEG) {
621                 if (input_photometric == PHOTOMETRIC_RGB &&
622                     jpegcolormode == JPEGCOLORMODE_RGB)
623                   TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
624                 else
625                   TIFFSetField(out, TIFFTAG_PHOTOMETRIC, input_photometric);
626         }
627         else if (compression == COMPRESSION_SGILOG
628             || compression == COMPRESSION_SGILOG24)
629                 TIFFSetField(out, TIFFTAG_PHOTOMETRIC,
630                     samplesperpixel == 1 ?
631                     PHOTOMETRIC_LOGL : PHOTOMETRIC_LOGLUV);
632         else
633                 CopyTag(TIFFTAG_PHOTOMETRIC, 1, TIFF_SHORT);
634         if (fillorder != 0)
635                 TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
636         else
637                 CopyTag(TIFFTAG_FILLORDER, 1, TIFF_SHORT);
638         /*
639          * Will copy `Orientation' tag from input image
640          */
641         TIFFGetFieldDefaulted(in, TIFFTAG_ORIENTATION, &orientation);
642         switch (orientation) {
643                 case ORIENTATION_BOTRIGHT:
644                 case ORIENTATION_RIGHTBOT:      /* XXX */
645                         TIFFWarning(TIFFFileName(in), "using bottom-left orientation");
646                         orientation = ORIENTATION_BOTLEFT;
647                 /* fall thru... */
648                 case ORIENTATION_LEFTBOT:       /* XXX */
649                 case ORIENTATION_BOTLEFT:
650                         break;
651                 case ORIENTATION_TOPRIGHT:
652                 case ORIENTATION_RIGHTTOP:      /* XXX */
653                 default:
654                         TIFFWarning(TIFFFileName(in), "using top-left orientation");
655                         orientation = ORIENTATION_TOPLEFT;
656                 /* fall thru... */
657                 case ORIENTATION_LEFTTOP:       /* XXX */
658                 case ORIENTATION_TOPLEFT:
659                         break;
660         }
661         TIFFSetField(out, TIFFTAG_ORIENTATION, orientation);
662         /*
663          * Choose tiles/strip for the output image according to
664          * the command line arguments (-tiles, -strips) and the
665          * structure of the input image.
666          */
667         if (outtiled == -1)
668                 outtiled = TIFFIsTiled(in);
669         if (outtiled) {
670                 /*
671                  * Setup output file's tile width&height.  If either
672                  * is not specified, use either the value from the
673                  * input image or, if nothing is defined, use the
674                  * library default.
675                  */
676                 if (tilewidth == (uint32) -1)
677                         TIFFGetField(in, TIFFTAG_TILEWIDTH, &tilewidth);
678                 if (tilelength == (uint32) -1)
679                         TIFFGetField(in, TIFFTAG_TILELENGTH, &tilelength);
680                 TIFFDefaultTileSize(out, &tilewidth, &tilelength);
681                 TIFFSetField(out, TIFFTAG_TILEWIDTH, tilewidth);
682                 TIFFSetField(out, TIFFTAG_TILELENGTH, tilelength);
683         } else {
684                 /*
685                  * RowsPerStrip is left unspecified: use either the
686                  * value from the input image or, if nothing is defined,
687                  * use the library default.
688                  */
689                 if (rowsperstrip == (uint32) 0) {
690                         if (!TIFFGetField(in, TIFFTAG_ROWSPERSTRIP,
691                             &rowsperstrip)) {
692                                 rowsperstrip =
693                                     TIFFDefaultStripSize(out, rowsperstrip);
694                         }
695                         if (rowsperstrip > length && rowsperstrip != (uint32)-1)
696                                 rowsperstrip = length;
697                 }
698                 else if (rowsperstrip == (uint32) -1)
699                         rowsperstrip = length;
700                 TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
701         }
702         if (config != (uint16) -1)
703                 TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
704         else
705                 CopyField(TIFFTAG_PLANARCONFIG, config);
706         if (samplesperpixel <= 4)
707                 CopyTag(TIFFTAG_TRANSFERFUNCTION, 4, TIFF_SHORT);
708         CopyTag(TIFFTAG_COLORMAP, 4, TIFF_SHORT);
709 /* SMinSampleValue & SMaxSampleValue */
710         switch (compression) {
711                 case COMPRESSION_JPEG:
712                         TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
713                         TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode);
714                         break;
715                 case COMPRESSION_JBIG:
716                         CopyTag(TIFFTAG_FAXRECVPARAMS, 1, TIFF_LONG);
717                         CopyTag(TIFFTAG_FAXRECVTIME, 1, TIFF_LONG);
718                         CopyTag(TIFFTAG_FAXSUBADDRESS, 1, TIFF_ASCII);
719                         CopyTag(TIFFTAG_FAXDCS, 1, TIFF_ASCII);
720                         break;
721                 case COMPRESSION_LZW:
722                 case COMPRESSION_ADOBE_DEFLATE:
723                 case COMPRESSION_DEFLATE:
724                 case COMPRESSION_LZMA:
725                         if (predictor != (uint16)-1)
726                                 TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
727                         else
728                                 CopyField(TIFFTAG_PREDICTOR, predictor);
729                         if (preset != -1) {
730                                 if (compression == COMPRESSION_ADOBE_DEFLATE
731                                          || compression == COMPRESSION_DEFLATE)
732                                         TIFFSetField(out, TIFFTAG_ZIPQUALITY, preset);
733                                 else if (compression == COMPRESSION_LZMA)
734                                         TIFFSetField(out, TIFFTAG_LZMAPRESET, preset);
735                         }
736                         break;
737                 case COMPRESSION_CCITTFAX3:
738                 case COMPRESSION_CCITTFAX4:
739                         if (compression == COMPRESSION_CCITTFAX3) {
740                                 if (g3opts != (uint32) -1)
741                                         TIFFSetField(out, TIFFTAG_GROUP3OPTIONS,
742                                             g3opts);
743                                 else
744                                         CopyField(TIFFTAG_GROUP3OPTIONS, g3opts);
745                         } else
746                                 CopyTag(TIFFTAG_GROUP4OPTIONS, 1, TIFF_LONG);
747                         CopyTag(TIFFTAG_BADFAXLINES, 1, TIFF_LONG);
748                         CopyTag(TIFFTAG_CLEANFAXDATA, 1, TIFF_LONG);
749                         CopyTag(TIFFTAG_CONSECUTIVEBADFAXLINES, 1, TIFF_LONG);
750                         CopyTag(TIFFTAG_FAXRECVPARAMS, 1, TIFF_LONG);
751                         CopyTag(TIFFTAG_FAXRECVTIME, 1, TIFF_LONG);
752                         CopyTag(TIFFTAG_FAXSUBADDRESS, 1, TIFF_ASCII);
753                         break;
754         }
755         {
756                 uint32 len32;
757                 void** data;
758                 if (TIFFGetField(in, TIFFTAG_ICCPROFILE, &len32, &data))
759                         TIFFSetField(out, TIFFTAG_ICCPROFILE, len32, data);
760         }
761         {
762                 uint16 ninks;
763                 const char* inknames;
764                 if (TIFFGetField(in, TIFFTAG_NUMBEROFINKS, &ninks)) {
765                         TIFFSetField(out, TIFFTAG_NUMBEROFINKS, ninks);
766                         if (TIFFGetField(in, TIFFTAG_INKNAMES, &inknames)) {
767                                 int inknameslen = strlen(inknames) + 1;
768                                 const char* cp = inknames;
769                                 while (ninks > 1) {
770                                         cp = strchr(cp, '\0');
771                                         cp++;
772                                         inknameslen += (strlen(cp) + 1);
773                                         ninks--;
774                                 }
775                                 TIFFSetField(out, TIFFTAG_INKNAMES, inknameslen, inknames);
776                         }
777                 }
778         }
779         {
780                 unsigned short pg0, pg1;
781
782                 if (pageInSeq == 1) {
783                         if (pageNum < 0) /* only one input file */ {
784                                 if (TIFFGetField(in, TIFFTAG_PAGENUMBER, &pg0, &pg1))
785                                         TIFFSetField(out, TIFFTAG_PAGENUMBER, pg0, pg1);
786                         } else
787                                 TIFFSetField(out, TIFFTAG_PAGENUMBER, pageNum++, 0);
788
789                 } else {
790                         if (TIFFGetField(in, TIFFTAG_PAGENUMBER, &pg0, &pg1)) {
791                                 if (pageNum < 0) /* only one input file */
792                                         TIFFSetField(out, TIFFTAG_PAGENUMBER, pg0, pg1);
793                                 else
794                                         TIFFSetField(out, TIFFTAG_PAGENUMBER, pageNum++, 0);
795                         }
796                 }
797         }
798
799         for (p = tags; p < &tags[NTAGS]; p++)
800                 CopyTag(p->tag, p->count, p->type);
801
802         cf = pickCopyFunc(in, out, bitspersample, samplesperpixel);
803         return (cf ? (*cf)(in, out, length, width, samplesperpixel) : FALSE);
804 }
805
806 /*
807  * Copy Functions.
808  */
809 #define DECLAREcpFunc(x) \
810 static int x(TIFF* in, TIFF* out, \
811     uint32 imagelength, uint32 imagewidth, tsample_t spp)
812
813 #define DECLAREreadFunc(x) \
814 static int x(TIFF* in, \
815     uint8* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)
816 typedef int (*readFunc)(TIFF*, uint8*, uint32, uint32, tsample_t);
817
818 #define DECLAREwriteFunc(x) \
819 static int x(TIFF* out, \
820     uint8* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)
821 typedef int (*writeFunc)(TIFF*, uint8*, uint32, uint32, tsample_t);
822
823 /*
824  * Contig -> contig by scanline for rows/strip change.
825  */
826 DECLAREcpFunc(cpContig2ContigByRow)
827 {
828         tsize_t scanlinesize = TIFFScanlineSize(in);
829         tdata_t buf;
830         uint32 row;
831
832         buf = _TIFFmalloc(scanlinesize);
833         if (!buf)
834                 return 0;
835         _TIFFmemset(buf, 0, scanlinesize);
836         (void) imagewidth; (void) spp;
837         for (row = 0; row < imagelength; row++) {
838                 if (TIFFReadScanline(in, buf, row, 0) < 0 && !ignore) {
839                         TIFFError(TIFFFileName(in),
840                                   "Error, can't read scanline %lu",
841                                   (unsigned long) row);
842                         goto bad;
843                 }
844                 if (TIFFWriteScanline(out, buf, row, 0) < 0) {
845                         TIFFError(TIFFFileName(out),
846                                   "Error, can't write scanline %lu",
847                                   (unsigned long) row);
848                         goto bad;
849                 }
850         }
851         _TIFFfree(buf);
852         return 1;
853 bad:
854         _TIFFfree(buf);
855         return 0;
856 }
857
858
859 typedef void biasFn (void *image, void *bias, uint32 pixels);
860
861 #define subtract(bits) \
862 static void subtract##bits (void *i, void *b, uint32 pixels)\
863 {\
864    uint##bits *image = i;\
865    uint##bits *bias = b;\
866    while (pixels--) {\
867      *image = *image > *bias ? *image-*bias : 0;\
868      image++, bias++; \
869    } \
870 }
871
872 subtract(8)
873 subtract(16)
874 subtract(32)
875
876 static biasFn *lineSubtractFn (unsigned bits)
877 {
878         switch (bits) {
879                 case  8:  return subtract8;
880                 case 16:  return subtract16;
881                 case 32:  return subtract32;
882         }
883         return NULL;
884 }
885
886 /*
887  * Contig -> contig by scanline while subtracting a bias image.
888  */
889 DECLAREcpFunc(cpBiasedContig2Contig)
890 {
891         if (spp == 1) {
892                 tsize_t biasSize = TIFFScanlineSize(bias);
893                 tsize_t bufSize = TIFFScanlineSize(in);
894                 tdata_t buf, biasBuf;
895                 uint32 biasWidth = 0, biasLength = 0;
896                 TIFFGetField(bias, TIFFTAG_IMAGEWIDTH, &biasWidth);
897                 TIFFGetField(bias, TIFFTAG_IMAGELENGTH, &biasLength);
898                 if (biasSize == bufSize &&
899                     imagelength == biasLength && imagewidth == biasWidth) {
900                         uint16 sampleBits = 0;
901                         biasFn *subtractLine;
902                         TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &sampleBits);
903                         subtractLine = lineSubtractFn (sampleBits);
904                         if (subtractLine) {
905                                 uint32 row;
906                                 buf = _TIFFmalloc(bufSize);
907                                 biasBuf = _TIFFmalloc(bufSize);
908                                 for (row = 0; row < imagelength; row++) {
909                                         if (TIFFReadScanline(in, buf, row, 0) < 0
910                                             && !ignore) {
911                                                 TIFFError(TIFFFileName(in),
912                                                     "Error, can't read scanline %lu",
913                                                     (unsigned long) row);
914                                                 goto bad;
915                                         }
916                                         if (TIFFReadScanline(bias, biasBuf, row, 0) < 0
917                                             && !ignore) {
918                                                 TIFFError(TIFFFileName(in),
919                                                     "Error, can't read biased scanline %lu",
920                                                     (unsigned long) row);
921                                                 goto bad;
922                                         }
923                                         subtractLine (buf, biasBuf, imagewidth);
924                                         if (TIFFWriteScanline(out, buf, row, 0) < 0) {
925                                                 TIFFError(TIFFFileName(out),
926                                                     "Error, can't write scanline %lu",
927                                                     (unsigned long) row);
928                                                 goto bad;
929                                         }
930                                 }
931
932                                 _TIFFfree(buf);
933                                 _TIFFfree(biasBuf);
934                                 TIFFSetDirectory(bias,
935                                     TIFFCurrentDirectory(bias)); /* rewind */
936                                 return 1;
937 bad:
938                                 _TIFFfree(buf);
939                                 _TIFFfree(biasBuf);
940                                 return 0;
941                         } else {
942                                 TIFFError(TIFFFileName(in),
943                                     "No support for biasing %d bit pixels\n",
944                                     sampleBits);
945                                 return 0;
946                         }
947                 }
948                 TIFFError(TIFFFileName(in),
949                     "Bias image %s,%d\nis not the same size as %s,%d\n",
950                     TIFFFileName(bias), TIFFCurrentDirectory(bias),
951                     TIFFFileName(in), TIFFCurrentDirectory(in));
952                 return 0;
953         } else {
954                 TIFFError(TIFFFileName(in),
955                     "Can't bias %s,%d as it has >1 Sample/Pixel\n",
956                     TIFFFileName(in), TIFFCurrentDirectory(in));
957                 return 0;
958         }
959
960 }
961
962
963 /*
964  * Strip -> strip for change in encoding.
965  */
966 DECLAREcpFunc(cpDecodedStrips)
967 {
968         tsize_t stripsize  = TIFFStripSize(in);
969         tdata_t buf = _TIFFmalloc(stripsize);
970
971         (void) imagewidth; (void) spp;
972         if (buf) {
973                 tstrip_t s, ns = TIFFNumberOfStrips(in);
974                 uint32 row = 0;
975                 _TIFFmemset(buf, 0, stripsize);
976                 for (s = 0; s < ns; s++) {
977                         tsize_t cc = (row + rowsperstrip > imagelength) ?
978                             TIFFVStripSize(in, imagelength - row) : stripsize;
979                         if (TIFFReadEncodedStrip(in, s, buf, cc) < 0
980                             && !ignore) {
981                                 TIFFError(TIFFFileName(in),
982                                     "Error, can't read strip %lu",
983                                     (unsigned long) s);
984                                 goto bad;
985                         }
986                         if (TIFFWriteEncodedStrip(out, s, buf, cc) < 0) {
987                                 TIFFError(TIFFFileName(out),
988                                     "Error, can't write strip %lu",
989                                     (unsigned long) s);
990                                 goto bad;
991                         }
992                         row += rowsperstrip;
993                 }
994                 _TIFFfree(buf);
995                 return 1;
996         } else {
997                 TIFFError(TIFFFileName(in),
998                     "Error, can't allocate memory buffer of size %lu "
999                     "to read strips", (unsigned long) stripsize);
1000                 return 0;
1001         }
1002
1003 bad:
1004         _TIFFfree(buf);
1005         return 0;
1006 }
1007
1008 /*
1009  * Separate -> separate by row for rows/strip change.
1010  */
1011 DECLAREcpFunc(cpSeparate2SeparateByRow)
1012 {
1013         tsize_t scanlinesize = TIFFScanlineSize(in);
1014         tdata_t buf;
1015         uint32 row;
1016         tsample_t s;
1017
1018         (void) imagewidth;
1019         buf = _TIFFmalloc(scanlinesize);
1020         if (!buf)
1021                 return 0;
1022         _TIFFmemset(buf, 0, scanlinesize);
1023         for (s = 0; s < spp; s++) {
1024                 for (row = 0; row < imagelength; row++) {
1025                         if (TIFFReadScanline(in, buf, row, s) < 0 && !ignore) {
1026                                 TIFFError(TIFFFileName(in),
1027                                     "Error, can't read scanline %lu",
1028                                     (unsigned long) row);
1029                                 goto bad;
1030                         }
1031                         if (TIFFWriteScanline(out, buf, row, s) < 0) {
1032                                 TIFFError(TIFFFileName(out),
1033                                     "Error, can't write scanline %lu",
1034                                     (unsigned long) row);
1035                                 goto bad;
1036                         }
1037                 }
1038         }
1039         _TIFFfree(buf);
1040         return 1;
1041 bad:
1042         _TIFFfree(buf);
1043         return 0;
1044 }
1045
1046 /*
1047  * Contig -> separate by row.
1048  */
1049 DECLAREcpFunc(cpContig2SeparateByRow)
1050 {
1051         tsize_t scanlinesizein = TIFFScanlineSize(in);
1052         tsize_t scanlinesizeout = TIFFScanlineSize(out);
1053         tdata_t inbuf;
1054         tdata_t outbuf;
1055         register uint8 *inp, *outp;
1056         register uint32 n;
1057         uint32 row;
1058         tsample_t s;
1059
1060         inbuf = _TIFFmalloc(scanlinesizein);
1061         outbuf = _TIFFmalloc(scanlinesizeout);
1062         if (!inbuf || !outbuf)
1063                 return 0;
1064         _TIFFmemset(inbuf, 0, scanlinesizein);
1065         _TIFFmemset(outbuf, 0, scanlinesizeout);
1066         /* unpack channels */
1067         for (s = 0; s < spp; s++) {
1068                 for (row = 0; row < imagelength; row++) {
1069                         if (TIFFReadScanline(in, inbuf, row, 0) < 0
1070                             && !ignore) {
1071                                 TIFFError(TIFFFileName(in),
1072                                     "Error, can't read scanline %lu",
1073                                     (unsigned long) row);
1074                                 goto bad;
1075                         }
1076                         inp = ((uint8*)inbuf) + s;
1077                         outp = (uint8*)outbuf;
1078                         for (n = imagewidth; n-- > 0;) {
1079                                 *outp++ = *inp;
1080                                 inp += spp;
1081                         }
1082                         if (TIFFWriteScanline(out, outbuf, row, s) < 0) {
1083                                 TIFFError(TIFFFileName(out),
1084                                     "Error, can't write scanline %lu",
1085                                     (unsigned long) row);
1086                                 goto bad;
1087                         }
1088                 }
1089         }
1090         if (inbuf) _TIFFfree(inbuf);
1091         if (outbuf) _TIFFfree(outbuf);
1092         return 1;
1093 bad:
1094         if (inbuf) _TIFFfree(inbuf);
1095         if (outbuf) _TIFFfree(outbuf);
1096         return 0;
1097 }
1098
1099 /*
1100  * Separate -> contig by row.
1101  */
1102 DECLAREcpFunc(cpSeparate2ContigByRow)
1103 {
1104         tsize_t scanlinesizein = TIFFScanlineSize(in);
1105         tsize_t scanlinesizeout = TIFFScanlineSize(out);
1106         tdata_t inbuf;
1107         tdata_t outbuf;
1108         register uint8 *inp, *outp;
1109         register uint32 n;
1110         uint32 row;
1111         tsample_t s;
1112
1113         inbuf = _TIFFmalloc(scanlinesizein);
1114         outbuf = _TIFFmalloc(scanlinesizeout);
1115         if (!inbuf || !outbuf)
1116                 return 0;
1117         _TIFFmemset(inbuf, 0, scanlinesizein);
1118         _TIFFmemset(outbuf, 0, scanlinesizeout);
1119         for (row = 0; row < imagelength; row++) {
1120                 /* merge channels */
1121                 for (s = 0; s < spp; s++) {
1122                         if (TIFFReadScanline(in, inbuf, row, s) < 0
1123                             && !ignore) {
1124                                 TIFFError(TIFFFileName(in),
1125                                     "Error, can't read scanline %lu",
1126                                     (unsigned long) row);
1127                                 goto bad;
1128                         }
1129                         inp = (uint8*)inbuf;
1130                         outp = ((uint8*)outbuf) + s;
1131                         for (n = imagewidth; n-- > 0;) {
1132                                 *outp = *inp++;
1133                                 outp += spp;
1134                         }
1135                 }
1136                 if (TIFFWriteScanline(out, outbuf, row, 0) < 0) {
1137                         TIFFError(TIFFFileName(out),
1138                             "Error, can't write scanline %lu",
1139                             (unsigned long) row);
1140                         goto bad;
1141                 }
1142         }
1143         if (inbuf) _TIFFfree(inbuf);
1144         if (outbuf) _TIFFfree(outbuf);
1145         return 1;
1146 bad:
1147         if (inbuf) _TIFFfree(inbuf);
1148         if (outbuf) _TIFFfree(outbuf);
1149         return 0;
1150 }
1151
1152 static void
1153 cpStripToTile(uint8* out, uint8* in,
1154     uint32 rows, uint32 cols, int outskew, int inskew)
1155 {
1156         while (rows-- > 0) {
1157                 uint32 j = cols;
1158                 while (j-- > 0)
1159                         *out++ = *in++;
1160                 out += outskew;
1161                 in += inskew;
1162         }
1163 }
1164
1165 static void
1166 cpContigBufToSeparateBuf(uint8* out, uint8* in,
1167     uint32 rows, uint32 cols, int outskew, int inskew, tsample_t spp,
1168     int bytes_per_sample )
1169 {
1170         while (rows-- > 0) {
1171                 uint32 j = cols;
1172                 while (j-- > 0)
1173                 {
1174                         int n = bytes_per_sample;
1175
1176                         while( n-- ) {
1177                                 *out++ = *in++;
1178                         }
1179                         in += (spp-1) * bytes_per_sample;
1180                 }
1181                 out += outskew;
1182                 in += inskew;
1183         }
1184 }
1185
1186 static void
1187 cpSeparateBufToContigBuf(uint8* out, uint8* in,
1188     uint32 rows, uint32 cols, int outskew, int inskew, tsample_t spp,
1189     int bytes_per_sample)
1190 {
1191         while (rows-- > 0) {
1192                 uint32 j = cols;
1193                 while (j-- > 0) {
1194                         int n = bytes_per_sample;
1195
1196                         while( n-- ) {
1197                                 *out++ = *in++;
1198                         }
1199                         out += (spp-1)*bytes_per_sample;
1200                 }
1201                 out += outskew;
1202                 in += inskew;
1203         }
1204 }
1205
1206 static int
1207 cpImage(TIFF* in, TIFF* out, readFunc fin, writeFunc fout,
1208         uint32 imagelength, uint32 imagewidth, tsample_t spp)
1209 {
1210         int status = 0;
1211         tdata_t buf = NULL;
1212         tsize_t scanlinesize = TIFFRasterScanlineSize(in);
1213         tsize_t bytes = scanlinesize * (tsize_t)imagelength;
1214         /*
1215          * XXX: Check for integer overflow.
1216          */
1217         if (scanlinesize
1218             && imagelength
1219             && bytes / (tsize_t)imagelength == scanlinesize) {
1220                 buf = _TIFFmalloc(bytes);
1221                 if (buf) {
1222                         if ((*fin)(in, (uint8*)buf, imagelength,
1223                             imagewidth, spp)) {
1224                                 status = (*fout)(out, (uint8*)buf,
1225                                     imagelength, imagewidth, spp);
1226                         }
1227                         _TIFFfree(buf);
1228                 } else {
1229                         TIFFError(TIFFFileName(in),
1230                             "Error, can't allocate space for image buffer");
1231                 }
1232         } else {
1233                 TIFFError(TIFFFileName(in), "Error, no space for image buffer");
1234         }
1235
1236         return status;
1237 }
1238
1239 DECLAREreadFunc(readContigStripsIntoBuffer)
1240 {
1241         tsize_t scanlinesize = TIFFScanlineSize(in);
1242         uint8* bufp = buf;
1243         uint32 row;
1244
1245         (void) imagewidth; (void) spp;
1246         for (row = 0; row < imagelength; row++) {
1247                 if (TIFFReadScanline(in, (tdata_t) bufp, row, 0) < 0
1248                     && !ignore) {
1249                         TIFFError(TIFFFileName(in),
1250                             "Error, can't read scanline %lu",
1251                             (unsigned long) row);
1252                         return 0;
1253                 }
1254                 bufp += scanlinesize;
1255         }
1256
1257         return 1;
1258 }
1259
1260 DECLAREreadFunc(readSeparateStripsIntoBuffer)
1261 {
1262         int status = 1;
1263         tsize_t scanlinesize = TIFFScanlineSize(in);
1264         tdata_t scanline;
1265         if (!scanlinesize)
1266                 return 0;
1267
1268         scanline = _TIFFmalloc(scanlinesize);
1269         if (!scanline)
1270                 return 0;
1271         _TIFFmemset(scanline, 0, scanlinesize);
1272         (void) imagewidth;
1273         if (scanline) {
1274                 uint8* bufp = (uint8*) buf;
1275                 uint32 row;
1276                 tsample_t s;
1277                 for (row = 0; row < imagelength; row++) {
1278                         /* merge channels */
1279                         for (s = 0; s < spp; s++) {
1280                                 uint8* bp = bufp + s;
1281                                 tsize_t n = scanlinesize;
1282                                 uint8* sbuf = scanline;
1283
1284                                 if (TIFFReadScanline(in, scanline, row, s) < 0
1285                                     && !ignore) {
1286                                         TIFFError(TIFFFileName(in),
1287                                             "Error, can't read scanline %lu",
1288                                             (unsigned long) row);
1289                                             status = 0;
1290                                         goto done;
1291                                 }
1292                                 while (n-- > 0)
1293                                         *bp = *sbuf++, bp += spp;
1294                         }
1295                         bufp += scanlinesize * spp;
1296                 }
1297         }
1298
1299 done:
1300         _TIFFfree(scanline);
1301         return status;
1302 }
1303
1304 DECLAREreadFunc(readContigTilesIntoBuffer)
1305 {
1306         int status = 1;
1307         tsize_t tilesize = TIFFTileSize(in);
1308         tdata_t tilebuf;
1309         uint32 imagew = TIFFScanlineSize(in);
1310         uint32 tilew  = TIFFTileRowSize(in);
1311         int iskew = imagew - tilew;
1312         uint8* bufp = (uint8*) buf;
1313         uint32 tw, tl;
1314         uint32 row;
1315
1316         (void) spp;
1317         tilebuf = _TIFFmalloc(tilesize);
1318         if (tilebuf == 0)
1319                 return 0;
1320         _TIFFmemset(tilebuf, 0, tilesize);
1321         (void) TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
1322         (void) TIFFGetField(in, TIFFTAG_TILELENGTH, &tl);
1323         
1324         for (row = 0; row < imagelength; row += tl) {
1325                 uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
1326                 uint32 colb = 0;
1327                 uint32 col;
1328
1329                 for (col = 0; col < imagewidth; col += tw) {
1330                         if (TIFFReadTile(in, tilebuf, col, row, 0, 0) < 0
1331                             && !ignore) {
1332                                 TIFFError(TIFFFileName(in),
1333                                     "Error, can't read tile at %lu %lu",
1334                                     (unsigned long) col,
1335                                     (unsigned long) row);
1336                                 status = 0;
1337                                 goto done;
1338                         }
1339                         if (colb + tilew > imagew) {
1340                                 uint32 width = imagew - colb;
1341                                 uint32 oskew = tilew - width;
1342                                 cpStripToTile(bufp + colb,
1343                                     tilebuf, nrow, width,
1344                                     oskew + iskew, oskew );
1345                         } else
1346                                 cpStripToTile(bufp + colb,
1347                                     tilebuf, nrow, tilew,
1348                                     iskew, 0);
1349                         colb += tilew;
1350                 }
1351                 bufp += imagew * nrow;
1352         }
1353 done:
1354         _TIFFfree(tilebuf);
1355         return status;
1356 }
1357
1358 DECLAREreadFunc(readSeparateTilesIntoBuffer)
1359 {
1360         int status = 1;
1361         uint32 imagew = TIFFRasterScanlineSize(in);
1362         uint32 tilew = TIFFTileRowSize(in);
1363         int iskew  = imagew - tilew*spp;
1364         tsize_t tilesize = TIFFTileSize(in);
1365         tdata_t tilebuf;
1366         uint8* bufp = (uint8*) buf;
1367         uint32 tw, tl;
1368         uint32 row;
1369         uint16 bps, bytes_per_sample;
1370
1371         tilebuf = _TIFFmalloc(tilesize);
1372         if (tilebuf == 0)
1373                 return 0;
1374         _TIFFmemset(tilebuf, 0, tilesize);
1375         (void) TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
1376         (void) TIFFGetField(in, TIFFTAG_TILELENGTH, &tl);
1377         (void) TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bps);
1378         assert( bps % 8 == 0 );
1379         bytes_per_sample = bps/8;
1380
1381         for (row = 0; row < imagelength; row += tl) {
1382                 uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
1383                 uint32 colb = 0;
1384                 uint32 col;
1385
1386                 for (col = 0; col < imagewidth; col += tw) {
1387                         tsample_t s;
1388
1389                         for (s = 0; s < spp; s++) {
1390                                 if (TIFFReadTile(in, tilebuf, col, row, 0, s) < 0
1391                                     && !ignore) {
1392                                         TIFFError(TIFFFileName(in),
1393                                             "Error, can't read tile at %lu %lu, "
1394                                             "sample %lu",
1395                                             (unsigned long) col,
1396                                             (unsigned long) row,
1397                                             (unsigned long) s);
1398                                         status = 0;
1399                                         goto done;
1400                                 }
1401                                 /*
1402                                  * Tile is clipped horizontally.  Calculate
1403                                  * visible portion and skewing factors.
1404                                  */
1405                                 if (colb + tilew*spp > imagew) {
1406                                         uint32 width = imagew - colb;
1407                                         int oskew = tilew*spp - width;
1408                                         cpSeparateBufToContigBuf(
1409                                             bufp+colb+s*bytes_per_sample,
1410                                             tilebuf, nrow,
1411                                             width/(spp*bytes_per_sample),
1412                                             oskew + iskew,
1413                                             oskew/spp, spp,
1414                                             bytes_per_sample);
1415                                 } else
1416                                         cpSeparateBufToContigBuf(
1417                                             bufp+colb+s*bytes_per_sample,
1418                                             tilebuf, nrow, tw,
1419                                             iskew, 0, spp,
1420                                             bytes_per_sample);
1421                         }
1422                         colb += tilew*spp;
1423                 }
1424                 bufp += imagew * nrow;
1425         }
1426 done:
1427         _TIFFfree(tilebuf);
1428         return status;
1429 }
1430
1431 DECLAREwriteFunc(writeBufferToContigStrips)
1432 {
1433         uint32 row, rowsperstrip;
1434         tstrip_t strip = 0;
1435
1436         (void) imagewidth; (void) spp;
1437         (void) TIFFGetFieldDefaulted(out, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
1438         for (row = 0; row < imagelength; row += rowsperstrip) {
1439                 uint32 nrows = (row+rowsperstrip > imagelength) ?
1440                     imagelength-row : rowsperstrip;
1441                 tsize_t stripsize = TIFFVStripSize(out, nrows);
1442                 if (TIFFWriteEncodedStrip(out, strip++, buf, stripsize) < 0) {
1443                         TIFFError(TIFFFileName(out),
1444                             "Error, can't write strip %u", strip - 1);
1445                         return 0;
1446                 }
1447                 buf += stripsize;
1448         }
1449         return 1;
1450 }
1451
1452 DECLAREwriteFunc(writeBufferToSeparateStrips)
1453 {
1454         uint32 rowsize = imagewidth * spp;
1455         uint32 rowsperstrip;
1456         tsize_t stripsize = TIFFStripSize(out);
1457         tdata_t obuf;
1458         tstrip_t strip = 0;
1459         tsample_t s;
1460
1461         obuf = _TIFFmalloc(stripsize);
1462         if (obuf == NULL)
1463                 return (0);
1464         _TIFFmemset(obuf, 0, stripsize);
1465         (void) TIFFGetFieldDefaulted(out, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
1466         for (s = 0; s < spp; s++) {
1467                 uint32 row;
1468                 for (row = 0; row < imagelength; row += rowsperstrip) {
1469                         uint32 nrows = (row+rowsperstrip > imagelength) ?
1470                             imagelength-row : rowsperstrip;
1471                         tsize_t stripsize = TIFFVStripSize(out, nrows);
1472
1473                         cpContigBufToSeparateBuf(
1474                             obuf, (uint8*) buf + row*rowsize + s,
1475                             nrows, imagewidth, 0, 0, spp, 1);
1476                         if (TIFFWriteEncodedStrip(out, strip++, obuf, stripsize) < 0) {
1477                                 TIFFError(TIFFFileName(out),
1478                                     "Error, can't write strip %u",
1479                                     strip - 1);
1480                                 _TIFFfree(obuf);
1481                                 return 0;
1482                         }
1483                 }
1484         }
1485         _TIFFfree(obuf);
1486         return 1;
1487
1488 }
1489
1490 DECLAREwriteFunc(writeBufferToContigTiles)
1491 {
1492         uint32 imagew = TIFFScanlineSize(out);
1493         uint32 tilew  = TIFFTileRowSize(out);
1494         int iskew = imagew - tilew;
1495         tsize_t tilesize = TIFFTileSize(out);
1496         tdata_t obuf;
1497         uint8* bufp = (uint8*) buf;
1498         uint32 tl, tw;
1499         uint32 row;
1500
1501         (void) spp;
1502
1503         obuf = _TIFFmalloc(TIFFTileSize(out));
1504         if (obuf == NULL)
1505                 return 0;
1506         _TIFFmemset(obuf, 0, tilesize);
1507         (void) TIFFGetField(out, TIFFTAG_TILELENGTH, &tl);
1508         (void) TIFFGetField(out, TIFFTAG_TILEWIDTH, &tw);
1509         for (row = 0; row < imagelength; row += tilelength) {
1510                 uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
1511                 uint32 colb = 0;
1512                 uint32 col;
1513
1514                 for (col = 0; col < imagewidth; col += tw) {
1515                         /*
1516                          * Tile is clipped horizontally.  Calculate
1517                          * visible portion and skewing factors.
1518                          */
1519                         if (colb + tilew > imagew) {
1520                                 uint32 width = imagew - colb;
1521                                 int oskew = tilew - width;
1522                                 cpStripToTile(obuf, bufp + colb, nrow, width,
1523                                     oskew, oskew + iskew);
1524                         } else
1525                                 cpStripToTile(obuf, bufp + colb, nrow, tilew,
1526                                     0, iskew);
1527                         if (TIFFWriteTile(out, obuf, col, row, 0, 0) < 0) {
1528                                 TIFFError(TIFFFileName(out),
1529                                     "Error, can't write tile at %lu %lu",
1530                                     (unsigned long) col,
1531                                     (unsigned long) row);
1532                                 _TIFFfree(obuf);
1533                                 return 0;
1534                         }
1535                         colb += tilew;
1536                 }
1537                 bufp += nrow * imagew;
1538         }
1539         _TIFFfree(obuf);
1540         return 1;
1541 }
1542
1543 DECLAREwriteFunc(writeBufferToSeparateTiles)
1544 {
1545         uint32 imagew = TIFFScanlineSize(out);
1546         tsize_t tilew  = TIFFTileRowSize(out);
1547         uint32 iimagew = TIFFRasterScanlineSize(out);
1548         int iskew = iimagew - tilew*spp;
1549         tsize_t tilesize = TIFFTileSize(out);
1550         tdata_t obuf;
1551         uint8* bufp = (uint8*) buf;
1552         uint32 tl, tw;
1553         uint32 row;
1554         uint16 bps, bytes_per_sample;
1555
1556         obuf = _TIFFmalloc(TIFFTileSize(out));
1557         if (obuf == NULL)
1558                 return 0;
1559         _TIFFmemset(obuf, 0, tilesize);
1560         (void) TIFFGetField(out, TIFFTAG_TILELENGTH, &tl);
1561         (void) TIFFGetField(out, TIFFTAG_TILEWIDTH, &tw);
1562         (void) TIFFGetField(out, TIFFTAG_BITSPERSAMPLE, &bps);
1563         assert( bps % 8 == 0 );
1564         bytes_per_sample = bps/8;
1565
1566         for (row = 0; row < imagelength; row += tl) {
1567                 uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
1568                 uint32 colb = 0;
1569                 uint32 col;
1570
1571                 for (col = 0; col < imagewidth; col += tw) {
1572                         tsample_t s;
1573                         for (s = 0; s < spp; s++) {
1574                                 /*
1575                                  * Tile is clipped horizontally.  Calculate
1576                                  * visible portion and skewing factors.
1577                                  */
1578                                 if (colb + tilew > imagew) {
1579                                         uint32 width = (imagew - colb);
1580                                         int oskew = tilew - width;
1581
1582                                         cpContigBufToSeparateBuf(obuf,
1583                                             bufp + (colb*spp) + s,
1584                                             nrow, width/bytes_per_sample,
1585                                             oskew, (oskew*spp)+iskew, spp,
1586                                             bytes_per_sample);
1587                                 } else
1588                                         cpContigBufToSeparateBuf(obuf,
1589                                             bufp + (colb*spp) + s,
1590                                             nrow, tilewidth,
1591                                             0, iskew, spp,
1592                                             bytes_per_sample);
1593                                 if (TIFFWriteTile(out, obuf, col, row, 0, s) < 0) {
1594                                         TIFFError(TIFFFileName(out),
1595                                             "Error, can't write tile at %lu %lu "
1596                                             "sample %lu",
1597                                             (unsigned long) col,
1598                                             (unsigned long) row,
1599                                             (unsigned long) s);
1600                                         _TIFFfree(obuf);
1601                                         return 0;
1602                                 }
1603                         }
1604                         colb += tilew;
1605                 }
1606                 bufp += nrow * iimagew;
1607         }
1608         _TIFFfree(obuf);
1609         return 1;
1610 }
1611
1612 /*
1613  * Contig strips -> contig tiles.
1614  */
1615 DECLAREcpFunc(cpContigStrips2ContigTiles)
1616 {
1617         return cpImage(in, out,
1618             readContigStripsIntoBuffer,
1619             writeBufferToContigTiles,
1620             imagelength, imagewidth, spp);
1621 }
1622
1623 /*
1624  * Contig strips -> separate tiles.
1625  */
1626 DECLAREcpFunc(cpContigStrips2SeparateTiles)
1627 {
1628         return cpImage(in, out,
1629             readContigStripsIntoBuffer,
1630             writeBufferToSeparateTiles,
1631             imagelength, imagewidth, spp);
1632 }
1633
1634 /*
1635  * Separate strips -> contig tiles.
1636  */
1637 DECLAREcpFunc(cpSeparateStrips2ContigTiles)
1638 {
1639         return cpImage(in, out,
1640             readSeparateStripsIntoBuffer,
1641             writeBufferToContigTiles,
1642             imagelength, imagewidth, spp);
1643 }
1644
1645 /*
1646  * Separate strips -> separate tiles.
1647  */
1648 DECLAREcpFunc(cpSeparateStrips2SeparateTiles)
1649 {
1650         return cpImage(in, out,
1651             readSeparateStripsIntoBuffer,
1652             writeBufferToSeparateTiles,
1653             imagelength, imagewidth, spp);
1654 }
1655
1656 /*
1657  * Contig strips -> contig tiles.
1658  */
1659 DECLAREcpFunc(cpContigTiles2ContigTiles)
1660 {
1661         return cpImage(in, out,
1662             readContigTilesIntoBuffer,
1663             writeBufferToContigTiles,
1664             imagelength, imagewidth, spp);
1665 }
1666
1667 /*
1668  * Contig tiles -> separate tiles.
1669  */
1670 DECLAREcpFunc(cpContigTiles2SeparateTiles)
1671 {
1672         return cpImage(in, out,
1673             readContigTilesIntoBuffer,
1674             writeBufferToSeparateTiles,
1675             imagelength, imagewidth, spp);
1676 }
1677
1678 /*
1679  * Separate tiles -> contig tiles.
1680  */
1681 DECLAREcpFunc(cpSeparateTiles2ContigTiles)
1682 {
1683         return cpImage(in, out,
1684             readSeparateTilesIntoBuffer,
1685             writeBufferToContigTiles,
1686             imagelength, imagewidth, spp);
1687 }
1688
1689 /*
1690  * Separate tiles -> separate tiles (tile dimension change).
1691  */
1692 DECLAREcpFunc(cpSeparateTiles2SeparateTiles)
1693 {
1694         return cpImage(in, out,
1695             readSeparateTilesIntoBuffer,
1696             writeBufferToSeparateTiles,
1697             imagelength, imagewidth, spp);
1698 }
1699
1700 /*
1701  * Contig tiles -> contig tiles (tile dimension change).
1702  */
1703 DECLAREcpFunc(cpContigTiles2ContigStrips)
1704 {
1705         return cpImage(in, out,
1706             readContigTilesIntoBuffer,
1707             writeBufferToContigStrips,
1708             imagelength, imagewidth, spp);
1709 }
1710
1711 /*
1712  * Contig tiles -> separate strips.
1713  */
1714 DECLAREcpFunc(cpContigTiles2SeparateStrips)
1715 {
1716         return cpImage(in, out,
1717             readContigTilesIntoBuffer,
1718             writeBufferToSeparateStrips,
1719             imagelength, imagewidth, spp);
1720 }
1721
1722 /*
1723  * Separate tiles -> contig strips.
1724  */
1725 DECLAREcpFunc(cpSeparateTiles2ContigStrips)
1726 {
1727         return cpImage(in, out,
1728             readSeparateTilesIntoBuffer,
1729             writeBufferToContigStrips,
1730             imagelength, imagewidth, spp);
1731 }
1732
1733 /*
1734  * Separate tiles -> separate strips.
1735  */
1736 DECLAREcpFunc(cpSeparateTiles2SeparateStrips)
1737 {
1738         return cpImage(in, out,
1739             readSeparateTilesIntoBuffer,
1740             writeBufferToSeparateStrips,
1741             imagelength, imagewidth, spp);
1742 }
1743
1744 /*
1745  * Select the appropriate copy function to use.
1746  */
1747 static copyFunc
1748 pickCopyFunc(TIFF* in, TIFF* out, uint16 bitspersample, uint16 samplesperpixel)
1749 {
1750         uint16 shortv;
1751         uint32 w, l, tw, tl;
1752         int bychunk;
1753
1754         (void) TIFFGetField(in, TIFFTAG_PLANARCONFIG, &shortv);
1755         if (shortv != config && bitspersample != 8 && samplesperpixel > 1) {
1756                 fprintf(stderr,
1757                     "%s: Cannot handle different planar configuration w/ bits/sample != 8\n",
1758                     TIFFFileName(in));
1759                 return (NULL);
1760         }
1761         TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &w);
1762         TIFFGetField(in, TIFFTAG_IMAGELENGTH, &l);
1763         if (!(TIFFIsTiled(out) || TIFFIsTiled(in))) {
1764                 uint32 irps = (uint32) -1L;
1765                 TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &irps);
1766                 /* if biased, force decoded copying to allow image subtraction */
1767                 bychunk = !bias && (rowsperstrip == irps);
1768         }else{  /* either in or out is tiled */
1769                 if (bias) {
1770                         fprintf(stderr,
1771                             "%s: Cannot handle tiled configuration w/bias image\n",
1772                         TIFFFileName(in));
1773                         return (NULL);
1774                 }
1775                 if (TIFFIsTiled(out)) {
1776                         if (!TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw))
1777                                 tw = w;
1778                         if (!TIFFGetField(in, TIFFTAG_TILELENGTH, &tl))
1779                                 tl = l;
1780                         bychunk = (tw == tilewidth && tl == tilelength);
1781                 } else {  /* out's not, so in must be tiled */
1782                         TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
1783                         TIFFGetField(in, TIFFTAG_TILELENGTH, &tl);
1784                         bychunk = (tw == w && tl == rowsperstrip);
1785                 }
1786         }
1787 #define T 1
1788 #define F 0
1789 #define pack(a,b,c,d,e) ((long)(((a)<<11)|((b)<<3)|((c)<<2)|((d)<<1)|(e)))
1790         switch(pack(shortv,config,TIFFIsTiled(in),TIFFIsTiled(out),bychunk)) {
1791                 /* Strips -> Tiles */
1792                 case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,T,F):
1793                 case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,T,T):
1794                         return cpContigStrips2ContigTiles;
1795                 case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, F,T,F):
1796                 case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, F,T,T):
1797                         return cpContigStrips2SeparateTiles;
1798                 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,T,F):
1799                 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,T,T):
1800                         return cpSeparateStrips2ContigTiles;
1801                 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,T,F):
1802                 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,T,T):
1803                         return cpSeparateStrips2SeparateTiles;
1804                 /* Tiles -> Tiles */
1805                 case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,T,F):
1806                 case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,T,T):
1807                         return cpContigTiles2ContigTiles;
1808                 case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,T,F):
1809                 case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,T,T):
1810                         return cpContigTiles2SeparateTiles;
1811                 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,T,F):
1812                 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,T,T):
1813                         return cpSeparateTiles2ContigTiles;
1814                 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,T,F):
1815                 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,T,T):
1816                         return cpSeparateTiles2SeparateTiles;
1817                 /* Tiles -> Strips */
1818                 case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,F,F):
1819                 case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,F,T):
1820                         return cpContigTiles2ContigStrips;
1821                 case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,F,F):
1822                 case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,F,T):
1823                         return cpContigTiles2SeparateStrips;
1824                 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,F,F):
1825                 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,F,T):
1826                         return cpSeparateTiles2ContigStrips;
1827                 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,F,F):
1828                 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,F,T):
1829                         return cpSeparateTiles2SeparateStrips;
1830                 /* Strips -> Strips */
1831                 case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,F,F):
1832                         return bias ? cpBiasedContig2Contig : cpContig2ContigByRow;
1833                 case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,F,T):
1834                         return cpDecodedStrips;
1835                 case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE,   F,F,F):
1836                 case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE,   F,F,T):
1837                         return cpContig2SeparateByRow;
1838                 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,F,F):
1839                 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,F,T):
1840                         return cpSeparate2ContigByRow;
1841                 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,F,F):
1842                 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,F,T):
1843                         return cpSeparate2SeparateByRow;
1844         }
1845 #undef pack
1846 #undef F
1847 #undef T
1848         fprintf(stderr, "tiffcp: %s: Don't know how to copy/convert image.\n",
1849             TIFFFileName(in));
1850         return (NULL);
1851 }
1852
1853 /* vim: set ts=8 sts=8 sw=8 noet: */
1854 /*
1855  * Local Variables:
1856  * mode: c
1857  * c-basic-offset: 8
1858  * fill-column: 78
1859  * End:
1860  */