home *** CD-ROM | disk | FTP | other *** search
/ Practical Algorithms for Image Analysis / Practical Algorithms for Image Analysis.iso / TARFILE.GZ / tarfile / libtiff / tools / tiffcp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-11  |  32.5 KB  |  1,246 lines

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