home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / software / unix / libtiff / lbtif3_3.tar / tools / tiffcp.c < prev    next >
C/C++ Source or Header  |  1993-08-26  |  30KB  |  1,137 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Header: /usr/people/sam/tiff/tools/RCS/tiffcp.c,v 1.24 93/08/26 18:10:05 sam Exp $";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler
  7.  * Copyright (c) 1991, 1992 Silicon Graphics, Inc.
  8.  *
  9.  * Permission to use, copy, modify, distribute, and sell this software and 
  10.  * its documentation for any purpose is hereby granted without fee, provided
  11.  * that (i) the above copyright notices and this permission notice appear in
  12.  * all copies of the software and related documentation, and (ii) the names of
  13.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  14.  * publicity relating to the software without the specific, prior written
  15.  * permission of Sam Leffler and Silicon Graphics.
  16.  * 
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  18.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  19.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  20.  * 
  21.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  22.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  23.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  24.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  25.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  26.  * OF THIS SOFTWARE.
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32.  
  33. #include "tiffio.h"
  34.  
  35. typedef    unsigned char u_char;
  36.  
  37. #if defined(VMS)
  38. #define unlink delete
  39. #endif
  40.  
  41. #define    streq(a,b)    (strcmp(a,b) == 0)
  42. #define    CopyField(tag, v) \
  43.     if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
  44. #define    CopyField2(tag, v1, v2) \
  45.     if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
  46. #define    CopyField3(tag, v1, v2, v3) \
  47.     if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
  48. #define    CopyField4(tag, v1, v2, v3, v4) \
  49.     if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4)
  50.  
  51. #define    TRUE    1
  52. #define    FALSE    0
  53.  
  54. static  int outtiled = -1;
  55. static  uint32 tilewidth;
  56. static  uint32 tilelength;
  57.  
  58. static    uint16 config;
  59. static    uint16 compression;
  60. static    uint16 predictor;
  61. static    uint16 fillorder;
  62. static    uint32 rowsperstrip;
  63. static    uint32 g3opts;
  64. static    int ignore = FALSE;        /* if true, ignore read errors */
  65. static    char *filename;
  66.  
  67. static    int tiffcp(TIFF*, TIFF*);
  68. static    void usage(void);
  69.  
  70. void
  71. main(int argc, char* argv[])
  72. {
  73.     uint16 defconfig = -1;
  74.     uint16 defcompression = -1;
  75.     uint16 defpredictor = -1;
  76.     uint16 deffillorder = 0;
  77.     uint32 deftilewidth = -1;
  78.     uint32 deftilelength = -1;
  79.     uint32 defrowsperstrip = -1;
  80.     uint32 defg3opts = -1;
  81.     TIFF *in, *out;
  82.  
  83.     argc--, argv++;
  84.     if (argc < 2)
  85.         usage();
  86.     for (; argc > 2 && argv[0][0] == '-'; argc--, argv++) {
  87.         if (streq(argv[0], "-none")) {
  88.             defcompression = COMPRESSION_NONE;
  89.             continue;
  90.         }
  91.         if (streq(argv[0], "-packbits")) {
  92.             defcompression = COMPRESSION_PACKBITS;
  93.             continue;
  94.         }
  95.         if (streq(argv[0], "-lzw")) {
  96.             defcompression = COMPRESSION_LZW;
  97.             continue;
  98.         }
  99.         if (streq(argv[0], "-g3")) {
  100.             defcompression = COMPRESSION_CCITTFAX3;
  101.             continue;
  102.         }
  103.         if (streq(argv[0], "-g4")) {
  104.             defcompression = COMPRESSION_CCITTFAX4;
  105.             continue;
  106.         }
  107.         if (streq(argv[0], "-contig")) {
  108.             defconfig = PLANARCONFIG_CONTIG;
  109.             continue;
  110.         }
  111.         if (streq(argv[0], "-separate")) {
  112.             defconfig = PLANARCONFIG_SEPARATE;
  113.             continue;
  114.         }
  115.         if (streq(argv[0], "-lsb2msb")) {
  116.             deffillorder = FILLORDER_LSB2MSB;
  117.             continue;
  118.         }
  119.         if (streq(argv[0], "-msb2lsb")) {
  120.             deffillorder = FILLORDER_MSB2LSB;
  121.             continue;
  122.         }
  123.         if (streq(argv[0], "-rowsperstrip")) {
  124.             argc--, argv++;
  125.             defrowsperstrip = atoi(argv[0]);
  126.             continue;
  127.         }
  128.         if (streq(argv[0], "-1d")) {
  129.             if (defg3opts == -1)
  130.                 defg3opts = 0;
  131.             defg3opts &= ~GROUP3OPT_2DENCODING;
  132.             continue;
  133.         }
  134.         if (streq(argv[0], "-2d")) {
  135.             if (defg3opts == -1)
  136.                 defg3opts = 0;
  137.             defg3opts |= GROUP3OPT_2DENCODING;
  138.             continue;
  139.         }
  140.         if (streq(argv[0], "-fill")) {
  141.             if (defg3opts == -1)
  142.                 defg3opts = 0;
  143.             defg3opts |= GROUP3OPT_FILLBITS;
  144.             continue;
  145.         }
  146.         if (streq(argv[0], "-predictor")) {
  147.             argc--, argv++;
  148.             defpredictor = atoi(argv[0]);
  149.             continue;
  150.         }
  151.         if (streq(argv[0], "-strips")) {
  152.             outtiled = FALSE;
  153.             continue;
  154.         }
  155.         if (streq(argv[0], "-tiles")) {
  156.             outtiled = TRUE;
  157.             continue;
  158.         }
  159.         if (streq(argv[0], "-tilewidth")) {
  160.             argc--, argv++;
  161.             outtiled = TRUE;
  162.             deftilewidth = atoi(argv[0]);
  163.             continue;
  164.         }
  165.         if (streq(argv[0], "-tilelength")) {
  166.             argc--, argv++;
  167.             outtiled = TRUE;
  168.             deftilelength = atoi(argv[0]);
  169.             continue;
  170.         }
  171.         if (streq(argv[0], "-ignore")) {
  172.             ignore = TRUE;
  173.             continue;
  174.         }
  175.         usage();
  176.     }
  177.     out = TIFFOpen(argv[argc-1], "w");
  178.     if (out == NULL)
  179.         exit(-2);
  180.     for (; argc > 1; argc--, argv++) {
  181.         in = TIFFOpen(filename = argv[0], "r");
  182.         if (in != NULL) {
  183.             do {
  184.                 config = defconfig;
  185.                 compression = defcompression;
  186.                 predictor = defpredictor;
  187.                 fillorder = deffillorder;
  188.                 rowsperstrip = defrowsperstrip;
  189.                 tilewidth = deftilewidth;
  190.                 tilelength = deftilelength;
  191.                 g3opts = defg3opts;
  192.                 if (!tiffcp(in, out) || !TIFFWriteDirectory(out)) {
  193.                     (void) TIFFClose(out);
  194.                     exit(1);
  195.                 }
  196.             } while (TIFFReadDirectory(in));
  197.             (void) TIFFClose(in);
  198.         }
  199.     }
  200.     (void) TIFFClose(out);
  201.     exit(0);
  202. }
  203.  
  204. char* stuff[] = {
  205. "usage: tiffcp [options] input... output",
  206. "where options are:",
  207. " -contig    pack samples contiguously (e.g. RGBRGB...)",
  208. " -separate    store samples separately (e.g. RRR...GGG...BBB...)",
  209. " -strips    write output in strips",
  210. " -tiles    write output in tiles",
  211. " -ignore    ignore read errors",
  212. "",
  213. " -rowsperstrip #    make each strip have no more than # rows",
  214. " -tilewidth #    set output tile width (pixels)",
  215. " -tilelength #    set output tile length (pixels)",
  216. "",
  217. " -lsb2msb    force lsb-to-msb FillOrder for output",
  218. " -msb2lsb    force msb-to-lsb FillOrder for output",
  219. "",
  220. " -lzw        compress output with Lempel-Ziv & Welch encoding",
  221. " -packbits    compress output with packbits encoding",
  222. " -g3        compress output with CCITT Group 3 encoding",
  223. " -g4        compress output with CCITT Group 4 encoding",
  224. " -none        use no compression algorithm on output",
  225. "",
  226. " -1d        use CCITT Group 3 1D encoding",
  227. " -2d        use CCITT Group 3 2D encoding",
  228. " -fill        zero-fill scanlines with CCITT Group 3 encoding",
  229. "",
  230. " -predictor    set predictor value for Lempel-Ziv & Welch encoding",
  231. NULL
  232. };
  233.  
  234. static void
  235. usage(void)
  236. {
  237.     char buf[BUFSIZ];
  238.     int i;
  239.  
  240.     setbuf(stderr, buf);
  241.     for (i = 0; stuff[i] != NULL; i++)
  242.         fprintf(stderr, "%s\n", stuff[i]);
  243.     exit(-1);
  244. }
  245.  
  246. static void
  247. CheckAndCorrectColormap(int n, uint16* r, uint16* g, uint16* b)
  248. {
  249.     int i;
  250.  
  251.     for (i = 0; i < n; i++)
  252.         if (r[i] >= 256 || g[i] >= 256 || b[i] >= 256)
  253.             return;
  254.     TIFFWarning(filename, "Scaling 8-bit colormap");
  255. #define    CVT(x)        (((x) * ((1L<<16)-1)) / 255)
  256.     for (i = 0; i < n; i++) {
  257.         r[i] = CVT(r[i]);
  258.         g[i] = CVT(g[i]);
  259.         b[i] = CVT(b[i]);
  260.     }
  261. #undef CVT
  262. }
  263.  
  264. static struct cpTag {
  265.     uint16    tag;
  266.     uint16    count;
  267.     TIFFDataType type;
  268. } tags[] = {
  269.     { TIFFTAG_SUBFILETYPE,        1, TIFF_LONG },
  270.     { TIFFTAG_PHOTOMETRIC,        1, TIFF_SHORT },
  271.     { TIFFTAG_THRESHHOLDING,    1, TIFF_SHORT },
  272.     { TIFFTAG_DOCUMENTNAME,        1, TIFF_ASCII },
  273.     { TIFFTAG_IMAGEDESCRIPTION,    1, TIFF_ASCII },
  274.     { TIFFTAG_MAKE,            1, TIFF_ASCII },
  275.     { TIFFTAG_MODEL,        1, TIFF_ASCII },
  276.     { TIFFTAG_ORIENTATION,        1, TIFF_SHORT },
  277.     { TIFFTAG_MINSAMPLEVALUE,    1, TIFF_SHORT },
  278.     { TIFFTAG_MAXSAMPLEVALUE,    1, TIFF_SHORT },
  279.     { TIFFTAG_XRESOLUTION,        1, TIFF_RATIONAL },
  280.     { TIFFTAG_YRESOLUTION,        1, TIFF_RATIONAL },
  281.     { TIFFTAG_PAGENAME,        1, TIFF_ASCII },
  282.     { TIFFTAG_XPOSITION,        1, TIFF_RATIONAL },
  283.     { TIFFTAG_YPOSITION,        1, TIFF_RATIONAL },
  284.     { TIFFTAG_GROUP4OPTIONS,    1, TIFF_LONG },
  285.     { TIFFTAG_RESOLUTIONUNIT,    1, TIFF_SHORT },
  286.     { TIFFTAG_PAGENUMBER,        2, TIFF_SHORT },
  287.     { TIFFTAG_SOFTWARE,        1, TIFF_ASCII },
  288.     { TIFFTAG_DATETIME,        1, TIFF_ASCII },
  289.     { TIFFTAG_ARTIST,        1, TIFF_ASCII },
  290.     { TIFFTAG_HOSTCOMPUTER,        1, TIFF_ASCII },
  291.     { TIFFTAG_WHITEPOINT,        1, TIFF_RATIONAL },
  292.     { TIFFTAG_PRIMARYCHROMATICITIES,-1,TIFF_RATIONAL },
  293.     { TIFFTAG_HALFTONEHINTS,    2, TIFF_SHORT },
  294.     { TIFFTAG_BADFAXLINES,        1, TIFF_LONG },
  295.     { TIFFTAG_CLEANFAXDATA,        1, TIFF_SHORT },
  296.     { TIFFTAG_CONSECUTIVEBADFAXLINES,1, TIFF_LONG },
  297.     { TIFFTAG_INKSET,        1, TIFF_SHORT },
  298.     { TIFFTAG_INKNAMES,        1, TIFF_ASCII },
  299.     { TIFFTAG_DOTRANGE,        2, TIFF_SHORT },
  300.     { TIFFTAG_TARGETPRINTER,    1, TIFF_ASCII },
  301.     { TIFFTAG_SAMPLEFORMAT,        1, TIFF_SHORT },
  302.     { TIFFTAG_YCBCRCOEFFICIENTS,    -1,TIFF_RATIONAL },
  303.     { TIFFTAG_YCBCRSUBSAMPLING,    2, TIFF_SHORT },
  304.     { TIFFTAG_YCBCRPOSITIONING,    1, TIFF_SHORT },
  305.     { TIFFTAG_REFERENCEBLACKWHITE,    -1,TIFF_RATIONAL },
  306.     { TIFFTAG_EXTRASAMPLES,        -1, TIFF_SHORT },
  307. };
  308. #define    NTAGS    (sizeof (tags) / sizeof (tags[0]))
  309.  
  310. static void
  311. cpOtherTags(TIFF* in, TIFF* out)
  312. {
  313.     struct cpTag *p;
  314.     uint16 shortv, shortv2, *shortav;
  315.     float floatv, *floatav;
  316.     char *stringv;
  317.     uint32 longv;
  318.  
  319.     for (p = tags; p < &tags[NTAGS]; p++)
  320.         switch (p->type) {
  321.         case TIFF_SHORT:
  322.             if (p->count == 1) {
  323.                 CopyField(p->tag, shortv);
  324.             } else if (p->count == 2) {
  325.                 CopyField2(p->tag, shortv, shortv2);
  326.             } else if (p->count == (uint16) -1) {
  327.                 CopyField2(p->tag, shortv, shortav);
  328.             }
  329.             break;
  330.         case TIFF_LONG:
  331.             CopyField(p->tag, longv);
  332.             break;
  333.         case TIFF_RATIONAL:
  334.             if (p->count == 1) {
  335.                 CopyField(p->tag, floatv);
  336.             } else if (p->count == (uint16) -1) {
  337.                 CopyField(p->tag, floatav);
  338.             }
  339.             break;
  340.         case TIFF_ASCII:
  341.             CopyField(p->tag, stringv);
  342.             break;
  343.         }
  344. }
  345.  
  346. typedef int (*copyFunc)
  347.     (TIFF* in, TIFF* out, uint32 l, uint32 w, uint16 samplesperpixel);
  348. static    copyFunc pickCopyFunc(TIFF*, TIFF*, uint16, uint16);
  349.  
  350. static int
  351. tiffcp(TIFF* in, TIFF* out)
  352. {
  353.     uint16 bitspersample, samplesperpixel, shortv;
  354.     copyFunc cf;
  355.     uint32 w, l;
  356.  
  357.     CopyField(TIFFTAG_IMAGEWIDTH, w);
  358.     CopyField(TIFFTAG_IMAGELENGTH, l);
  359.     CopyField(TIFFTAG_BITSPERSAMPLE, bitspersample);
  360.     if (compression != (uint16)-1)
  361.         TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
  362.     else
  363.         CopyField(TIFFTAG_COMPRESSION, compression);
  364.     if (fillorder != 0)
  365.         TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
  366.     else
  367.         CopyField(TIFFTAG_FILLORDER, shortv);
  368.     CopyField(TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
  369.     /*
  370.      * Choose tiles/strip for the output image according to
  371.      * the command line arguments (-tiles, -strips) and the
  372.      * structure of the input image.
  373.      */
  374.     if (outtiled == -1)
  375.         outtiled = TIFFIsTiled(in);
  376.     if (outtiled) {
  377.         /*
  378.          * Setup output file's tile width&height.  If either
  379.          * is not specified, it defaults to 256.
  380.          */
  381.         if (tilewidth < 0 &&
  382.             !TIFFGetField(in, TIFFTAG_TILEWIDTH, &tilewidth))
  383.             tilewidth = 256;
  384.         if (tilelength < 0 &&
  385.             !TIFFGetField(in, TIFFTAG_TILELENGTH, &tilelength))
  386.             tilelength = 256;
  387.         TIFFSetField(out, TIFFTAG_TILEWIDTH, tilewidth);
  388.         TIFFSetField(out, TIFFTAG_TILELENGTH, tilelength);
  389.     } else {
  390.         /*
  391.          * RowsPerStrip is left unspecified: use either the
  392.          * value from the input image or, if nothing is defined,
  393.          * something that approximates 8Kbyte strips.
  394.          */
  395.         if (rowsperstrip < 0 &&
  396.             !TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &rowsperstrip))
  397.             rowsperstrip = (8*1024)/TIFFScanlineSize(out);
  398.         if (rowsperstrip == 0)
  399.             rowsperstrip = 1L;
  400.         TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
  401.     }
  402.     if (config != (uint16) -1)
  403.         TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
  404.     else
  405.         CopyField(TIFFTAG_PLANARCONFIG, config);
  406.     if (g3opts != -1)
  407.         TIFFSetField(out, TIFFTAG_GROUP3OPTIONS, g3opts);
  408.     else
  409.         CopyField(TIFFTAG_GROUP3OPTIONS, g3opts);
  410.     if (samplesperpixel <= 4) {
  411.         uint16 *tr, *tg, *tb, *ta;
  412.         CopyField4(TIFFTAG_TRANSFERFUNCTION, tr, tg, tb, ta);
  413.     }
  414.     if (predictor != (uint16)-1)
  415.         TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
  416.     else
  417.         CopyField(TIFFTAG_PREDICTOR, predictor);
  418.     { uint16 *red, *green, *blue;
  419.       if (TIFFGetField(in, TIFFTAG_COLORMAP, &red, &green, &blue)) {
  420.         CheckAndCorrectColormap(1<<bitspersample, red, green, blue);
  421.         TIFFSetField(out, TIFFTAG_COLORMAP, red, green, blue);
  422.       }
  423.     }
  424. /* SMinSampleValue & SMaxSampleValue */
  425. /* JPEG stuff */
  426.     cpOtherTags(in, out);
  427.  
  428.     cf = pickCopyFunc(in, out, bitspersample, samplesperpixel);
  429.     return (cf ? (*cf)(in, out, l, w, samplesperpixel) : FALSE);
  430. }
  431.  
  432. /*
  433.  * Copy Functions.
  434.  */
  435. #define    DECLAREcpFunc(x) \
  436. static int x(TIFF* in, TIFF* out, \
  437.     uint32 imagelength, uint32 imagewidth, tsample_t spp)
  438.  
  439. #define    DECLAREreadFunc(x) \
  440. static void x(TIFF* in, \
  441.     u_char* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)
  442. typedef void (*readFunc)(TIFF*, u_char*, uint32, uint32, tsample_t);
  443.  
  444. #define    DECLAREwriteFunc(x) \
  445. static int x(TIFF* out, \
  446.     u_char* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)
  447. typedef int (*writeFunc)(TIFF*, u_char*, uint32, uint32, tsample_t);
  448.  
  449. /*
  450.  * Contig -> contig by scanline for rows/strip change.
  451.  */
  452. DECLAREcpFunc(cpContig2ContigByRow)
  453. {
  454.     u_char *buf = (u_char *)malloc(TIFFScanlineSize(in));
  455.     uint32 row;
  456.  
  457.     for (row = 0; row < imagelength; row++) {
  458.         if (TIFFReadScanline(in, buf, row, 0) < 0 && !ignore)
  459.             goto done;
  460.         if (TIFFWriteScanline(out, buf, row, 0) < 0)
  461.             goto bad;
  462.     }
  463. done:
  464.     free(buf);
  465.     return (TRUE);
  466. bad:
  467.     free(buf);
  468.     return (FALSE);
  469. }
  470.  
  471. /*
  472.  * Strip -> strip for change in encoding.
  473.  */
  474. DECLAREcpFunc(cpDecodedStrips)
  475. {
  476.     tsize_t stripsize  = TIFFStripSize(in);
  477.     u_char *buf = (u_char *)malloc(stripsize);
  478.  
  479.     if (buf) {
  480.         tstrip_t s, ns = TIFFNumberOfStrips(in);
  481.         uint32 row = 0;
  482.         for (s = 0; s < ns; s++) {
  483.             tsize_t cc = (row + rowsperstrip > imagelength) ?
  484.                 TIFFVStripSize(in, imagelength - row) : stripsize;
  485.             if (TIFFReadEncodedStrip(in, s, buf, cc) < 0 && !ignore)
  486.                 break;
  487.             if (TIFFWriteEncodedStrip(out, s, buf, cc) < 0) {
  488.                 free(buf);
  489.                 return (FALSE);
  490.             }
  491.             row += rowsperstrip;
  492.         }
  493.         free(buf);
  494.         return (TRUE);
  495.     }
  496.     return (FALSE);
  497. }
  498.  
  499. /*
  500.  * Separate -> separate by row for rows/strip change.
  501.  */
  502. DECLAREcpFunc(cpSeparate2SeparateByRow)
  503. {
  504.     u_char *buf = (u_char *)malloc(TIFFScanlineSize(in));
  505.     uint32 row;
  506.     tsample_t s;
  507.  
  508.     for (s = 0; s < spp; s++) {
  509.         for (row = 0; row < imagelength; row++) {
  510.             if (TIFFReadScanline(in, buf, row, s) < 0 && !ignore)
  511.                 goto done;
  512.             if (TIFFWriteScanline(out, buf, row, s) < 0)
  513.                 goto bad;
  514.         }
  515.     }
  516. done:
  517.     free(buf);
  518.     return (TRUE);
  519. bad:
  520.     free(buf);
  521.     return (FALSE);
  522. }
  523.  
  524. /*
  525.  * Contig -> separate by row.
  526.  */
  527. DECLAREcpFunc(cpContig2SeparateByRow)
  528. {
  529.     u_char *inbuf = (u_char *)malloc(TIFFScanlineSize(in));
  530.     u_char *outbuf = (u_char *)malloc(TIFFScanlineSize(out));
  531.     register u_char *inp, *outp;
  532.     register uint32 n;
  533.     uint32 row;
  534.     tsample_t s;
  535.  
  536.     /* unpack channels */
  537.     for (s = 0; s < spp; s++) {
  538.         for (row = 0; row < imagelength; row++) {
  539.             if (TIFFReadScanline(in, inbuf, row, 0) < 0 && !ignore)
  540.                 goto done;
  541.             inp = inbuf + s;
  542.             outp = outbuf;
  543.             for (n = imagewidth; n-- > 0;) {
  544.                 *outp++ = *inp;
  545.                 inp += spp;
  546.             }
  547.             if (TIFFWriteScanline(out, outbuf, row, s) < 0)
  548.                 goto bad;
  549.         }
  550.     }
  551. done:
  552.     if (inbuf) free(inbuf);
  553.     if (outbuf) free(outbuf);
  554.     return (TRUE);
  555. bad:
  556.     if (inbuf) free(inbuf);
  557.     if (outbuf) free(outbuf);
  558.     return (FALSE);
  559. }
  560.  
  561. /*
  562.  * Separate -> contig by row.
  563.  */
  564. DECLAREcpFunc(cpSeparate2ContigByRow)
  565. {
  566.     u_char *inbuf = (u_char *)malloc(TIFFScanlineSize(in));
  567.     u_char *outbuf = (u_char *)malloc(TIFFScanlineSize(out));
  568.     register u_char *inp, *outp;
  569.     register uint32 n;
  570.     uint32 row;
  571.     tsample_t s;
  572.  
  573.     for (row = 0; row < imagelength; row++) {
  574.         /* merge channels */
  575.         for (s = 0; s < spp; s++) {
  576.             if (TIFFReadScanline(in, inbuf, row, s) < 0 && !ignore)
  577.                 goto done;
  578.             inp = inbuf;
  579.             outp = outbuf + s;
  580.             for (n = imagewidth; n-- > 0;) {
  581.                 *outp = *inp++;
  582.                 outp += spp;
  583.             }
  584.         }
  585.         if (TIFFWriteScanline(out, outbuf, row, 0) < 0)
  586.             goto bad;
  587.     }
  588. done:
  589.     if (inbuf) free(inbuf);
  590.     if (outbuf) free(outbuf);
  591.     return (TRUE);
  592. bad:
  593.     if (inbuf) free(inbuf);
  594.     if (outbuf) free(outbuf);
  595.     return (FALSE);
  596. }
  597.  
  598. static void
  599. cpStripToTile(u_char* out, u_char* in,
  600.     uint32 rows, uint32 cols, int outskew, int inskew)
  601. {
  602.     while (rows-- > 0) {
  603.         uint32 j = cols;
  604.         while (j-- > 0)
  605.             *out++ = *in++;
  606.         out += outskew;
  607.         in += inskew;
  608.     }
  609. }
  610.  
  611. static void
  612. cpContigBufToSeparateBuf(u_char* out, u_char* in,
  613.     uint32 rows, uint32 cols, int outskew, int inskew, tsample_t spp)
  614. {
  615.     while (rows-- > 0) {
  616.         uint32 j = cols;
  617.         while (j-- > 0)
  618.             *out++ = *in, in += spp;
  619.         out += outskew;
  620.         in += inskew;
  621.     }
  622. }
  623.  
  624. static int
  625. cpImage(TIFF* in, TIFF* out, readFunc fin, writeFunc fout,
  626.     uint32 imagelength, uint32 imagewidth, tsample_t spp)
  627. {
  628.     u_char *buf = (u_char *) malloc(TIFFScanlineSize(in) * imagelength);
  629.     int status = FALSE;
  630.  
  631.     if (buf) {
  632.         (*fin)(in, buf, imagelength, imagewidth, spp);
  633.         status = (fout)(out, buf, imagelength, imagewidth, spp);
  634.         free(buf);
  635.     }
  636.     return (status);
  637. }
  638.  
  639. DECLAREreadFunc(readContigStripsIntoBuffer)
  640. {
  641.     tsize_t scanlinesize = TIFFScanlineSize(in);
  642.          u_char *bufp = buf;
  643.     uint32 row;
  644.  
  645.     for (row = 0; row < imagelength; row++) {
  646.         if (TIFFReadScanline(in, bufp, row, 0) < 0 && !ignore)
  647.             break;
  648.         bufp += scanlinesize;
  649.     }
  650. }
  651.  
  652. DECLAREreadFunc(readSeparateStripsIntoBuffer)
  653. {
  654.     tsize_t scanlinesize = TIFFScanlineSize(in);
  655.     u_char* scanline = (u_char *) malloc(scanlinesize);
  656.  
  657.     if (scanline) {
  658.         u_char *bufp = buf;
  659.         uint32 row;
  660.         tsample_t s;
  661.  
  662.         for (row = 0; row < imagelength; row++) {
  663.             /* merge channels */
  664.             for (s = 0; s < spp; s++) {
  665.                 u_char* sp = scanline;
  666.                 u_char* bp = bufp + s;
  667.                 tsize_t n = scanlinesize;
  668.  
  669.                 if (TIFFReadScanline(in, sp, row, s) < 0 && !ignore)
  670.                     goto done;
  671.                 while (n-- > 0)
  672.                     *bp = *bufp++, bp += spp;
  673.             }
  674.             bufp += scanlinesize;
  675.         }
  676. done:
  677.         free(scanline);
  678.     }
  679. }
  680.  
  681. DECLAREreadFunc(readContigTilesIntoBuffer)
  682. {
  683.     u_char* tilebuf = (u_char *) malloc(TIFFTileSize(in));
  684.     uint32 imagew = TIFFScanlineSize(in);
  685.     uint32 tilew  = TIFFTileRowSize(in);
  686.     int iskew = imagew - tilew;
  687.     u_char *bufp = buf;
  688.     uint32 tw, tl;
  689.     uint32 row;
  690.  
  691.     if (tilebuf == 0)
  692.         return;
  693.     (void) TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
  694.     (void) TIFFGetField(in, TIFFTAG_TILELENGTH, &tl);
  695.     for (row = 0; row < imagelength; row += tl) {
  696.         uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
  697.         uint32 colb = 0;
  698.         uint32 col;
  699.  
  700.         for (col = 0; col < imagewidth; col += tw) {
  701.             if (TIFFReadTile(in, tilebuf, col, row, 0, 0) < 0 &&
  702.                 !ignore)
  703.                 goto done;
  704.             if (colb + tilew > imagew) {
  705.                 uint32 width = imagew - colb;
  706.                 uint32 oskew = tilew - width;
  707.                 cpStripToTile(bufp + colb,
  708.                     tilebuf, nrow, width,
  709.                     oskew + iskew, oskew);
  710.             } else
  711.                 cpStripToTile(bufp + colb,
  712.                     tilebuf, nrow, tilew,
  713.                     iskew, 0);
  714.             colb += tilew;
  715.         }
  716.         bufp += imagew * nrow;
  717.     }
  718. done:
  719.     free(tilebuf);
  720. }
  721.  
  722. DECLAREreadFunc(readSeparateTilesIntoBuffer)
  723. {
  724.     uint32 imagew = TIFFScanlineSize(in);
  725.     uint32 tilew = TIFFTileRowSize(in);
  726.     int iskew  = imagew - tilew;
  727.     u_char* tilebuf = (u_char *) malloc(TIFFTileSize(in));
  728.     u_char *bufp = buf;
  729.     uint32 tw, tl;
  730.     uint32 row;
  731.  
  732.     if (tilebuf == 0)
  733.         return;
  734.     (void) TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
  735.     (void) TIFFGetField(in, TIFFTAG_TILELENGTH, &tl);
  736.     for (row = 0; row < imagelength; row += tl) {
  737.         uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
  738.         uint32 colb = 0;
  739.         uint32 col;
  740.  
  741.         for (col = 0; col < imagewidth; col += tw) {
  742.             tsample_t s;
  743.  
  744.             for (s = 0; s < spp; s++) {
  745.                 if (TIFFReadTile(in, tilebuf, col, row, 0, s) < 0 && !ignore)
  746.                     goto done;
  747.                 /*
  748.                  * Tile is clipped horizontally.  Calculate
  749.                  * visible portion and skewing factors.
  750.                  */
  751.                 if (colb + tilew > imagew) {
  752.                     uint32 width = imagew - colb;
  753.                     int oskew = tilew - width;
  754.                     cpContigBufToSeparateBuf(bufp+colb+s,
  755.                         tilebuf, nrow, width,
  756.                         oskew + imagew, oskew/spp, spp);
  757.                 } else
  758.                     cpContigBufToSeparateBuf(bufp+colb+s,
  759.                         tilebuf, nrow, tilewidth,
  760.                         iskew, 0, spp);
  761.             }
  762.             colb += tilew;
  763.         }
  764.         bufp += imagew * nrow;
  765.     }
  766. done:
  767.     free(tilebuf);
  768. }
  769.  
  770. DECLAREwriteFunc(writeBufferToContigStrips)
  771. {
  772.     tsize_t scanline = TIFFScanlineSize(out);
  773.     uint32 row;
  774.  
  775.     for (row = 0; row < imagelength; row++) {
  776.         if (TIFFWriteScanline(out, buf, row, 0) < 0)
  777.             return (FALSE);
  778.         buf += scanline;
  779.     }
  780.     return (TRUE);
  781. }
  782.  
  783. DECLAREwriteFunc(writeBufferToSeparateStrips)
  784. {
  785.     u_char *obuf = (u_char *) malloc(TIFFScanlineSize(out));
  786.     tsample_t s;
  787.  
  788.     if (obuf == NULL)
  789.         return (0);
  790.     for (s = 0; s < spp; s++) {
  791.         uint32 row;
  792.         for (row = 0; row < imagelength; row++) {
  793.             u_char* inp = buf + s;
  794.             u_char* outp = obuf;
  795.             uint32 n = imagewidth;
  796.  
  797.             while (n-- > 0)
  798.                 *outp++ = *inp, inp += spp;
  799.             if (TIFFWriteScanline(out, obuf, row, s) < 0) {
  800.                 free(obuf);
  801.                 return (FALSE);
  802.             }
  803.         }
  804.     }
  805.     free(obuf);
  806.     return (TRUE);
  807.  
  808. }
  809.  
  810. DECLAREwriteFunc(writeBufferToContigTiles)
  811. {
  812.     uint32 imagew = TIFFScanlineSize(out);
  813.     uint32 tilew  = TIFFTileRowSize(out);
  814.     int iskew = imagew - tilew;
  815.     u_char* obuf = (u_char *) malloc(TIFFTileSize(out));
  816.     u_char* bufp = buf;
  817.     uint32 tl, tw;
  818.     uint32 row;
  819.  
  820.     if (obuf == NULL)
  821.         return (FALSE);
  822.     (void) TIFFGetField(out, TIFFTAG_TILELENGTH, &tl);
  823.     (void) TIFFGetField(out, TIFFTAG_TILEWIDTH, &tw);
  824.     for (row = 0; row < imagelength; row += tilelength) {
  825.         uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
  826.         uint32 colb = 0;
  827.         uint32 col;
  828.  
  829.         for (col = 0; col < imagewidth; col += tw) {
  830.             /*
  831.              * Tile is clipped horizontally.  Calculate
  832.              * visible portion and skewing factors.
  833.              */
  834.             if (colb + tilew > imagew) {
  835.                 uint32 width = imagew - colb;
  836.                 int oskew = tilew - width;
  837.                 cpStripToTile(obuf, bufp + colb, nrow, width,
  838.                     oskew, oskew + iskew);
  839.             } else
  840.                 cpStripToTile(obuf, bufp + colb, nrow, tilew,
  841.                     0, iskew);
  842.             if (TIFFWriteTile(out, obuf, col, row, 0, 0) < 0) {
  843.                 free(obuf);
  844.                 return (FALSE);
  845.             }
  846.             colb += tilew;
  847.         }
  848.         bufp += nrow * imagew;
  849.     }
  850.     free(obuf);
  851.     return (TRUE);
  852. }
  853.  
  854. DECLAREwriteFunc(writeBufferToSeparateTiles)
  855. {
  856.     uint32 imagew = TIFFScanlineSize(out);
  857.     tsize_t tilew  = TIFFTileRowSize(out);
  858.     int iskew = imagew - tilew;
  859.     u_char *obuf = (u_char*) malloc(TIFFTileSize(out));
  860.     u_char *bufp = buf;
  861.     uint32 tl, tw;
  862.     uint32 row;
  863.  
  864.     if (obuf == NULL)
  865.         return (FALSE);
  866.     (void) TIFFGetField(out, TIFFTAG_TILELENGTH, &tl);
  867.     (void) TIFFGetField(out, TIFFTAG_TILEWIDTH, &tw);
  868.     for (row = 0; row < imagelength; row += tl) {
  869.         uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
  870.         uint32 colb = 0;
  871.         uint32 col;
  872.  
  873.         for (col = 0; col < imagewidth; col += tw) {
  874.             tsample_t s;
  875.             for (s = 0; s < spp; s++) {
  876.                 /*
  877.                  * Tile is clipped horizontally.  Calculate
  878.                  * visible portion and skewing factors.
  879.                  */
  880.                 if (colb + tilew > imagew) {
  881.                     uint32 width = imagew - colb;
  882.                     int oskew = tilew - width;
  883.  
  884.                     cpContigBufToSeparateBuf(obuf,
  885.                         bufp + colb + s,
  886.                         nrow, width,
  887.                         oskew/spp, oskew + imagew, spp);
  888.                 } else
  889.                     cpContigBufToSeparateBuf(obuf,
  890.                         bufp + colb + s,
  891.                         nrow, tilewidth,
  892.                         0, iskew, spp);
  893.                 if (TIFFWriteTile(out, obuf, col, row, 0, s) < 0) {
  894.                     free(obuf);
  895.                     return (FALSE);
  896.                 }
  897.             }
  898.             colb += tilew;
  899.         }
  900.         bufp += nrow * imagew;
  901.     }
  902.     free(obuf);
  903.     return (TRUE);
  904. }
  905.  
  906. /*
  907.  * Contig strips -> contig tiles.
  908.  */
  909. DECLAREcpFunc(cpContigStrips2ContigTiles)
  910. {
  911.     return cpImage(in, out,
  912.         readContigStripsIntoBuffer,
  913.         writeBufferToContigTiles,
  914.         imagelength, imagewidth, spp);
  915. }
  916.  
  917. /*
  918.  * Contig strips -> separate tiles.
  919.  */
  920. DECLAREcpFunc(cpContigStrips2SeparateTiles)
  921. {
  922.     return cpImage(in, out,
  923.         readContigStripsIntoBuffer,
  924.         writeBufferToSeparateTiles,
  925.         imagelength, imagewidth, spp);
  926. }
  927.  
  928. /*
  929.  * Separate strips -> contig tiles.
  930.  */
  931. DECLAREcpFunc(cpSeparateStrips2ContigTiles)
  932. {
  933.     return cpImage(in, out,
  934.         readSeparateStripsIntoBuffer,
  935.         writeBufferToContigTiles,
  936.         imagelength, imagewidth, spp);
  937. }
  938.  
  939. /*
  940.  * Separate strips -> separate tiles.
  941.  */
  942. DECLAREcpFunc(cpSeparateStrips2SeparateTiles)
  943. {
  944.     return cpImage(in, out,
  945.         readSeparateStripsIntoBuffer,
  946.         writeBufferToSeparateTiles,
  947.         imagelength, imagewidth, spp);
  948. }
  949.  
  950. /*
  951.  * Contig strips -> contig tiles.
  952.  */
  953. DECLAREcpFunc(cpContigTiles2ContigTiles)
  954. {
  955.     return cpImage(in, out,
  956.         readContigTilesIntoBuffer,
  957.         writeBufferToContigTiles,
  958.         imagelength, imagewidth, spp);
  959. }
  960.  
  961. /*
  962.  * Contig tiles -> separate tiles.
  963.  */
  964. DECLAREcpFunc(cpContigTiles2SeparateTiles)
  965. {
  966.     return cpImage(in, out,
  967.         readContigTilesIntoBuffer,
  968.         writeBufferToSeparateTiles,
  969.         imagelength, imagewidth, spp);
  970. }
  971.  
  972. /*
  973.  * Separate tiles -> contig tiles.
  974.  */
  975. DECLAREcpFunc(cpSeparateTiles2ContigTiles)
  976. {
  977.     return cpImage(in, out,
  978.         readSeparateTilesIntoBuffer,
  979.         writeBufferToContigTiles,
  980.         imagelength, imagewidth, spp);
  981. }
  982.  
  983. /*
  984.  * Separate tiles -> separate tiles (tile dimension change).
  985.  */
  986. DECLAREcpFunc(cpSeparateTiles2SeparateTiles)
  987. {
  988.     return cpImage(in, out,
  989.         readSeparateTilesIntoBuffer,
  990.         writeBufferToSeparateTiles,
  991.         imagelength, imagewidth, spp);
  992. }
  993.  
  994. /*
  995.  * Contig tiles -> contig tiles (tile dimension change).
  996.  */
  997. DECLAREcpFunc(cpContigTiles2ContigStrips)
  998. {
  999.     return cpImage(in, out,
  1000.         readContigTilesIntoBuffer,
  1001.         writeBufferToContigStrips,
  1002.         imagelength, imagewidth, spp);
  1003. }
  1004.  
  1005. /*
  1006.  * Contig tiles -> separate strips.
  1007.  */
  1008. DECLAREcpFunc(cpContigTiles2SeparateStrips)
  1009. {
  1010.     return cpImage(in, out,
  1011.         readContigTilesIntoBuffer,
  1012.         writeBufferToSeparateStrips,
  1013.         imagelength, imagewidth, spp);
  1014. }
  1015.  
  1016. /*
  1017.  * Separate tiles -> contig strips.
  1018.  */
  1019. DECLAREcpFunc(cpSeparateTiles2ContigStrips)
  1020. {
  1021.     return cpImage(in, out,
  1022.         readSeparateTilesIntoBuffer,
  1023.         writeBufferToContigStrips,
  1024.         imagelength, imagewidth, spp);
  1025. }
  1026.  
  1027. /*
  1028.  * Separate tiles -> separate strips.
  1029.  */
  1030. DECLAREcpFunc(cpSeparateTiles2SeparateStrips)
  1031. {
  1032.     return cpImage(in, out,
  1033.         readSeparateTilesIntoBuffer,
  1034.         writeBufferToSeparateStrips,
  1035.         imagelength, imagewidth, spp);
  1036. }
  1037.  
  1038. /*
  1039.  * Select the appropriate copy function to use.
  1040.  */
  1041. static copyFunc
  1042. pickCopyFunc(TIFF* in, TIFF* out, uint16 bitspersample, uint16 samplesperpixel)
  1043. {
  1044.     uint16 shortv;
  1045.     uint32 w, l, tw, tl;
  1046.     int bychunk;
  1047.  
  1048.     (void) TIFFGetField(in, TIFFTAG_PLANARCONFIG, &shortv);
  1049.     if (shortv != config && bitspersample != 8 && samplesperpixel > 1) {
  1050.         fprintf(stderr,
  1051. "%s: Can not handle different planar configuration w/ bits/sample != 8\n",
  1052.             TIFFFileName(in));
  1053.         return (NULL);
  1054.     }
  1055.     TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &w);
  1056.     TIFFGetField(in, TIFFTAG_IMAGELENGTH, &l);
  1057.     if (TIFFIsTiled(out)) {
  1058.         if (!TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw))
  1059.             tw = w;
  1060.         if (!TIFFGetField(in, TIFFTAG_TILELENGTH, &tl))
  1061.             tl = l;
  1062.         bychunk = (tw == tilewidth && tl == tilelength);
  1063.     } else if (TIFFIsTiled(in)) {
  1064.         TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
  1065.         TIFFGetField(in, TIFFTAG_TILELENGTH, &tl);
  1066.         bychunk = (tw == w && tl == rowsperstrip);
  1067.     } else {
  1068.         uint32 irps = -1L;
  1069.         TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &irps);
  1070.         bychunk = (rowsperstrip == irps);
  1071.     }
  1072. #define    T 1
  1073. #define    F 0
  1074. #define pack(a,b,c,d,e)    ((long)(((a)<<11)|((b)<<3)|((c)<<2)|((d)<<1)|(e)))
  1075.     switch(pack(shortv,config,TIFFIsTiled(in),TIFFIsTiled(out),bychunk)) {
  1076. /* Strips -> Tiles */
  1077.     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,T,F):
  1078.     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,T,T):
  1079.         return cpContigStrips2ContigTiles;
  1080.     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, F,T,F):
  1081.     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, F,T,T):
  1082.         return cpContigStrips2SeparateTiles;
  1083.         case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,T,F):
  1084.         case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,T,T):
  1085.         return cpSeparateStrips2ContigTiles;
  1086.     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,T,F):
  1087.     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,T,T):
  1088.         return cpSeparateStrips2SeparateTiles;
  1089. /* Tiles -> Tiles */
  1090.     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,T,F):
  1091.     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,T,T):
  1092.         return cpContigTiles2ContigTiles;
  1093.     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,T,F):
  1094.     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,T,T):
  1095.         return cpContigTiles2SeparateTiles;
  1096.         case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,T,F):
  1097.         case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,T,T):
  1098.         return cpSeparateTiles2ContigTiles;
  1099.     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,T,F):
  1100.     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,T,T):
  1101.         return cpSeparateTiles2SeparateTiles;
  1102. /* Tiles -> Strips */
  1103.     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,F,F):
  1104.     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,F,T):
  1105.         return cpContigTiles2ContigStrips;
  1106.     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,F,F):
  1107.     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,F,T):
  1108.         return cpContigTiles2SeparateStrips;
  1109.         case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,F,F):
  1110.         case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,F,T):
  1111.         return cpSeparateTiles2ContigStrips;
  1112.     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,F,F):
  1113.     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,F,T):
  1114.         return cpSeparateTiles2SeparateStrips;
  1115. /* Strips -> Strips */
  1116.     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,F,F):
  1117.         return cpContig2ContigByRow;
  1118.     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,F,T):
  1119.         return cpDecodedStrips;
  1120.     case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE,   F,F,F):
  1121.     case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE,   F,F,T):
  1122.         return cpContig2SeparateByRow;
  1123.     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,F,F):
  1124.     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,F,T):
  1125.         return cpSeparate2ContigByRow;
  1126.     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,F,F):
  1127.     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,F,T):
  1128.         return cpSeparate2SeparateByRow;
  1129.     }
  1130. #undef pack
  1131. #undef F
  1132. #undef T
  1133.     fprintf(stderr, "tiffcp: %s: Don't know how to copy/convert image.\n",
  1134.         TIFFFileName(in));
  1135.     return (NULL);
  1136. }
  1137.