"Fossies" - the Fresh Open Source Software Archive

Member "libgeotiff-1.6.0/bin/geotifcp.c" (15 Jun 2019, 39984 Bytes) of package /linux/privat/libgeotiff-1.6.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "geotifcp.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.5.1_vs_1.6.0.

    1 /* geotifcp.c -- based on Sam Leffler's "tiffcp" code */
    2 
    3 /*
    4  *  Original code had this copyright notice: 
    5  *
    6  * Copyright (c) 1988-1995 Sam Leffler
    7  * Copyright (c) 1991-1995 Silicon Graphics, Inc.
    8  *
    9  * and a lot of legal stuff denying liability for anything.
   10  */
   11 
   12 #include <stdio.h>
   13 #include <stdlib.h>
   14 #include <string.h>
   15 #include <ctype.h>
   16 
   17 /* GeoTIFF overrides */
   18 
   19 #include "geotiff.h"
   20 #include "geo_normalize.h"
   21 #include "geo_tiffp.h"
   22 #include "geo_keyp.h"
   23 #include "xtiffio.h"
   24 #include "cpl_serv.h"
   25 
   26 #define TIFFOpen XTIFFOpen
   27 #define TIFFClose XTIFFClose
   28 
   29 #if defined(VMS)
   30 #define unlink delete
   31 #endif
   32 
   33 #define streq(a,b)  (strcmp(a,b) == 0)
   34 #define strneq(a,b,n)   (strncmp(a,b,n) == 0)
   35 
   36 #define TRUE    1
   37 #define FALSE   0
   38 
   39 int getopt();
   40 
   41 static  int outtiled = -1;
   42 static  uint32 tilewidth;
   43 static  uint32 tilelength;
   44 static  int convert_8_to_4 = 0;
   45 
   46 static  uint16 config;
   47 static  uint16 compression;
   48 static  uint16 predictor;
   49 static  uint16 fillorder;
   50 static  uint32 rowsperstrip;
   51 static  uint32 g3opts;
   52 static  int ignore = FALSE;     /* if true, ignore read errors */
   53 static  uint32 defg3opts = (uint32) -1;
   54 static  int quality = 75;       /* JPEG quality */
   55 static  int jpegcolormode = JPEGCOLORMODE_RGB;
   56 static  uint16 defcompression = (uint16) -1;
   57 static  uint16 defpredictor = (uint16) -1;
   58 static  char *geofile=(char *)0;
   59 static  char *proj4_string = (char *) 0;
   60 static  char *worldfile=(char *)0;
   61 
   62 static  void ApplyWorldFile(const char *worldfile, TIFF *out);
   63 static  int tiffcp(TIFF*, TIFF*);
   64 static  int processCompressOptions(char*);
   65 static  void usage(void);
   66 
   67 static  int forced_version = 0;
   68 static  unsigned short version = 0;
   69 static  unsigned short key_version = 0;
   70 static  unsigned short minor_revision = 0;
   71 
   72 static int parseVersion(const char* str)
   73 {
   74     if( strlen(str) != 5 || str[1] != ':' || str[3] != ':' )
   75         return 0;
   76     if( str[0] < '0' || str[0] > '9' )
   77         return 0;
   78     if( str[2] < '0' || str[2] > '9' )
   79         return 0;
   80     if( str[4] < '0' || str[4] > '9' )
   81         return 0;
   82     forced_version = 1;
   83     version = str[0] - '0';
   84     key_version = str[2] - '0';
   85     minor_revision = str[4] - '0';
   86     return 1;
   87 }
   88 
   89 static void SetVersionNumbers(GTIF* gtif)
   90 {
   91     if( forced_version )
   92     {
   93         GTIFSetVersionNumbers(gtif, version, key_version, minor_revision);
   94     }
   95 }
   96 
   97 int
   98 main(int argc, char* argv[])
   99 {
  100     uint16 defconfig = (uint16) -1;
  101     uint16 deffillorder = 0;
  102     uint32 deftilewidth = (uint32) -1;
  103     uint32 deftilelength = (uint32) -1;
  104     uint32 defrowsperstrip = (uint32) -1;
  105     uint32 diroff = 0;
  106     TIFF* in;
  107     TIFF* out;
  108     char mode[10];
  109     char* mp = mode;
  110     int c;
  111     extern int optind;
  112     extern char* optarg;
  113 
  114     *mp++ = 'w';
  115     *mp = '\0';
  116     while ((c = getopt(argc, argv, "c:f:l:o:p:r:w:e:g:4:v:aistd8BLMC")) != -1)
  117         switch (c) {
  118         case 'a':       /* append to output */
  119             mode[0] = 'a';
  120             break;
  121         case 'd':       /* down cast 8bit to 4bit */
  122                         convert_8_to_4 = 1;
  123             break;
  124         case 'c':       /* compression scheme */
  125             if (!processCompressOptions(optarg))
  126                 usage();
  127             break;
  128                 case 'e':
  129                         worldfile = optarg;
  130                         break;
  131         case 'f':       /* fill order */
  132             if (streq(optarg, "lsb2msb"))
  133                 deffillorder = FILLORDER_LSB2MSB;
  134             else if (streq(optarg, "msb2lsb"))
  135                 deffillorder = FILLORDER_MSB2LSB;
  136             else
  137                 usage();
  138             break;
  139         case 'i':       /* ignore errors */
  140             ignore = TRUE;
  141             break;
  142         case 'g':       /* GeoTIFF metadata file */
  143             geofile = optarg;
  144             break;
  145         case '4':          
  146             proj4_string = optarg;
  147             break;
  148         case 'l':       /* tile length */
  149             outtiled = TRUE;
  150             deftilelength = atoi(optarg);
  151             break;
  152         case 'o':       /* initial directory offset */
  153             diroff = strtoul(optarg, NULL, 0);
  154             break;
  155         case 'p':       /* planar configuration */
  156             if (streq(optarg, "separate"))
  157                 defconfig = PLANARCONFIG_SEPARATE;
  158             else if (streq(optarg, "contig"))
  159                 defconfig = PLANARCONFIG_CONTIG;
  160             else
  161                 usage();
  162             break;
  163         case 'r':       /* rows/strip */
  164             defrowsperstrip = atoi(optarg);
  165             break;
  166         case 's':       /* generate stripped output */
  167             outtiled = FALSE;
  168             break;
  169         case 't':       /* generate tiled output */
  170             outtiled = TRUE;
  171             break;
  172         case 'w':       /* tile width */
  173             outtiled = TRUE;
  174             deftilewidth = atoi(optarg);
  175             break;
  176         case 'B':
  177             *mp++ = 'b'; *mp = '\0';
  178             break;
  179         case 'L':
  180             *mp++ = 'l'; *mp = '\0';
  181             break;
  182         case 'M':
  183             *mp++ = 'm'; *mp = '\0';
  184             break;
  185         case 'C':
  186             *mp++ = 'c'; *mp = '\0';
  187             break;
  188         case '8':
  189             *mp++ = '8'; *mp = '\0';
  190             break;
  191         case 'v':
  192             if (!parseVersion(optarg))
  193                 usage();
  194             break;
  195         case '?':
  196             usage();
  197             /*NOTREACHED*/
  198         }
  199     if (argc - optind < 2)
  200         usage();
  201         printf( "mode=%s\n", mode);
  202     out = TIFFOpen(argv[argc-1], mode);
  203     if (out == NULL)
  204         return (-2);
  205     for (; optind < argc-1 ; optind++) {
  206         in = TIFFOpen(argv[optind], "r");
  207         if (in == NULL)
  208             return (-3);
  209         if (diroff != 0 && !TIFFSetSubDirectory(in, diroff)) {
  210             TIFFError(TIFFFileName(in),
  211                 "Error, setting subdirectory at %#x", diroff);
  212             (void) TIFFClose(out);
  213             return (1);
  214         }
  215         do {
  216             config = defconfig;
  217             compression = defcompression;
  218             predictor = defpredictor;
  219             fillorder = deffillorder;
  220             rowsperstrip = defrowsperstrip;
  221             tilewidth = deftilewidth;
  222             tilelength = deftilelength;
  223             g3opts = defg3opts;
  224             if (!tiffcp(in, out) || !TIFFWriteDirectory(out)) {
  225                 (void) TIFFClose(out);
  226                 return (1);
  227             }
  228         } while (TIFFReadDirectory(in));
  229         (void) TIFFClose(in);
  230     }
  231     (void) TIFFClose(out);
  232     return (0);
  233 }
  234 
  235 static void ApplyWorldFile(const char *worldfilename, TIFF *out)
  236 
  237 {
  238     FILE    *tfw;
  239     double  pixsize[3], xoff, yoff, tiepoint[6], x_rot, y_rot;
  240     int         success;
  241 
  242     /* 
  243      * Read the world file.  Note we currently ignore rotational coefficients!
  244      */
  245     tfw = fopen( worldfilename, "rt" );
  246     if( tfw == NULL )
  247     {
  248         perror( worldfilename );
  249         return;
  250     }
  251 
  252     success  = fscanf( tfw, "%lf", pixsize + 0 );
  253     success &= fscanf( tfw, "%lf", &y_rot );
  254     success &= fscanf( tfw, "%lf", &x_rot );
  255     success &= fscanf( tfw, "%lf", pixsize + 1 );
  256     success &= fscanf( tfw, "%lf", &xoff );
  257     success &= fscanf( tfw, "%lf", &yoff );
  258 
  259     fclose( tfw );
  260 
  261     if( success != 1 )
  262     {
  263         fprintf( stderr, "Failure parsing one or more lines of world file.\n");
  264         return;
  265     }
  266 
  267     /*
  268      * Write out pixel scale, and tiepoint information.
  269      */
  270     if( x_rot == 0.0 && y_rot == 0.0 )
  271     {
  272         pixsize[1] = ABS(pixsize[1]);
  273         pixsize[2] = 0.0;
  274         TIFFSetField(out, GTIFF_PIXELSCALE, 3, pixsize);
  275 
  276         tiepoint[0] = 0.5;
  277         tiepoint[1] = 0.5;
  278         tiepoint[2] = 0.0;
  279         tiepoint[3] = xoff;
  280         tiepoint[4] = yoff;
  281         tiepoint[5] = 0.0;
  282         TIFFSetField(out, GTIFF_TIEPOINTS, 6, tiepoint);
  283     }
  284     else
  285     {
  286         double  adfMatrix[16];
  287         
  288         memset(adfMatrix,0,sizeof(double) * 16);
  289         
  290         adfMatrix[0] = pixsize[0];
  291         adfMatrix[1] = x_rot;
  292         adfMatrix[3] = xoff - (pixsize[0]+x_rot) * 0.5;
  293         adfMatrix[4] = y_rot;
  294         adfMatrix[5] = pixsize[1];
  295         adfMatrix[7] = yoff - (pixsize[1]+y_rot) * 0.5;
  296         adfMatrix[15] = 1.0;
  297         
  298         TIFFSetField( out, TIFFTAG_GEOTRANSMATRIX, 16, adfMatrix );
  299     }
  300 }
  301 
  302 static void InstallGeoTIFF(TIFF *out)
  303 {
  304     GTIF *gtif; /* GeoKey-level descriptor */
  305     FILE *fd;
  306 
  307     gtif = GTIFNew(out);
  308     if (!gtif)
  309     {
  310         printf("failed in GTIFNew\n");
  311         return;
  312     }
  313 
  314     if( geofile )
  315     {
  316         /* Install keys and tags */
  317         fd = fopen(geofile,"r");
  318         if( fd == NULL )
  319         {
  320             perror( geofile );
  321             exit( -1 );
  322         }
  323         if (!GTIFImport(gtif,0,fd))
  324         {
  325             fprintf(stderr,"Failure in GTIFImport\n");
  326             exit (-1);
  327         }
  328         fclose(fd);
  329     }
  330     else if( proj4_string )
  331     {
  332         if( !GTIFSetFromProj4(gtif,proj4_string) )
  333         {
  334             fprintf(stderr,"Failure in GTIFSetFromProj4\n");
  335             exit (-1);
  336         }
  337     }
  338     SetVersionNumbers(gtif);
  339     GTIFWriteKeys(gtif);
  340     GTIFFree(gtif);
  341     return;
  342 }
  343 
  344 static void CopyGeoTIFF(TIFF * in, TIFF *out)
  345 {
  346     GTIF *gtif; /* GeoKey-level descriptor */
  347     double *d_list = NULL;
  348     int16   d_list_count;
  349 
  350     /* read definition from source file. */
  351     gtif = GTIFNew(in);
  352     if (!gtif)
  353         return;
  354 
  355     if (TIFFGetField(in, GTIFF_TIEPOINTS, &d_list_count, &d_list))
  356         TIFFSetField(out, GTIFF_TIEPOINTS, d_list_count, d_list);
  357     if (TIFFGetField(in, GTIFF_PIXELSCALE, &d_list_count, &d_list))
  358         TIFFSetField(out, GTIFF_PIXELSCALE, d_list_count, d_list);
  359     if (TIFFGetField(in, GTIFF_TRANSMATRIX, &d_list_count, &d_list))
  360         TIFFSetField(out, GTIFF_TRANSMATRIX, d_list_count, d_list);
  361             
  362     /* Here we violate the GTIF abstraction to retarget on another file.
  363        We should just have a function for copying tags from one GTIF object
  364        to another. */
  365     gtif->gt_tif = out;
  366     gtif->gt_flags |= FLAG_FILE_MODIFIED;
  367 
  368     /* Install keys and tags */
  369     SetVersionNumbers(gtif);
  370     GTIFWriteKeys(gtif);
  371     GTIFFree(gtif);
  372     return;
  373 }
  374 
  375 static void
  376 processG3Options(char* cp)
  377 {
  378     if( (cp = strchr(cp, ':')) != NULL ) {
  379         if (defg3opts == (uint32) -1)
  380             defg3opts = 0;
  381         do {
  382             cp++;
  383             if (strneq(cp, "1d", 2))
  384                 defg3opts &= ~GROUP3OPT_2DENCODING;
  385             else if (strneq(cp, "2d", 2))
  386                 defg3opts |= GROUP3OPT_2DENCODING;
  387             else if (strneq(cp, "fill", 4))
  388                 defg3opts |= GROUP3OPT_FILLBITS;
  389             else
  390                 usage();
  391         } while( (cp = strchr(cp, ':')) != NULL );
  392     }
  393 }
  394 
  395 static int
  396 processCompressOptions(char* opt)
  397 {
  398     if (streq(opt, "none"))
  399         defcompression = COMPRESSION_NONE;
  400     else if (streq(opt, "packbits"))
  401         defcompression = COMPRESSION_PACKBITS;
  402     else if (strneq(opt, "jpeg", 4)) {
  403         char* cp = strchr(opt, ':');
  404         if (cp && isdigit(cp[1]))
  405             quality = atoi(cp+1);
  406         if (cp && strchr(cp, 'r'))
  407             jpegcolormode = JPEGCOLORMODE_RAW;
  408         defcompression = COMPRESSION_JPEG;
  409     } else if (strneq(opt, "g3", 2)) {
  410         processG3Options(opt);
  411         defcompression = COMPRESSION_CCITTFAX3;
  412     } else if (streq(opt, "g4"))
  413         defcompression = COMPRESSION_CCITTFAX4;
  414     else if (strneq(opt, "lzw", 3)) {
  415         char* cp = strchr(opt, ':');
  416         if (cp)
  417             defpredictor = atoi(cp+1);
  418         defcompression = COMPRESSION_LZW;
  419     } else if (strneq(opt, "zip", 3)) {
  420         char* cp = strchr(opt, ':');
  421         if (cp)
  422             defpredictor = atoi(cp+1);
  423         defcompression = COMPRESSION_DEFLATE;
  424     } else
  425         return (0);
  426     return (1);
  427 }
  428 
  429 char* stuff[] = {
  430 "usage: gtiffcp [options] input... output",
  431 "where options are:",
  432 " -g file   install GeoTIFF metadata from <file>",
  433 " -4 proj4_str  install GeoTIFF metadata from proj4 string",
  434 " -e file   install positioning info from ESRI Worldfile <file>",
  435 " -v v:k:m      force the GeoTIFF version numbers (v=version, k=key_major, m=minor_rev)",
  436 " -a        append to output instead of overwriting",
  437 " -8        write BigTIFF instead of default ClassicTIFF",
  438 " -o offset set initial directory offset",
  439 " -p contig pack samples contiguously (e.g. RGBRGB...)",
  440 " -p separate   store samples separately (e.g. RRR...GGG...BBB...)",
  441 " -s        write output in strips",
  442 " -t        write output in tiles",
  443 " -i        ignore read errors",
  444 " -d        truncate 8 bitspersample to 4bitspersample",
  445 "",
  446 " -r #      make each strip have no more than # rows",
  447 " -w #      set output tile width (pixels)",
  448 " -l #      set output tile length (pixels)",
  449 "",
  450 " -f lsb2msb    force lsb-to-msb FillOrder for output",
  451 " -f msb2lsb    force msb-to-lsb FillOrder for output",
  452 "",
  453 " -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
  454 " -c zip[:opts] compress output with deflate encoding",
  455 " -c jpeg[:opts]compress output with JPEG encoding",
  456 " -c packbits   compress output with packbits encoding",
  457 " -c g3[:opts]  compress output with CCITT Group 3 encoding",
  458 " -c g4     compress output with CCITT Group 4 encoding",
  459 " -c none   use no compression algorithm on output",
  460 "",
  461 "Group 3 options:",
  462 " 1d        use default CCITT Group 3 1D-encoding",
  463 " 2d        use optional CCITT Group 3 2D-encoding",
  464 " fill      byte-align EOL codes",
  465 "For example, -c g3:2d:fill to get G3-2D-encoded data with byte-aligned EOLs",
  466 "",
  467 "JPEG options:",
  468 " #     set compression quality level (0-100, default 75)",
  469 " r     output color image as RGB rather than YCbCr",
  470 "For example, -c jpeg:r:50 to get JPEG-encoded RGB data with 50% comp. quality",
  471 "",
  472 "LZW and deflate options:",
  473 " #     set predictor value",
  474 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
  475 NULL
  476 };
  477 
  478 static void
  479 usage(void)
  480 {
  481     char buf[BUFSIZ];
  482     int i;
  483 
  484     setbuf(stderr, buf);
  485     for (i = 0; stuff[i] != NULL; i++)
  486         fprintf(stderr, "%s\n", stuff[i]);
  487     exit(-1);
  488 }
  489 
  490 static void
  491 CheckAndCorrectColormap(TIFF* tif, int n, uint16* r, uint16* g, uint16* b)
  492 {
  493     int i;
  494 
  495     for (i = 0; i < n; i++)
  496         if (r[i] >= 256 || g[i] >= 256 || b[i] >= 256)
  497             return;
  498     TIFFWarning(TIFFFileName(tif), "Scaling 8-bit colormap");
  499 #define CVT(x)      (((x) * ((1L<<16)-1)) / 255)
  500     for (i = 0; i < n; i++) {
  501         r[i] = CVT(r[i]);
  502         g[i] = CVT(g[i]);
  503         b[i] = CVT(b[i]);
  504     }
  505 #undef CVT
  506 }
  507 
  508 #define CopyField(tag, v) \
  509     if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
  510 #define CopyField2(tag, v1, v2) \
  511     if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
  512 #define CopyField3(tag, v1, v2, v3) \
  513     if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
  514 #define CopyField4(tag, v1, v2, v3, v4) \
  515     if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4)
  516 
  517 static struct cpTag {
  518     uint16  tag;
  519     uint16  count;
  520     TIFFDataType type;
  521 } tags[] = {
  522     { TIFFTAG_SUBFILETYPE,      1, TIFF_LONG },
  523     { TIFFTAG_THRESHHOLDING,    1, TIFF_SHORT },
  524     { TIFFTAG_DOCUMENTNAME,     1, TIFF_ASCII },
  525     { TIFFTAG_IMAGEDESCRIPTION, 1, TIFF_ASCII },
  526     { TIFFTAG_MAKE,         1, TIFF_ASCII },
  527     { TIFFTAG_MODEL,        1, TIFF_ASCII },
  528     { TIFFTAG_ORIENTATION,      1, TIFF_SHORT },
  529     { TIFFTAG_MINSAMPLEVALUE,   1, TIFF_SHORT },
  530     { TIFFTAG_MAXSAMPLEVALUE,   1, TIFF_SHORT },
  531     { TIFFTAG_XRESOLUTION,      1, TIFF_RATIONAL },
  532     { TIFFTAG_YRESOLUTION,      1, TIFF_RATIONAL },
  533     { TIFFTAG_PAGENAME,     1, TIFF_ASCII },
  534     { TIFFTAG_XPOSITION,        1, TIFF_RATIONAL },
  535     { TIFFTAG_YPOSITION,        1, TIFF_RATIONAL },
  536     { TIFFTAG_GROUP4OPTIONS,    1, TIFF_LONG },
  537     { TIFFTAG_RESOLUTIONUNIT,   1, TIFF_SHORT },
  538     { TIFFTAG_PAGENUMBER,       2, TIFF_SHORT },
  539     { TIFFTAG_SOFTWARE,     1, TIFF_ASCII },
  540     { TIFFTAG_DATETIME,     1, TIFF_ASCII },
  541     { TIFFTAG_ARTIST,       1, TIFF_ASCII },
  542     { TIFFTAG_HOSTCOMPUTER,     1, TIFF_ASCII },
  543     { TIFFTAG_WHITEPOINT,       (uint16) -1,TIFF_RATIONAL },
  544     { TIFFTAG_PRIMARYCHROMATICITIES,(uint16) -1,TIFF_RATIONAL },
  545     { TIFFTAG_HALFTONEHINTS,    2, TIFF_SHORT },
  546     { TIFFTAG_BADFAXLINES,      1, TIFF_LONG },
  547     { TIFFTAG_CLEANFAXDATA,     1, TIFF_SHORT },
  548     { TIFFTAG_CONSECUTIVEBADFAXLINES,1, TIFF_LONG },
  549     { TIFFTAG_INKSET,       1, TIFF_SHORT },
  550     { TIFFTAG_INKNAMES,     1, TIFF_ASCII },
  551     { TIFFTAG_DOTRANGE,     2, TIFF_SHORT },
  552     { TIFFTAG_TARGETPRINTER,    1, TIFF_ASCII },
  553     { TIFFTAG_SAMPLEFORMAT,     1, TIFF_SHORT },
  554     { TIFFTAG_YCBCRCOEFFICIENTS,    (uint16) -1,TIFF_RATIONAL },
  555     { TIFFTAG_YCBCRSUBSAMPLING, 2, TIFF_SHORT },
  556     { TIFFTAG_YCBCRPOSITIONING, 1, TIFF_SHORT },
  557     { TIFFTAG_REFERENCEBLACKWHITE,  (uint16) -1,TIFF_RATIONAL },
  558     { TIFFTAG_EXTRASAMPLES,     (uint16) -1, TIFF_SHORT },
  559     { TIFFTAG_SMINSAMPLEVALUE,  1, TIFF_DOUBLE },
  560     { TIFFTAG_SMAXSAMPLEVALUE,  1, TIFF_DOUBLE },
  561 };
  562 #define NTAGS   (sizeof (tags) / sizeof (tags[0]))
  563 
  564 static void
  565 cpOtherTags(TIFF* in, TIFF* out)
  566 {
  567     struct cpTag *p;
  568 
  569     for (p = tags; p < &tags[NTAGS]; p++)
  570         switch (p->type) {
  571         case TIFF_SHORT:
  572             if (p->count == 1) {
  573                 uint16 shortv;
  574                 CopyField(p->tag, shortv);
  575             } else if (p->count == 2) {
  576                 uint16 shortv1, shortv2;
  577                 CopyField2(p->tag, shortv1, shortv2);
  578             } else if (p->count == (uint16) -1) {
  579                 uint16 shortv1;
  580                 uint16* shortav;
  581                 CopyField2(p->tag, shortv1, shortav);
  582             }
  583             break;
  584         case TIFF_LONG:
  585             { uint32 longv;
  586               CopyField(p->tag, longv);
  587             }
  588             break;
  589         case TIFF_RATIONAL:
  590             if (p->count == 1) {
  591                 float floatv;
  592                 CopyField(p->tag, floatv);
  593             } else if (p->count == (uint16) -1) {
  594                 float* floatav;
  595                 CopyField(p->tag, floatav);
  596             }
  597             break;
  598         case TIFF_ASCII:
  599             { char* stringv;
  600               CopyField(p->tag, stringv);
  601             }
  602             break;
  603         case TIFF_DOUBLE:
  604             if (p->count == 1) {
  605                 double doublev;
  606                 CopyField(p->tag, doublev);
  607             } else if (p->count == (uint16) -1) {
  608                 double* doubleav;
  609                 CopyField(p->tag, doubleav);
  610             }
  611             break;
  612                 default:
  613                     break;
  614         }
  615 }
  616 
  617 typedef int (*copyFunc)
  618     (TIFF* in, TIFF* out, uint32 l, uint32 w, uint16 samplesperpixel);
  619 static  copyFunc pickCopyFunc(TIFF*, TIFF*, uint16, uint16);
  620 
  621 static int
  622 tiffcp(TIFF* in, TIFF* out)
  623 {
  624     uint16 bitspersample = 0, samplesperpixel, shortv;
  625     copyFunc cf;
  626     uint32 w, l;
  627 
  628     CopyField(TIFFTAG_IMAGEWIDTH, w);
  629     CopyField(TIFFTAG_IMAGELENGTH, l);
  630         if( convert_8_to_4 )
  631         {
  632             TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 4);
  633         }
  634         else
  635         {
  636             CopyField(TIFFTAG_BITSPERSAMPLE, bitspersample);
  637         }
  638     if (compression != (uint16)-1)
  639         TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
  640     else
  641         CopyField(TIFFTAG_COMPRESSION, compression);
  642     if (compression == COMPRESSION_JPEG && jpegcolormode == JPEGCOLORMODE_RGB)
  643         TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
  644     else
  645         CopyField(TIFFTAG_PHOTOMETRIC, shortv);
  646     if (fillorder != 0)
  647         TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
  648     else
  649         CopyField(TIFFTAG_FILLORDER, shortv);
  650     CopyField(TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
  651     /*
  652      * Choose tiles/strip for the output image according to
  653      * the command line arguments (-tiles, -strips) and the
  654      * structure of the input image.
  655      */
  656     if (outtiled == -1)
  657         outtiled = TIFFIsTiled(in);
  658     if (outtiled) {
  659         /*
  660          * Setup output file's tile width&height.  If either
  661          * is not specified, use either the value from the
  662          * input image or, if nothing is defined, use the
  663          * library default.
  664          */
  665         if (tilewidth == (uint32) -1)
  666             TIFFGetField(in, TIFFTAG_TILEWIDTH, &tilewidth);
  667         if (tilelength == (uint32) -1)
  668             TIFFGetField(in, TIFFTAG_TILELENGTH, &tilelength);
  669         TIFFDefaultTileSize(out, &tilewidth, &tilelength);
  670         TIFFSetField(out, TIFFTAG_TILEWIDTH, tilewidth);
  671         TIFFSetField(out, TIFFTAG_TILELENGTH, tilelength);
  672     } else {
  673         /*
  674          * RowsPerStrip is left unspecified: use either the
  675          * value from the input image or, if nothing is defined,
  676          * use the library default.
  677          */
  678         if (rowsperstrip == (uint32) -1)
  679             TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
  680         rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip);
  681         TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
  682     }
  683     if (config != (uint16) -1)
  684         TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
  685     else
  686         CopyField(TIFFTAG_PLANARCONFIG, config);
  687     if (g3opts != (uint32) -1)
  688         TIFFSetField(out, TIFFTAG_GROUP3OPTIONS, g3opts);
  689     else
  690         CopyField(TIFFTAG_GROUP3OPTIONS, g3opts);
  691     if (samplesperpixel <= 4) {
  692         uint16 *tr, *tg, *tb, *ta;
  693         CopyField4(TIFFTAG_TRANSFERFUNCTION, tr, tg, tb, ta);
  694     }
  695     { uint16 *red, *green, *blue;
  696       if (TIFFGetField(in, TIFFTAG_COLORMAP, &red, &green, &blue)) {
  697         CheckAndCorrectColormap(in, 1<<bitspersample, red, green, blue);
  698         TIFFSetField(out, TIFFTAG_COLORMAP, red, green, blue);
  699       }
  700     }
  701 /* SMinSampleValue & SMaxSampleValue */
  702     switch (compression) {
  703     case COMPRESSION_JPEG:
  704         TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
  705         TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode);
  706         break;
  707     case COMPRESSION_LZW:
  708     case COMPRESSION_DEFLATE:
  709         if (predictor != (uint16)-1)
  710             TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
  711         else
  712             CopyField(TIFFTAG_PREDICTOR, predictor);
  713         break;
  714     }
  715     cpOtherTags(in, out);
  716 
  717     if (geofile || proj4_string )
  718             InstallGeoTIFF(out);
  719         else
  720             CopyGeoTIFF(in,out);
  721 
  722         if( worldfile )
  723             ApplyWorldFile( worldfile, out);
  724 
  725     cf = pickCopyFunc(in, out, bitspersample, samplesperpixel);
  726     return (cf ? (*cf)(in, out, l, w, samplesperpixel) : FALSE);
  727 }
  728 
  729 /*
  730  * Copy Functions.
  731  */
  732 #define DECLAREcpFunc(x) \
  733 static int x(TIFF* in, TIFF* out, \
  734     uint32 imagelength, uint32 imagewidth, tsample_t spp)
  735 
  736 #define DECLAREreadFunc(x) \
  737 static void x(TIFF* in, \
  738     unsigned char* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)
  739 typedef void (*readFunc)(TIFF*, unsigned char*, uint32, uint32, tsample_t);
  740 
  741 #define DECLAREwriteFunc(x) \
  742 static int x(TIFF* out, \
  743     unsigned char* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)
  744 typedef int (*writeFunc)(TIFF*, unsigned char*, uint32, uint32, tsample_t);
  745 
  746 /*
  747  * Contig -> contig by scanline for rows/strip change.
  748  */
  749 DECLAREcpFunc(cpContig2ContigByRow)
  750 {
  751     unsigned char *buf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
  752     uint32 row;
  753 
  754     (void) imagewidth; (void) spp;
  755     for (row = 0; row < imagelength; row++) {
  756         if (TIFFReadScanline(in, buf, row, 0) < 0 && !ignore)
  757             goto done;
  758         if (TIFFWriteScanline(out, buf, row, 0) < 0)
  759             goto bad;
  760     }
  761 done:
  762     _TIFFfree(buf);
  763     return (TRUE);
  764 bad:
  765     _TIFFfree(buf);
  766     return (FALSE);
  767 }
  768 
  769 /*
  770  * Contig -> contig by scanline for rows/strip change.
  771  */
  772 DECLAREcpFunc(cpContig2ContigByRow_8_to_4)
  773 {
  774     unsigned char *buf_in = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
  775     unsigned char *buf_out = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(out));
  776     uint32 row;
  777 
  778     printf( "Downsample\n" );
  779 
  780     (void) spp;
  781     for (row = 0; row < imagelength; row++) {
  782         int i_in, i_out_byte;
  783             
  784         if (TIFFReadScanline(in, buf_in, row, 0) < 0 && !ignore)
  785             goto done;
  786 
  787         for( i_in = 0, i_out_byte = 0;
  788              (unsigned)i_in < imagewidth;
  789              i_in += 2, i_out_byte++ )
  790         {
  791             buf_out[i_out_byte] =
  792                 (buf_in[i_in] & 0xf)*16 + (buf_in[i_in+1] & 0xf);
  793         }
  794         
  795         if (TIFFWriteScanline(out, buf_out, row, 0) < 0)
  796             goto bad;
  797     }
  798   done:
  799     _TIFFfree(buf_in);
  800     _TIFFfree(buf_out);
  801     return (TRUE);
  802   bad:
  803     _TIFFfree(buf_in);
  804     _TIFFfree(buf_out);
  805     return (FALSE);
  806 }
  807 
  808 /*
  809  * Strip -> strip for change in encoding.
  810  */
  811 DECLAREcpFunc(cpDecodedStrips)
  812 {
  813     tsize_t stripsize  = TIFFStripSize(in);
  814     unsigned char *buf = (unsigned char *)_TIFFmalloc(stripsize);
  815 
  816     (void) imagewidth; (void) spp;
  817     if (buf) {
  818         tstrip_t s, ns = TIFFNumberOfStrips(in);
  819         uint32 row = 0;
  820         for (s = 0; s < ns; s++) {
  821             tsize_t cc = (row + rowsperstrip > imagelength) ?
  822                 TIFFVStripSize(in, imagelength - row) : stripsize;
  823             if (TIFFReadEncodedStrip(in, s, buf, cc) < 0 && !ignore)
  824                 break;
  825             if (TIFFWriteEncodedStrip(out, s, buf, cc) < 0) {
  826                 _TIFFfree(buf);
  827                 return (FALSE);
  828             }
  829             row += rowsperstrip;
  830         }
  831         _TIFFfree(buf);
  832         return (TRUE);
  833     }
  834     return (FALSE);
  835 }
  836 
  837 /*
  838  * Separate -> separate by row for rows/strip change.
  839  */
  840 DECLAREcpFunc(cpSeparate2SeparateByRow)
  841 {
  842     unsigned char *buf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
  843     uint32 row;
  844     tsample_t s;
  845 
  846     (void) imagewidth;
  847     for (s = 0; s < spp; s++) {
  848         for (row = 0; row < imagelength; row++) {
  849             if (TIFFReadScanline(in, buf, row, s) < 0 && !ignore)
  850                 goto done;
  851             if (TIFFWriteScanline(out, buf, row, s) < 0)
  852                 goto bad;
  853         }
  854     }
  855 done:
  856     _TIFFfree(buf);
  857     return (TRUE);
  858 bad:
  859     _TIFFfree(buf);
  860     return (FALSE);
  861 }
  862 
  863 /*
  864  * Contig -> separate by row.
  865  */
  866 DECLAREcpFunc(cpContig2SeparateByRow)
  867 {
  868     unsigned char *inbuf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
  869     unsigned char *outbuf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(out));
  870     register unsigned char *inp, *outp;
  871     register uint32 n;
  872     uint32 row;
  873     tsample_t s;
  874 
  875     /* unpack channels */
  876     for (s = 0; s < spp; s++) {
  877         for (row = 0; row < imagelength; row++) {
  878             if (TIFFReadScanline(in, inbuf, row, 0) < 0 && !ignore)
  879                 goto done;
  880             inp = inbuf + s;
  881             outp = outbuf;
  882             for (n = imagewidth; n-- > 0;) {
  883                 *outp++ = *inp;
  884                 inp += spp;
  885             }
  886             if (TIFFWriteScanline(out, outbuf, row, s) < 0)
  887                 goto bad;
  888         }
  889     }
  890 done:
  891     if (inbuf) _TIFFfree(inbuf);
  892     if (outbuf) _TIFFfree(outbuf);
  893     return (TRUE);
  894 bad:
  895     if (inbuf) _TIFFfree(inbuf);
  896     if (outbuf) _TIFFfree(outbuf);
  897     return (FALSE);
  898 }
  899 
  900 /*
  901  * Separate -> contig by row.
  902  */
  903 DECLAREcpFunc(cpSeparate2ContigByRow)
  904 {
  905     unsigned char *inbuf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
  906     unsigned char *outbuf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(out));
  907     register unsigned char *inp, *outp;
  908     register uint32 n;
  909     uint32 row;
  910     tsample_t s;
  911 
  912     for (row = 0; row < imagelength; row++) {
  913         /* merge channels */
  914         for (s = 0; s < spp; s++) {
  915             if (TIFFReadScanline(in, inbuf, row, s) < 0 && !ignore)
  916                 goto done;
  917             inp = inbuf;
  918             outp = outbuf + s;
  919             for (n = imagewidth; n-- > 0;) {
  920                 *outp = *inp++;
  921                 outp += spp;
  922             }
  923         }
  924         if (TIFFWriteScanline(out, outbuf, row, 0) < 0)
  925             goto bad;
  926     }
  927 done:
  928     if (inbuf) _TIFFfree(inbuf);
  929     if (outbuf) _TIFFfree(outbuf);
  930     return (TRUE);
  931 bad:
  932     if (inbuf) _TIFFfree(inbuf);
  933     if (outbuf) _TIFFfree(outbuf);
  934     return (FALSE);
  935 }
  936 
  937 static void
  938 cpStripToTile(unsigned char* out, unsigned char* in,
  939     uint32 rows, uint32 cols, int outskew, int inskew)
  940 {
  941     while (rows-- > 0) {
  942         uint32 j = cols;
  943         while (j-- > 0)
  944             *out++ = *in++;
  945         out += outskew;
  946         in += inskew;
  947     }
  948 }
  949 
  950 static void
  951 cpContigBufToSeparateBuf(unsigned char* out, unsigned char* in,
  952     uint32 rows, uint32 cols, int outskew, int inskew, tsample_t spp)
  953 {
  954     while (rows-- > 0) {
  955         uint32 j = cols;
  956         while (j-- > 0)
  957             *out++ = *in, in += spp;
  958         out += outskew;
  959         in += inskew;
  960     }
  961 }
  962 
  963 static void
  964 cpSeparateBufToContigBuf(unsigned char* out, unsigned char* in,
  965     uint32 rows, uint32 cols, int outskew, int inskew, tsample_t spp)
  966 {
  967     while (rows-- > 0) {
  968         uint32 j = cols;
  969         while (j-- > 0)
  970             *out = *in++, out += spp;
  971         out += outskew;
  972         in += inskew;
  973     }
  974 }
  975 
  976 static int
  977 cpImage(TIFF* in, TIFF* out, readFunc fin, writeFunc fout,
  978     uint32 imagelength, uint32 imagewidth, tsample_t spp)
  979 {
  980     int status = FALSE;
  981     unsigned char* buf = (unsigned char *)
  982         _TIFFmalloc(TIFFRasterScanlineSize(in) * imagelength);
  983     if (buf) {
  984         (*fin)(in, buf, imagelength, imagewidth, spp);
  985         status = (fout)(out, buf, imagelength, imagewidth, spp);
  986         _TIFFfree(buf);
  987     }
  988     return (status);
  989 }
  990 
  991 DECLAREreadFunc(readContigStripsIntoBuffer)
  992 {
  993     tsize_t scanlinesize = TIFFScanlineSize(in);
  994         unsigned char *bufp = buf;
  995     uint32 row;
  996 
  997     (void) imagewidth; (void) spp;
  998     for (row = 0; row < imagelength; row++) {
  999         if (TIFFReadScanline(in, bufp, row, 0) < 0 && !ignore)
 1000             break;
 1001         bufp += scanlinesize;
 1002     }
 1003 }
 1004 
 1005 DECLAREreadFunc(readSeparateStripsIntoBuffer)
 1006 {
 1007     tsize_t scanlinesize = TIFFScanlineSize(in);
 1008     unsigned char* scanline = (unsigned char *) _TIFFmalloc(scanlinesize);
 1009 
 1010     (void) imagewidth;
 1011     if (scanline) {
 1012         unsigned char *bufp = buf;
 1013         uint32 row;
 1014         tsample_t s;
 1015 
 1016         for (row = 0; row < imagelength; row++) {
 1017             /* merge channels */
 1018             for (s = 0; s < spp; s++) {
 1019                 unsigned char* sp = scanline;
 1020                 unsigned char* bp = bufp + s;
 1021                 tsize_t n = scanlinesize;
 1022 
 1023                 if (TIFFReadScanline(in, sp, row, s) < 0 && !ignore)
 1024                     goto done;
 1025                 while (n-- > 0)
 1026                     *bp = *bufp++, bp += spp;
 1027             }
 1028             bufp += scanlinesize;
 1029         }
 1030 done:
 1031         _TIFFfree(scanline);
 1032     }
 1033 }
 1034 
 1035 DECLAREreadFunc(readContigTilesIntoBuffer)
 1036 {
 1037     unsigned char* tilebuf = (unsigned char *) _TIFFmalloc(TIFFTileSize(in));
 1038     uint32 imagew = TIFFScanlineSize(in);
 1039     uint32 tilew  = TIFFTileRowSize(in);
 1040     int iskew = imagew - tilew;
 1041     unsigned char *bufp = buf;
 1042     uint32 tw, tl;
 1043     uint32 row;
 1044 
 1045     (void) spp;
 1046     if (tilebuf == 0)
 1047         return;
 1048     (void) TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
 1049     (void) TIFFGetField(in, TIFFTAG_TILELENGTH, &tl);
 1050     for (row = 0; row < imagelength; row += tl) {
 1051         uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
 1052         uint32 colb = 0;
 1053         uint32 col;
 1054 
 1055         for (col = 0; col < imagewidth; col += tw) {
 1056             if (TIFFReadTile(in, tilebuf, col, row, 0, 0) < 0 &&
 1057                 !ignore)
 1058                 goto done;
 1059             if (colb + tilew > imagew) {
 1060                 uint32 width = imagew - colb;
 1061                 uint32 oskew = tilew - width;
 1062                 cpStripToTile(bufp + colb,
 1063                     tilebuf, nrow, width,
 1064                     oskew + iskew, oskew);
 1065             } else
 1066                 cpStripToTile(bufp + colb,
 1067                     tilebuf, nrow, tilew,
 1068                     iskew, 0);
 1069             colb += tilew;
 1070         }
 1071         bufp += imagew * nrow;
 1072     }
 1073 done:
 1074     _TIFFfree(tilebuf);
 1075 }
 1076 
 1077 DECLAREreadFunc(readSeparateTilesIntoBuffer)
 1078 {
 1079     uint32 imagew = TIFFScanlineSize(in);
 1080     uint32 tilew = TIFFTileRowSize(in);
 1081     int iskew  = imagew - tilew;
 1082     unsigned char* tilebuf = (unsigned char *) _TIFFmalloc(TIFFTileSize(in));
 1083     unsigned char *bufp = buf;
 1084     uint32 tw, tl;
 1085     uint32 row;
 1086 
 1087     if (tilebuf == 0)
 1088         return;
 1089     (void) TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
 1090     (void) TIFFGetField(in, TIFFTAG_TILELENGTH, &tl);
 1091     for (row = 0; row < imagelength; row += tl) {
 1092         uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
 1093         uint32 colb = 0;
 1094         uint32 col;
 1095 
 1096         for (col = 0; col < imagewidth; col += tw) {
 1097             tsample_t s;
 1098 
 1099             for (s = 0; s < spp; s++) {
 1100                 if (TIFFReadTile(in, tilebuf, col, row, 0, s) < 0 && !ignore)
 1101                     goto done;
 1102                 /*
 1103                  * Tile is clipped horizontally.  Calculate
 1104                  * visible portion and skewing factors.
 1105                  */
 1106                 if (colb + tilew > imagew) {
 1107                     uint32 width = imagew - colb;
 1108                     int oskew = tilew - width;
 1109                     cpSeparateBufToContigBuf(bufp+colb+s,
 1110                         tilebuf, nrow, width,
 1111                         oskew + iskew, oskew, spp);
 1112                 } else
 1113                     cpSeparateBufToContigBuf(bufp+colb+s,
 1114                         tilebuf, nrow, tw,
 1115                         iskew, 0, spp);
 1116             }
 1117             colb += tilew;
 1118         }
 1119         bufp += imagew * nrow;
 1120     }
 1121 done:
 1122     _TIFFfree(tilebuf);
 1123 }
 1124 
 1125 DECLAREwriteFunc(writeBufferToContigStrips)
 1126 {
 1127     tsize_t scanline = TIFFScanlineSize(out);
 1128     uint32 row;
 1129 
 1130     (void) imagewidth; (void) spp;
 1131     for (row = 0; row < imagelength; row++) {
 1132         if (TIFFWriteScanline(out, buf, row, 0) < 0)
 1133             return (FALSE);
 1134         buf += scanline;
 1135     }
 1136     return (TRUE);
 1137 }
 1138 
 1139 DECLAREwriteFunc(writeBufferToSeparateStrips)
 1140 {
 1141     unsigned char *obuf = (unsigned char *) _TIFFmalloc(TIFFScanlineSize(out));
 1142     tsample_t s;
 1143 
 1144     if (obuf == NULL)
 1145         return (0);
 1146     for (s = 0; s < spp; s++) {
 1147         uint32 row;
 1148         for (row = 0; row < imagelength; row++) {
 1149             unsigned char* inp = buf + s;
 1150             unsigned char* outp = obuf;
 1151             uint32 n = imagewidth;
 1152 
 1153             while (n-- > 0)
 1154                 *outp++ = *inp, inp += spp;
 1155             if (TIFFWriteScanline(out, obuf, row, s) < 0) {
 1156                 _TIFFfree(obuf);
 1157                 return (FALSE);
 1158             }
 1159         }
 1160     }
 1161     _TIFFfree(obuf);
 1162     return (TRUE);
 1163 
 1164 }
 1165 
 1166 DECLAREwriteFunc(writeBufferToContigTiles)
 1167 {
 1168     uint32 imagew = TIFFScanlineSize(out);
 1169     uint32 tilew  = TIFFTileRowSize(out);
 1170     int iskew = imagew - tilew;
 1171     unsigned char* obuf = (unsigned char *) _TIFFmalloc(TIFFTileSize(out));
 1172     unsigned char* bufp = buf;
 1173     uint32 tl, tw;
 1174     uint32 row;
 1175 
 1176     (void) spp;
 1177     if (obuf == NULL)
 1178         return (FALSE);
 1179     (void) TIFFGetField(out, TIFFTAG_TILELENGTH, &tl);
 1180     (void) TIFFGetField(out, TIFFTAG_TILEWIDTH, &tw);
 1181     for (row = 0; row < imagelength; row += tilelength) {
 1182         uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
 1183         uint32 colb = 0;
 1184         uint32 col;
 1185 
 1186         for (col = 0; col < imagewidth; col += tw) {
 1187             /*
 1188              * Tile is clipped horizontally.  Calculate
 1189              * visible portion and skewing factors.
 1190              */
 1191             if (colb + tilew > imagew) {
 1192                 uint32 width = imagew - colb;
 1193                 int oskew = tilew - width;
 1194                 cpStripToTile(obuf, bufp + colb, nrow, width,
 1195                     oskew, oskew + iskew);
 1196             } else
 1197                 cpStripToTile(obuf, bufp + colb, nrow, tilew,
 1198                     0, iskew);
 1199             if (TIFFWriteTile(out, obuf, col, row, 0, 0) < 0) {
 1200                 _TIFFfree(obuf);
 1201                 return (FALSE);
 1202             }
 1203             colb += tilew;
 1204         }
 1205         bufp += nrow * imagew;
 1206     }
 1207     _TIFFfree(obuf);
 1208     return (TRUE);
 1209 }
 1210 
 1211 DECLAREwriteFunc(writeBufferToSeparateTiles)
 1212 {
 1213     uint32 imagew = TIFFScanlineSize(out);
 1214     tsize_t tilew  = TIFFTileRowSize(out);
 1215     int iskew = imagew - tilew;
 1216     unsigned char *obuf = (unsigned char*) _TIFFmalloc(TIFFTileSize(out));
 1217     unsigned char *bufp = buf;
 1218     uint32 tl, tw;
 1219     uint32 row;
 1220 
 1221     if (obuf == NULL)
 1222         return (FALSE);
 1223     (void) TIFFGetField(out, TIFFTAG_TILELENGTH, &tl);
 1224     (void) TIFFGetField(out, TIFFTAG_TILEWIDTH, &tw);
 1225     for (row = 0; row < imagelength; row += tl) {
 1226         uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
 1227         uint32 colb = 0;
 1228         uint32 col;
 1229 
 1230         for (col = 0; col < imagewidth; col += tw) {
 1231             tsample_t s;
 1232             for (s = 0; s < spp; s++) {
 1233                 /*
 1234                  * Tile is clipped horizontally.  Calculate
 1235                  * visible portion and skewing factors.
 1236                  */
 1237                 if (colb + tilew > imagew) {
 1238                     uint32 width = imagew - colb;
 1239                     int oskew = tilew - width;
 1240 
 1241                     cpContigBufToSeparateBuf(obuf,
 1242                         bufp + colb + s,
 1243                         nrow, width,
 1244                         oskew/spp, oskew + imagew, spp);
 1245                 } else
 1246                     cpContigBufToSeparateBuf(obuf,
 1247                         bufp + colb + s,
 1248                         nrow, tilewidth,
 1249                         0, iskew, spp);
 1250                 if (TIFFWriteTile(out, obuf, col, row, 0, s) < 0) {
 1251                     _TIFFfree(obuf);
 1252                     return (FALSE);
 1253                 }
 1254             }
 1255             colb += tilew;
 1256         }
 1257         bufp += nrow * imagew;
 1258     }
 1259     _TIFFfree(obuf);
 1260     return (TRUE);
 1261 }
 1262 
 1263 /*
 1264  * Contig strips -> contig tiles.
 1265  */
 1266 DECLAREcpFunc(cpContigStrips2ContigTiles)
 1267 {
 1268     return cpImage(in, out,
 1269         readContigStripsIntoBuffer,
 1270         writeBufferToContigTiles,
 1271         imagelength, imagewidth, spp);
 1272 }
 1273 
 1274 /*
 1275  * Contig strips -> separate tiles.
 1276  */
 1277 DECLAREcpFunc(cpContigStrips2SeparateTiles)
 1278 {
 1279     return cpImage(in, out,
 1280         readContigStripsIntoBuffer,
 1281         writeBufferToSeparateTiles,
 1282         imagelength, imagewidth, spp);
 1283 }
 1284 
 1285 /*
 1286  * Separate strips -> contig tiles.
 1287  */
 1288 DECLAREcpFunc(cpSeparateStrips2ContigTiles)
 1289 {
 1290     return cpImage(in, out,
 1291         readSeparateStripsIntoBuffer,
 1292         writeBufferToContigTiles,
 1293         imagelength, imagewidth, spp);
 1294 }
 1295 
 1296 /*
 1297  * Separate strips -> separate tiles.
 1298  */
 1299 DECLAREcpFunc(cpSeparateStrips2SeparateTiles)
 1300 {
 1301     return cpImage(in, out,
 1302         readSeparateStripsIntoBuffer,
 1303         writeBufferToSeparateTiles,
 1304         imagelength, imagewidth, spp);
 1305 }
 1306 
 1307 /*
 1308  * Contig strips -> contig tiles.
 1309  */
 1310 DECLAREcpFunc(cpContigTiles2ContigTiles)
 1311 {
 1312     return cpImage(in, out,
 1313         readContigTilesIntoBuffer,
 1314         writeBufferToContigTiles,
 1315         imagelength, imagewidth, spp);
 1316 }
 1317 
 1318 /*
 1319  * Contig tiles -> separate tiles.
 1320  */
 1321 DECLAREcpFunc(cpContigTiles2SeparateTiles)
 1322 {
 1323     return cpImage(in, out,
 1324         readContigTilesIntoBuffer,
 1325         writeBufferToSeparateTiles,
 1326         imagelength, imagewidth, spp);
 1327 }
 1328 
 1329 /*
 1330  * Separate tiles -> contig tiles.
 1331  */
 1332 DECLAREcpFunc(cpSeparateTiles2ContigTiles)
 1333 {
 1334     return cpImage(in, out,
 1335         readSeparateTilesIntoBuffer,
 1336         writeBufferToContigTiles,
 1337         imagelength, imagewidth, spp);
 1338 }
 1339 
 1340 /*
 1341  * Separate tiles -> separate tiles (tile dimension change).
 1342  */
 1343 DECLAREcpFunc(cpSeparateTiles2SeparateTiles)
 1344 {
 1345     return cpImage(in, out,
 1346         readSeparateTilesIntoBuffer,
 1347         writeBufferToSeparateTiles,
 1348         imagelength, imagewidth, spp);
 1349 }
 1350 
 1351 /*
 1352  * Contig tiles -> contig tiles (tile dimension change).
 1353  */
 1354 DECLAREcpFunc(cpContigTiles2ContigStrips)
 1355 {
 1356     return cpImage(in, out,
 1357         readContigTilesIntoBuffer,
 1358         writeBufferToContigStrips,
 1359         imagelength, imagewidth, spp);
 1360 }
 1361 
 1362 /*
 1363  * Contig tiles -> separate strips.
 1364  */
 1365 DECLAREcpFunc(cpContigTiles2SeparateStrips)
 1366 {
 1367     return cpImage(in, out,
 1368         readContigTilesIntoBuffer,
 1369         writeBufferToSeparateStrips,
 1370         imagelength, imagewidth, spp);
 1371 }
 1372 
 1373 /*
 1374  * Separate tiles -> contig strips.
 1375  */
 1376 DECLAREcpFunc(cpSeparateTiles2ContigStrips)
 1377 {
 1378     return cpImage(in, out,
 1379         readSeparateTilesIntoBuffer,
 1380         writeBufferToContigStrips,
 1381         imagelength, imagewidth, spp);
 1382 }
 1383 
 1384 /*
 1385  * Separate tiles -> separate strips.
 1386  */
 1387 DECLAREcpFunc(cpSeparateTiles2SeparateStrips)
 1388 {
 1389     return cpImage(in, out,
 1390         readSeparateTilesIntoBuffer,
 1391         writeBufferToSeparateStrips,
 1392         imagelength, imagewidth, spp);
 1393 }
 1394 
 1395 /*
 1396  * Select the appropriate copy function to use.
 1397  */
 1398 static copyFunc
 1399 pickCopyFunc(TIFF* in, TIFF* out, uint16 bitspersample, uint16 samplesperpixel)
 1400 {
 1401     uint16 shortv;
 1402     uint32 w, l, tw, tl;
 1403     int bychunk;
 1404 
 1405     (void) TIFFGetField(in, TIFFTAG_PLANARCONFIG, &shortv);
 1406     if (shortv != config && bitspersample != 8 && samplesperpixel > 1) {
 1407         fprintf(stderr,
 1408 "%s: Can not handle different planar configuration w/ bits/sample != 8\n",
 1409             TIFFFileName(in));
 1410         return (NULL);
 1411     }
 1412     TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &w);
 1413     TIFFGetField(in, TIFFTAG_IMAGELENGTH, &l);
 1414     if (TIFFIsTiled(out)) {
 1415         if (!TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw))
 1416             tw = w;
 1417         if (!TIFFGetField(in, TIFFTAG_TILELENGTH, &tl))
 1418             tl = l;
 1419         bychunk = (tw == tilewidth && tl == tilelength);
 1420     } else if (TIFFIsTiled(in)) {
 1421         TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
 1422         TIFFGetField(in, TIFFTAG_TILELENGTH, &tl);
 1423         bychunk = (tw == w && tl == rowsperstrip);
 1424     } else {
 1425         uint32 irps = (uint32) -1L;
 1426         TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &irps);
 1427         bychunk = (rowsperstrip == irps);
 1428     }
 1429 #define T 1
 1430 #define F 0
 1431 #define pack(a,b,c,d,e) ((long)(((a)<<11)|((b)<<3)|((c)<<2)|((d)<<1)|(e)))
 1432     switch(pack(shortv,config,TIFFIsTiled(in),TIFFIsTiled(out),bychunk)) {
 1433 /* Strips -> Tiles */
 1434     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,T,F):
 1435     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,T,T):
 1436         return cpContigStrips2ContigTiles;
 1437     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, F,T,F):
 1438     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, F,T,T):
 1439         return cpContigStrips2SeparateTiles;
 1440         case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,T,F):
 1441         case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,T,T):
 1442         return cpSeparateStrips2ContigTiles;
 1443     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,T,F):
 1444     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,T,T):
 1445         return cpSeparateStrips2SeparateTiles;
 1446 /* Tiles -> Tiles */
 1447     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,T,F):
 1448     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,T,T):
 1449         return cpContigTiles2ContigTiles;
 1450     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,T,F):
 1451     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,T,T):
 1452         return cpContigTiles2SeparateTiles;
 1453         case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,T,F):
 1454         case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,T,T):
 1455         return cpSeparateTiles2ContigTiles;
 1456     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,T,F):
 1457     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,T,T):
 1458         return cpSeparateTiles2SeparateTiles;
 1459 /* Tiles -> Strips */
 1460     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,F,F):
 1461     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,F,T):
 1462         return cpContigTiles2ContigStrips;
 1463     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,F,F):
 1464     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,F,T):
 1465         return cpContigTiles2SeparateStrips;
 1466         case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,F,F):
 1467         case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,F,T):
 1468         return cpSeparateTiles2ContigStrips;
 1469     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,F,F):
 1470     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,F,T):
 1471         return cpSeparateTiles2SeparateStrips;
 1472 /* Strips -> Strips */
 1473     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,F,F):
 1474           if( convert_8_to_4 )
 1475               return cpContig2ContigByRow_8_to_4;
 1476           else
 1477               return cpContig2ContigByRow;
 1478           
 1479     case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,F,T):
 1480           if( convert_8_to_4 )
 1481               return cpContig2ContigByRow_8_to_4;
 1482           else
 1483               return cpDecodedStrips;
 1484     case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE,   F,F,F):
 1485     case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE,   F,F,T):
 1486         return cpContig2SeparateByRow;
 1487     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,F,F):
 1488     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,F,T):
 1489         return cpSeparate2ContigByRow;
 1490     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,F,F):
 1491     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,F,T):
 1492         return cpSeparate2SeparateByRow;
 1493     }
 1494 #undef pack
 1495 #undef F
 1496 #undef T
 1497     fprintf(stderr, "tiffcp: %s: Don't know how to copy/convert image.\n",
 1498         TIFFFileName(in));
 1499     return (NULL);
 1500 }