Blame tools/tiffcp.c

Packit 7838c8
/* $Id: tiffcp.c,v 1.61 2017-01-11 19:26:14 erouault Exp $ */
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Copyright (c) 1988-1997 Sam Leffler
Packit 7838c8
 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
Packit 7838c8
 *
Packit 7838c8
 *  Revised:  2/18/01 BAR -- added syntax for extracting single images from
Packit 7838c8
 *                          multi-image TIFF files.
Packit 7838c8
 *
Packit 7838c8
 *    New syntax is:  sourceFileName,image#
Packit 7838c8
 *
Packit 7838c8
 * image# ranges from 0..<n-1> where n is the # of images in the file.
Packit 7838c8
 * There may be no white space between the comma and the filename or
Packit 7838c8
 * image number.
Packit 7838c8
 *
Packit 7838c8
 *    Example:   tiffcp source.tif,1 destination.tif
Packit 7838c8
 *
Packit 7838c8
 * Copies the 2nd image in source.tif to the destination.
Packit 7838c8
 *
Packit 7838c8
 *****
Packit 7838c8
 * Permission to use, copy, modify, distribute, and sell this software and 
Packit 7838c8
 * its documentation for any purpose is hereby granted without fee, provided
Packit 7838c8
 * that (i) the above copyright notices and this permission notice appear in
Packit 7838c8
 * all copies of the software and related documentation, and (ii) the names of
Packit 7838c8
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
Packit 7838c8
 * publicity relating to the software without the specific, prior written
Packit 7838c8
 * permission of Sam Leffler and Silicon Graphics.
Packit 7838c8
 * 
Packit 7838c8
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
Packit 7838c8
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
Packit 7838c8
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
Packit 7838c8
 * 
Packit 7838c8
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
Packit 7838c8
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
Packit 7838c8
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
Packit 7838c8
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
Packit 7838c8
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
Packit 7838c8
 * OF THIS SOFTWARE.
Packit 7838c8
 */
Packit 7838c8
Packit 7838c8
#include "tif_config.h"
Packit 7838c8
Packit 7838c8
#include <stdio.h>
Packit 7838c8
#include <stdlib.h>
Packit 7838c8
#include <string.h>
Packit 7838c8
Packit 7838c8
#include <ctype.h>
Packit 7838c8
Packit 7838c8
#ifdef HAVE_UNISTD_H
Packit 7838c8
# include <unistd.h>
Packit 7838c8
#endif
Packit 7838c8
Packit 7838c8
#include "tiffio.h"
Packit 7838c8
Packit 7838c8
#ifndef HAVE_GETOPT
Packit 7838c8
extern int getopt(int, char**, char*);
Packit 7838c8
#endif
Packit 7838c8
Packit 7838c8
#if defined(VMS)
Packit 7838c8
# define unlink delete
Packit 7838c8
#endif
Packit 7838c8
Packit 7838c8
#define	streq(a,b)	(strcmp(a,b) == 0)
Packit 7838c8
#define	strneq(a,b,n)	(strncmp(a,b,n) == 0)
Packit 7838c8
Packit 7838c8
#define	TRUE	1
Packit 7838c8
#define	FALSE	0
Packit 7838c8
Packit 7838c8
static int outtiled = -1;
Packit 7838c8
static uint32 tilewidth;
Packit 7838c8
static uint32 tilelength;
Packit 7838c8
Packit 7838c8
static uint16 config;
Packit 7838c8
static uint16 compression;
Packit 7838c8
static uint16 predictor;
Packit 7838c8
static int preset;
Packit 7838c8
static uint16 fillorder;
Packit 7838c8
static uint16 orientation;
Packit 7838c8
static uint32 rowsperstrip;
Packit 7838c8
static uint32 g3opts;
Packit 7838c8
static int ignore = FALSE;		/* if true, ignore read errors */
Packit 7838c8
static uint32 defg3opts = (uint32) -1;
Packit 7838c8
static int quality = 75;		/* JPEG quality */
Packit 7838c8
static int jpegcolormode = JPEGCOLORMODE_RGB;
Packit 7838c8
static uint16 defcompression = (uint16) -1;
Packit 7838c8
static uint16 defpredictor = (uint16) -1;
Packit 7838c8
static int defpreset =  -1;
Packit 7838c8
Packit 7838c8
static int tiffcp(TIFF*, TIFF*);
Packit 7838c8
static int processCompressOptions(char*);
Packit 7838c8
static void usage(void);
Packit 7838c8
Packit 7838c8
static char comma = ',';  /* (default) comma separator character */
Packit 7838c8
static TIFF* bias = NULL;
Packit 7838c8
static int pageNum = 0;
Packit 7838c8
static int pageInSeq = 0;
Packit 7838c8
Packit 7838c8
static int nextSrcImage (TIFF *tif, char **imageSpec)
Packit 7838c8
/*
Packit 7838c8
  seek to the next image specified in *imageSpec
Packit 7838c8
  returns 1 if success, 0 if no more images to process
Packit 7838c8
  *imageSpec=NULL if subsequent images should be processed in sequence
Packit 7838c8
*/
Packit 7838c8
{
Packit 7838c8
	if (**imageSpec == comma) {  /* if not @comma, we've done all images */
Packit 7838c8
		char *start = *imageSpec + 1;
Packit 7838c8
		tdir_t nextImage = (tdir_t)strtol(start, imageSpec, 0);
Packit 7838c8
		if (start == *imageSpec) nextImage = TIFFCurrentDirectory (tif);
Packit 7838c8
		if (**imageSpec)
Packit 7838c8
		{
Packit 7838c8
			if (**imageSpec == comma) {
Packit 7838c8
				/* a trailing comma denotes remaining images in sequence */
Packit 7838c8
				if ((*imageSpec)[1] == '\0') *imageSpec = NULL;
Packit 7838c8
			}else{
Packit 7838c8
				fprintf (stderr,
Packit 7838c8
				    "Expected a %c separated image # list after %s\n",
Packit 7838c8
				    comma, TIFFFileName (tif));
Packit 7838c8
				exit (-4);   /* syntax error */
Packit 7838c8
			}
Packit 7838c8
		}
Packit 7838c8
		if (TIFFSetDirectory (tif, nextImage)) return 1;
Packit 7838c8
		fprintf (stderr, "%s%c%d not found!\n",
Packit 7838c8
		    TIFFFileName(tif), comma, (int) nextImage);
Packit 7838c8
	}
Packit 7838c8
	return 0;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
  
Packit 7838c8
static TIFF* openSrcImage (char **imageSpec)
Packit 7838c8
/*
Packit 7838c8
  imageSpec points to a pointer to a filename followed by optional ,image#'s
Packit 7838c8
  Open the TIFF file and assign *imageSpec to either NULL if there are
Packit 7838c8
  no images specified, or a pointer to the next image number text
Packit 7838c8
*/
Packit 7838c8
{
Packit 7838c8
	TIFF *tif;
Packit 7838c8
	char *fn = *imageSpec;
Packit 7838c8
	*imageSpec = strchr (fn, comma);
Packit 7838c8
	if (*imageSpec) {  /* there is at least one image number specifier */
Packit 7838c8
		**imageSpec = '\0';
Packit 7838c8
		tif = TIFFOpen (fn, "r");
Packit 7838c8
		/* but, ignore any single trailing comma */
Packit 7838c8
		if (!(*imageSpec)[1]) {*imageSpec = NULL; return tif;}
Packit 7838c8
		if (tif) {
Packit 7838c8
			**imageSpec = comma;  /* replace the comma */
Packit 7838c8
			if (!nextSrcImage(tif, imageSpec)) {
Packit 7838c8
				TIFFClose (tif);
Packit 7838c8
				tif = NULL;
Packit 7838c8
			}
Packit 7838c8
		}
Packit 7838c8
	}else
Packit 7838c8
		tif = TIFFOpen (fn, "r");
Packit 7838c8
	return tif;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
int
Packit 7838c8
main(int argc, char* argv[])
Packit 7838c8
{
Packit 7838c8
	uint16 defconfig = (uint16) -1;
Packit 7838c8
	uint16 deffillorder = 0;
Packit 7838c8
	uint32 deftilewidth = (uint32) -1;
Packit 7838c8
	uint32 deftilelength = (uint32) -1;
Packit 7838c8
	uint32 defrowsperstrip = (uint32) 0;
Packit 7838c8
	uint64 diroff = 0;
Packit 7838c8
	TIFF* in;
Packit 7838c8
	TIFF* out;
Packit 7838c8
	char mode[10];
Packit 7838c8
	char* mp = mode;
Packit 7838c8
	int c;
Packit 7838c8
#if !HAVE_DECL_OPTARG
Packit 7838c8
	extern int optind;
Packit 7838c8
	extern char* optarg;
Packit 7838c8
#endif
Packit 7838c8
Packit 7838c8
	*mp++ = 'w';
Packit 7838c8
	*mp = '\0';
Packit 7838c8
	while ((c = getopt(argc, argv, ",:b:c:f:l:o:p:r:w:aistBLMC8x")) != -1)
Packit 7838c8
		switch (c) {
Packit 7838c8
		case ',':
Packit 7838c8
			if (optarg[0] != '=') usage();
Packit 7838c8
			comma = optarg[1];
Packit 7838c8
			break;
Packit 7838c8
		case 'b':   /* this file is bias image subtracted from others */
Packit 7838c8
			if (bias) {
Packit 7838c8
				fputs ("Only 1 bias image may be specified\n", stderr);
Packit 7838c8
				exit (-2);
Packit 7838c8
			}
Packit 7838c8
			{
Packit 7838c8
				uint16 samples = (uint16) -1;
Packit 7838c8
				char **biasFn = &optarg;
Packit 7838c8
				bias = openSrcImage (biasFn);
Packit 7838c8
				if (!bias) exit (-5);
Packit 7838c8
				if (TIFFIsTiled (bias)) {
Packit 7838c8
					fputs ("Bias image must be organized in strips\n", stderr);
Packit 7838c8
					exit (-7);
Packit 7838c8
				}
Packit 7838c8
				TIFFGetField(bias, TIFFTAG_SAMPLESPERPIXEL, &samples);
Packit 7838c8
				if (samples != 1) {
Packit 7838c8
					fputs ("Bias image must be monochrome\n", stderr);
Packit 7838c8
					exit (-7);
Packit 7838c8
				}
Packit 7838c8
			}
Packit 7838c8
			break;
Packit 7838c8
		case 'a':   /* append to output */
Packit 7838c8
			mode[0] = 'a';
Packit 7838c8
			break;
Packit 7838c8
		case 'c':   /* compression scheme */
Packit 7838c8
			if (!processCompressOptions(optarg))
Packit 7838c8
				usage();
Packit 7838c8
			break;
Packit 7838c8
		case 'f':   /* fill order */
Packit 7838c8
			if (streq(optarg, "lsb2msb"))
Packit 7838c8
				deffillorder = FILLORDER_LSB2MSB;
Packit 7838c8
			else if (streq(optarg, "msb2lsb"))
Packit 7838c8
				deffillorder = FILLORDER_MSB2LSB;
Packit 7838c8
			else
Packit 7838c8
				usage();
Packit 7838c8
			break;
Packit 7838c8
		case 'i':   /* ignore errors */
Packit 7838c8
			ignore = TRUE;
Packit 7838c8
			break;
Packit 7838c8
		case 'l':   /* tile length */
Packit 7838c8
			outtiled = TRUE;
Packit 7838c8
			deftilelength = atoi(optarg);
Packit 7838c8
			break;
Packit 7838c8
		case 'o':   /* initial directory offset */
Packit 7838c8
			diroff = strtoul(optarg, NULL, 0);
Packit 7838c8
			break;
Packit 7838c8
		case 'p':   /* planar configuration */
Packit 7838c8
			if (streq(optarg, "separate"))
Packit 7838c8
				defconfig = PLANARCONFIG_SEPARATE;
Packit 7838c8
			else if (streq(optarg, "contig"))
Packit 7838c8
				defconfig = PLANARCONFIG_CONTIG;
Packit 7838c8
			else
Packit 7838c8
				usage();
Packit 7838c8
			break;
Packit 7838c8
		case 'r':   /* rows/strip */
Packit 7838c8
			defrowsperstrip = atol(optarg);
Packit 7838c8
			break;
Packit 7838c8
		case 's':   /* generate stripped output */
Packit 7838c8
			outtiled = FALSE;
Packit 7838c8
			break;
Packit 7838c8
		case 't':   /* generate tiled output */
Packit 7838c8
			outtiled = TRUE;
Packit 7838c8
			break;
Packit 7838c8
		case 'w':   /* tile width */
Packit 7838c8
			outtiled = TRUE;
Packit 7838c8
			deftilewidth = atoi(optarg);
Packit 7838c8
			break;
Packit 7838c8
		case 'B':
Packit 7838c8
			*mp++ = 'b'; *mp = '\0';
Packit 7838c8
			break;
Packit 7838c8
		case 'L':
Packit 7838c8
			*mp++ = 'l'; *mp = '\0';
Packit 7838c8
			break;
Packit 7838c8
		case 'M':
Packit 7838c8
			*mp++ = 'm'; *mp = '\0';
Packit 7838c8
			break;
Packit 7838c8
		case 'C':
Packit 7838c8
			*mp++ = 'c'; *mp = '\0';
Packit 7838c8
			break;
Packit 7838c8
		case '8':
Packit 7838c8
			*mp++ = '8'; *mp = '\0';
Packit 7838c8
			break;
Packit 7838c8
		case 'x':
Packit 7838c8
			pageInSeq = 1;
Packit 7838c8
			break;
Packit 7838c8
		case '?':
Packit 7838c8
			usage();
Packit 7838c8
			/*NOTREACHED*/
Packit 7838c8
		}
Packit 7838c8
	if (argc - optind < 2)
Packit 7838c8
		usage();
Packit 7838c8
	out = TIFFOpen(argv[argc-1], mode);
Packit 7838c8
	if (out == NULL)
Packit 7838c8
		return (-2);
Packit 7838c8
	if ((argc - optind) == 2)
Packit 7838c8
		pageNum = -1;
Packit 7838c8
	for (; optind < argc-1 ; optind++) {
Packit 7838c8
		char *imageCursor = argv[optind];
Packit 7838c8
		in = openSrcImage (&imageCursor);
Packit 7838c8
		if (in == NULL) {
Packit 7838c8
			(void) TIFFClose(out);
Packit 7838c8
			return (-3);
Packit 7838c8
		}
Packit 7838c8
		if (diroff != 0 && !TIFFSetSubDirectory(in, diroff)) {
Packit 7838c8
			TIFFError(TIFFFileName(in),
Packit 7838c8
			    "Error, setting subdirectory at " TIFF_UINT64_FORMAT, diroff);
Packit 7838c8
			(void) TIFFClose(in);
Packit 7838c8
			(void) TIFFClose(out);
Packit 7838c8
			return (1);
Packit 7838c8
		}
Packit 7838c8
		for (;;) {
Packit 7838c8
			config = defconfig;
Packit 7838c8
			compression = defcompression;
Packit 7838c8
			predictor = defpredictor;
Packit 7838c8
                        preset = defpreset;
Packit 7838c8
			fillorder = deffillorder;
Packit 7838c8
			rowsperstrip = defrowsperstrip;
Packit 7838c8
			tilewidth = deftilewidth;
Packit 7838c8
			tilelength = deftilelength;
Packit 7838c8
			g3opts = defg3opts;
Packit 7838c8
			if (!tiffcp(in, out) || !TIFFWriteDirectory(out)) {
Packit 7838c8
				(void) TIFFClose(in);
Packit 7838c8
				(void) TIFFClose(out);
Packit 7838c8
				return (1);
Packit 7838c8
			}
Packit 7838c8
			if (imageCursor) { /* seek next image directory */
Packit 7838c8
				if (!nextSrcImage(in, &imageCursor)) break;
Packit 7838c8
			}else
Packit 7838c8
				if (!TIFFReadDirectory(in)) break;
Packit 7838c8
		}
Packit 7838c8
		(void) TIFFClose(in);
Packit 7838c8
	}
Packit 7838c8
Packit 7838c8
	(void) TIFFClose(out);
Packit 7838c8
	return (0);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
static void
Packit 7838c8
processZIPOptions(char* cp)
Packit 7838c8
{
Packit 7838c8
	if ( (cp = strchr(cp, ':')) ) {
Packit 7838c8
		do {
Packit 7838c8
			cp++;
Packit 7838c8
			if (isdigit((int)*cp))
Packit 7838c8
				defpredictor = atoi(cp);
Packit 7838c8
			else if (*cp == 'p')
Packit 7838c8
				defpreset = atoi(++cp);
Packit 7838c8
			else
Packit 7838c8
				usage();
Packit 7838c8
		} while( (cp = strchr(cp, ':')) );
Packit 7838c8
	}
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
static void
Packit 7838c8
processG3Options(char* cp)
Packit 7838c8
{
Packit 7838c8
	if( (cp = strchr(cp, ':')) ) {
Packit 7838c8
		if (defg3opts == (uint32) -1)
Packit 7838c8
			defg3opts = 0;
Packit 7838c8
		do {
Packit 7838c8
			cp++;
Packit 7838c8
			if (strneq(cp, "1d", 2))
Packit 7838c8
				defg3opts &= ~GROUP3OPT_2DENCODING;
Packit 7838c8
			else if (strneq(cp, "2d", 2))
Packit 7838c8
				defg3opts |= GROUP3OPT_2DENCODING;
Packit 7838c8
			else if (strneq(cp, "fill", 4))
Packit 7838c8
				defg3opts |= GROUP3OPT_FILLBITS;
Packit 7838c8
			else
Packit 7838c8
				usage();
Packit 7838c8
		} while( (cp = strchr(cp, ':')) );
Packit 7838c8
	}
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
static int
Packit 7838c8
processCompressOptions(char* opt)
Packit 7838c8
{
Packit 7838c8
	if (streq(opt, "none")) {
Packit 7838c8
		defcompression = COMPRESSION_NONE;
Packit 7838c8
	} else if (streq(opt, "packbits")) {
Packit 7838c8
		defcompression = COMPRESSION_PACKBITS;
Packit 7838c8
	} else if (strneq(opt, "jpeg", 4)) {
Packit 7838c8
		char* cp = strchr(opt, ':');
Packit 7838c8
Packit 7838c8
		defcompression = COMPRESSION_JPEG;
Packit 7838c8
		while( cp )
Packit 7838c8
		{
Packit 7838c8
			if (isdigit((int)cp[1]))
Packit 7838c8
				quality = atoi(cp+1);
Packit 7838c8
			else if (cp[1] == 'r' )
Packit 7838c8
				jpegcolormode = JPEGCOLORMODE_RAW;
Packit 7838c8
			else
Packit 7838c8
				usage();
Packit 7838c8
Packit 7838c8
			cp = strchr(cp+1,':');
Packit 7838c8
		}
Packit 7838c8
	} else if (strneq(opt, "g3", 2)) {
Packit 7838c8
		processG3Options(opt);
Packit 7838c8
		defcompression = COMPRESSION_CCITTFAX3;
Packit 7838c8
	} else if (streq(opt, "g4")) {
Packit 7838c8
		defcompression = COMPRESSION_CCITTFAX4;
Packit 7838c8
	} else if (strneq(opt, "lzw", 3)) {
Packit 7838c8
		char* cp = strchr(opt, ':');
Packit 7838c8
		if (cp)
Packit 7838c8
			defpredictor = atoi(cp+1);
Packit 7838c8
		defcompression = COMPRESSION_LZW;
Packit 7838c8
	} else if (strneq(opt, "zip", 3)) {
Packit 7838c8
		processZIPOptions(opt);
Packit 7838c8
		defcompression = COMPRESSION_ADOBE_DEFLATE;
Packit 7838c8
	} else if (strneq(opt, "lzma", 4)) {
Packit 7838c8
		processZIPOptions(opt);
Packit 7838c8
		defcompression = COMPRESSION_LZMA;
Packit 7838c8
	} else if (strneq(opt, "jbig", 4)) {
Packit 7838c8
		defcompression = COMPRESSION_JBIG;
Packit 7838c8
	} else if (strneq(opt, "sgilog", 6)) {
Packit 7838c8
		defcompression = COMPRESSION_SGILOG;
Packit 7838c8
	} else
Packit 7838c8
		return (0);
Packit 7838c8
	return (1);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
char* stuff[] = {
Packit 7838c8
"usage: tiffcp [options] input... output",
Packit 7838c8
"where options are:",
Packit 7838c8
" -a              append to output instead of overwriting",
Packit 7838c8
" -o offset       set initial directory offset",
Packit 7838c8
" -p contig       pack samples contiguously (e.g. RGBRGB...)",
Packit 7838c8
" -p separate     store samples separately (e.g. RRR...GGG...BBB...)",
Packit 7838c8
" -s              write output in strips",
Packit 7838c8
" -t              write output in tiles",
Packit 7838c8
" -x              force the merged tiff pages in sequence",
Packit 7838c8
" -8              write BigTIFF instead of default ClassicTIFF",
Packit 7838c8
" -B              write big-endian instead of native byte order",
Packit 7838c8
" -L              write little-endian instead of native byte order",
Packit 7838c8
" -M              disable use of memory-mapped files",
Packit 7838c8
" -C              disable strip chopping",
Packit 7838c8
" -i              ignore read errors",
Packit 7838c8
" -b file[,#]     bias (dark) monochrome image to be subtracted from all others",
Packit 7838c8
" -,=%            use % rather than , to separate image #'s (per Note below)",
Packit 7838c8
"",
Packit 7838c8
" -r #            make each strip have no more than # rows",
Packit 7838c8
" -w #            set output tile width (pixels)",
Packit 7838c8
" -l #            set output tile length (pixels)",
Packit 7838c8
"",
Packit 7838c8
" -f lsb2msb      force lsb-to-msb FillOrder for output",
Packit 7838c8
" -f msb2lsb      force msb-to-lsb FillOrder for output",
Packit 7838c8
"",
Packit 7838c8
" -c lzw[:opts]   compress output with Lempel-Ziv & Welch encoding",
Packit 7838c8
" -c zip[:opts]   compress output with deflate encoding",
Packit 7838c8
" -c lzma[:opts]  compress output with LZMA2 encoding",
Packit 7838c8
" -c jpeg[:opts]  compress output with JPEG encoding",
Packit 7838c8
" -c jbig         compress output with ISO JBIG encoding",
Packit 7838c8
" -c packbits     compress output with packbits encoding",
Packit 7838c8
" -c g3[:opts]    compress output with CCITT Group 3 encoding",
Packit 7838c8
" -c g4           compress output with CCITT Group 4 encoding",
Packit 7838c8
" -c sgilog       compress output with SGILOG encoding",
Packit 7838c8
" -c none         use no compression algorithm on output",
Packit 7838c8
"",
Packit 7838c8
"Group 3 options:",
Packit 7838c8
" 1d              use default CCITT Group 3 1D-encoding",
Packit 7838c8
" 2d              use optional CCITT Group 3 2D-encoding",
Packit 7838c8
" fill            byte-align EOL codes",
Packit 7838c8
"For example, -c g3:2d:fill to get G3-2D-encoded data with byte-aligned EOLs",
Packit 7838c8
"",
Packit 7838c8
"JPEG options:",
Packit 7838c8
" #               set compression quality level (0-100, default 75)",
Packit 7838c8
" r               output color image as RGB rather than YCbCr",
Packit 7838c8
"For example, -c jpeg:r:50 to get JPEG-encoded RGB data with 50% comp. quality",
Packit 7838c8
"",
Packit 7838c8
"LZW, Deflate (ZIP) and LZMA2 options:",
Packit 7838c8
" #               set predictor value",
Packit 7838c8
" p#              set compression level (preset)",
Packit 7838c8
"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing,",
Packit 7838c8
"-c zip:3:p9 for Deflate encoding with maximum compression level and floating",
Packit 7838c8
"point predictor.",
Packit 7838c8
"",
Packit 7838c8
"Note that input filenames may be of the form filename,x,y,z",
Packit 7838c8
"where x, y, and z specify image numbers in the filename to copy.",
Packit 7838c8
"example:  tiffcp -c none -b esp.tif,1 esp.tif,0 test.tif",
Packit 7838c8
"  subtract 2nd image in esp.tif from 1st yielding uncompressed result test.tif",
Packit 7838c8
NULL
Packit 7838c8
};
Packit 7838c8
Packit 7838c8
static void
Packit 7838c8
usage(void)
Packit 7838c8
{
Packit 7838c8
	char buf[BUFSIZ];
Packit 7838c8
	int i;
Packit 7838c8
Packit 7838c8
	setbuf(stderr, buf);
Packit 7838c8
	fprintf(stderr, "%s\n\n", TIFFGetVersion());
Packit 7838c8
	for (i = 0; stuff[i] != NULL; i++)
Packit 7838c8
		fprintf(stderr, "%s\n", stuff[i]);
Packit 7838c8
	exit(-1);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
#define	CopyField(tag, v) \
Packit 7838c8
    if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
Packit 7838c8
#define	CopyField2(tag, v1, v2) \
Packit 7838c8
    if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
Packit 7838c8
#define	CopyField3(tag, v1, v2, v3) \
Packit 7838c8
    if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
Packit 7838c8
#define	CopyField4(tag, v1, v2, v3, v4) \
Packit 7838c8
    if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4)
Packit 7838c8
Packit 7838c8
static void
Packit 7838c8
cpTag(TIFF* in, TIFF* out, uint16 tag, uint16 count, TIFFDataType type)
Packit 7838c8
{
Packit 7838c8
	switch (type) {
Packit 7838c8
	case TIFF_SHORT:
Packit 7838c8
		if (count == 1) {
Packit 7838c8
			uint16 shortv;
Packit 7838c8
			CopyField(tag, shortv);
Packit 7838c8
		} else if (count == 2) {
Packit 7838c8
			uint16 shortv1, shortv2;
Packit 7838c8
			CopyField2(tag, shortv1, shortv2);
Packit 7838c8
		} else if (count == 4) {
Packit 7838c8
			uint16 *tr, *tg, *tb, *ta;
Packit 7838c8
			CopyField4(tag, tr, tg, tb, ta);
Packit 7838c8
		} else if (count == (uint16) -1) {
Packit 7838c8
			uint16 shortv1;
Packit 7838c8
			uint16* shortav;
Packit 7838c8
			CopyField2(tag, shortv1, shortav);
Packit 7838c8
		}
Packit 7838c8
		break;
Packit 7838c8
	case TIFF_LONG:
Packit 7838c8
		{ uint32 longv;
Packit 7838c8
		  CopyField(tag, longv);
Packit 7838c8
		}
Packit 7838c8
		break;
Packit 7838c8
	case TIFF_RATIONAL:
Packit 7838c8
		if (count == 1) {
Packit 7838c8
			float floatv;
Packit 7838c8
			CopyField(tag, floatv);
Packit 7838c8
		} else if (count == (uint16) -1) {
Packit 7838c8
			float* floatav;
Packit 7838c8
			CopyField(tag, floatav);
Packit 7838c8
		}
Packit 7838c8
		break;
Packit 7838c8
	case TIFF_ASCII:
Packit 7838c8
		{ char* stringv;
Packit 7838c8
		  CopyField(tag, stringv);
Packit 7838c8
		}
Packit 7838c8
		break;
Packit 7838c8
	case TIFF_DOUBLE:
Packit 7838c8
		if (count == 1) {
Packit 7838c8
			double doublev;
Packit 7838c8
			CopyField(tag, doublev);
Packit 7838c8
		} else if (count == (uint16) -1) {
Packit 7838c8
			double* doubleav;
Packit 7838c8
			CopyField(tag, doubleav);
Packit 7838c8
		}
Packit 7838c8
		break;
Packit 7838c8
	default:
Packit 7838c8
		TIFFError(TIFFFileName(in),
Packit 7838c8
		    "Data type %d is not supported, tag %d skipped.",
Packit 7838c8
		    tag, type);
Packit 7838c8
	}
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
static struct cpTag {
Packit 7838c8
	uint16 tag;
Packit 7838c8
	uint16 count;
Packit 7838c8
	TIFFDataType type;
Packit 7838c8
} tags[] = {
Packit 7838c8
	{ TIFFTAG_SUBFILETYPE,		1, TIFF_LONG },
Packit 7838c8
	{ TIFFTAG_THRESHHOLDING,	1, TIFF_SHORT },
Packit 7838c8
	{ TIFFTAG_DOCUMENTNAME,		1, TIFF_ASCII },
Packit 7838c8
	{ TIFFTAG_IMAGEDESCRIPTION,	1, TIFF_ASCII },
Packit 7838c8
	{ TIFFTAG_MAKE,			1, TIFF_ASCII },
Packit 7838c8
	{ TIFFTAG_MODEL,		1, TIFF_ASCII },
Packit 7838c8
	{ TIFFTAG_MINSAMPLEVALUE,	1, TIFF_SHORT },
Packit 7838c8
	{ TIFFTAG_MAXSAMPLEVALUE,	1, TIFF_SHORT },
Packit 7838c8
	{ TIFFTAG_XRESOLUTION,		1, TIFF_RATIONAL },
Packit 7838c8
	{ TIFFTAG_YRESOLUTION,		1, TIFF_RATIONAL },
Packit 7838c8
	{ TIFFTAG_PAGENAME,		1, TIFF_ASCII },
Packit 7838c8
	{ TIFFTAG_XPOSITION,		1, TIFF_RATIONAL },
Packit 7838c8
	{ TIFFTAG_YPOSITION,		1, TIFF_RATIONAL },
Packit 7838c8
	{ TIFFTAG_RESOLUTIONUNIT,	1, TIFF_SHORT },
Packit 7838c8
	{ TIFFTAG_SOFTWARE,		1, TIFF_ASCII },
Packit 7838c8
	{ TIFFTAG_DATETIME,		1, TIFF_ASCII },
Packit 7838c8
	{ TIFFTAG_ARTIST,		1, TIFF_ASCII },
Packit 7838c8
	{ TIFFTAG_HOSTCOMPUTER,		1, TIFF_ASCII },
Packit 7838c8
	{ TIFFTAG_WHITEPOINT,		(uint16) -1, TIFF_RATIONAL },
Packit 7838c8
	{ TIFFTAG_PRIMARYCHROMATICITIES,(uint16) -1,TIFF_RATIONAL },
Packit 7838c8
	{ TIFFTAG_HALFTONEHINTS,	2, TIFF_SHORT },
Packit 7838c8
	{ TIFFTAG_INKSET,		1, TIFF_SHORT },
Packit 7838c8
	{ TIFFTAG_DOTRANGE,		2, TIFF_SHORT },
Packit 7838c8
	{ TIFFTAG_TARGETPRINTER,	1, TIFF_ASCII },
Packit 7838c8
	{ TIFFTAG_SAMPLEFORMAT,		1, TIFF_SHORT },
Packit 7838c8
	{ TIFFTAG_YCBCRCOEFFICIENTS,	(uint16) -1,TIFF_RATIONAL },
Packit 7838c8
	{ TIFFTAG_YCBCRSUBSAMPLING,	2, TIFF_SHORT },
Packit 7838c8
	{ TIFFTAG_YCBCRPOSITIONING,	1, TIFF_SHORT },
Packit 7838c8
	{ TIFFTAG_REFERENCEBLACKWHITE,	(uint16) -1,TIFF_RATIONAL },
Packit 7838c8
	{ TIFFTAG_EXTRASAMPLES,		(uint16) -1, TIFF_SHORT },
Packit 7838c8
	{ TIFFTAG_SMINSAMPLEVALUE,	1, TIFF_DOUBLE },
Packit 7838c8
	{ TIFFTAG_SMAXSAMPLEVALUE,	1, TIFF_DOUBLE },
Packit 7838c8
	{ TIFFTAG_STONITS,		1, TIFF_DOUBLE },
Packit 7838c8
};
Packit 7838c8
#define	NTAGS	(sizeof (tags) / sizeof (tags[0]))
Packit 7838c8
Packit 7838c8
#define	CopyTag(tag, count, type)	cpTag(in, out, tag, count, type)
Packit 7838c8
Packit 7838c8
typedef int (*copyFunc)
Packit 7838c8
    (TIFF* in, TIFF* out, uint32 l, uint32 w, uint16 samplesperpixel);
Packit 7838c8
static	copyFunc pickCopyFunc(TIFF*, TIFF*, uint16, uint16);
Packit 7838c8
Packit 7838c8
/* PODD */
Packit 7838c8
Packit 7838c8
static int
Packit 7838c8
tiffcp(TIFF* in, TIFF* out)
Packit 7838c8
{
Packit 7838c8
	uint16 bitspersample = 1, samplesperpixel = 1;
Packit 7838c8
	uint16 input_compression, input_photometric = PHOTOMETRIC_MINISBLACK;
Packit 7838c8
	copyFunc cf;
Packit 7838c8
	uint32 width, length;
Packit 7838c8
	struct cpTag* p;
Packit 7838c8
Packit 7838c8
	CopyField(TIFFTAG_IMAGEWIDTH, width);
Packit 7838c8
	CopyField(TIFFTAG_IMAGELENGTH, length);
Packit 7838c8
	CopyField(TIFFTAG_BITSPERSAMPLE, bitspersample);
Packit 7838c8
	CopyField(TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
Packit 7838c8
	if (compression != (uint16)-1)
Packit 7838c8
		TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
Packit 7838c8
	else
Packit 7838c8
		CopyField(TIFFTAG_COMPRESSION, compression);
Packit 7838c8
	TIFFGetFieldDefaulted(in, TIFFTAG_COMPRESSION, &input_compression);
Packit 7838c8
	TIFFGetFieldDefaulted(in, TIFFTAG_PHOTOMETRIC, &input_photometric);
Packit 7838c8
	if (input_compression == COMPRESSION_JPEG) {
Packit 7838c8
		/* Force conversion to RGB */
Packit 7838c8
		TIFFSetField(in, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
Packit 7838c8
	} else if (input_photometric == PHOTOMETRIC_YCBCR) {
Packit 7838c8
		/* Otherwise, can't handle subsampled input */
Packit 7838c8
		uint16 subsamplinghor,subsamplingver;
Packit 7838c8
Packit 7838c8
		TIFFGetFieldDefaulted(in, TIFFTAG_YCBCRSUBSAMPLING,
Packit 7838c8
				      &subsamplinghor, &subsamplingver);
Packit 7838c8
		if (subsamplinghor!=1 || subsamplingver!=1) {
Packit 7838c8
			fprintf(stderr, "tiffcp: %s: Can't copy/convert subsampled image.\n",
Packit 7838c8
				TIFFFileName(in));
Packit 7838c8
			return FALSE;
Packit 7838c8
		}
Packit 7838c8
	}
Packit 7838c8
	if (compression == COMPRESSION_JPEG) {
Packit 7838c8
		if (input_photometric == PHOTOMETRIC_RGB &&
Packit 7838c8
		    jpegcolormode == JPEGCOLORMODE_RGB)
Packit 7838c8
		  TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
Packit 7838c8
		else
Packit 7838c8
		  TIFFSetField(out, TIFFTAG_PHOTOMETRIC, input_photometric);
Packit 7838c8
	}
Packit 7838c8
	else if (compression == COMPRESSION_SGILOG
Packit 7838c8
	    || compression == COMPRESSION_SGILOG24)
Packit 7838c8
		TIFFSetField(out, TIFFTAG_PHOTOMETRIC,
Packit 7838c8
		    samplesperpixel == 1 ?
Packit 7838c8
		    PHOTOMETRIC_LOGL : PHOTOMETRIC_LOGLUV);
Packit 7838c8
	else if (input_compression == COMPRESSION_JPEG &&
Packit 7838c8
			 samplesperpixel == 3 ) {
Packit 7838c8
		/* RGB conversion was forced above
Packit 7838c8
		hence the output will be of the same type */
Packit 7838c8
		TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
Packit 7838c8
	}
Packit 7838c8
	else
Packit 7838c8
		CopyTag(TIFFTAG_PHOTOMETRIC, 1, TIFF_SHORT);
Packit 7838c8
	if (fillorder != 0)
Packit 7838c8
		TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
Packit 7838c8
	else
Packit 7838c8
		CopyTag(TIFFTAG_FILLORDER, 1, TIFF_SHORT);
Packit 7838c8
	/*
Packit 7838c8
	 * Will copy `Orientation' tag from input image
Packit 7838c8
	 */
Packit 7838c8
	TIFFGetFieldDefaulted(in, TIFFTAG_ORIENTATION, &orientation);
Packit 7838c8
	switch (orientation) {
Packit 7838c8
		case ORIENTATION_BOTRIGHT:
Packit 7838c8
		case ORIENTATION_RIGHTBOT:	/* XXX */
Packit 7838c8
			TIFFWarning(TIFFFileName(in), "using bottom-left orientation");
Packit 7838c8
			orientation = ORIENTATION_BOTLEFT;
Packit 7838c8
		/* fall thru... */
Packit 7838c8
		case ORIENTATION_LEFTBOT:	/* XXX */
Packit 7838c8
		case ORIENTATION_BOTLEFT:
Packit 7838c8
			break;
Packit 7838c8
		case ORIENTATION_TOPRIGHT:
Packit 7838c8
		case ORIENTATION_RIGHTTOP:	/* XXX */
Packit 7838c8
		default:
Packit 7838c8
			TIFFWarning(TIFFFileName(in), "using top-left orientation");
Packit 7838c8
			orientation = ORIENTATION_TOPLEFT;
Packit 7838c8
		/* fall thru... */
Packit 7838c8
		case ORIENTATION_LEFTTOP:	/* XXX */
Packit 7838c8
		case ORIENTATION_TOPLEFT:
Packit 7838c8
			break;
Packit 7838c8
	}
Packit 7838c8
	TIFFSetField(out, TIFFTAG_ORIENTATION, orientation);
Packit 7838c8
	/*
Packit 7838c8
	 * Choose tiles/strip for the output image according to
Packit 7838c8
	 * the command line arguments (-tiles, -strips) and the
Packit 7838c8
	 * structure of the input image.
Packit 7838c8
	 */
Packit 7838c8
	if (outtiled == -1)
Packit 7838c8
		outtiled = TIFFIsTiled(in);
Packit 7838c8
	if (outtiled) {
Packit 7838c8
		/*
Packit 7838c8
		 * Setup output file's tile width&height.  If either
Packit 7838c8
		 * is not specified, use either the value from the
Packit 7838c8
		 * input image or, if nothing is defined, use the
Packit 7838c8
		 * library default.
Packit 7838c8
		 */
Packit 7838c8
		if (tilewidth == (uint32) -1)
Packit 7838c8
			TIFFGetField(in, TIFFTAG_TILEWIDTH, &tilewidth);
Packit 7838c8
		if (tilelength == (uint32) -1)
Packit 7838c8
			TIFFGetField(in, TIFFTAG_TILELENGTH, &tilelength);
Packit 7838c8
		TIFFDefaultTileSize(out, &tilewidth, &tilelength);
Packit 7838c8
		TIFFSetField(out, TIFFTAG_TILEWIDTH, tilewidth);
Packit 7838c8
		TIFFSetField(out, TIFFTAG_TILELENGTH, tilelength);
Packit 7838c8
	} else {
Packit 7838c8
		/*
Packit 7838c8
		 * RowsPerStrip is left unspecified: use either the
Packit 7838c8
		 * value from the input image or, if nothing is defined,
Packit 7838c8
		 * use the library default.
Packit 7838c8
		 */
Packit 7838c8
		if (rowsperstrip == (uint32) 0) {
Packit 7838c8
			if (!TIFFGetField(in, TIFFTAG_ROWSPERSTRIP,
Packit 7838c8
			    &rowsperstrip)) {
Packit 7838c8
				rowsperstrip =
Packit 7838c8
				    TIFFDefaultStripSize(out, rowsperstrip);
Packit 7838c8
			}
Packit 7838c8
			if (rowsperstrip > length && rowsperstrip != (uint32)-1)
Packit 7838c8
				rowsperstrip = length;
Packit 7838c8
		}
Packit 7838c8
		else if (rowsperstrip == (uint32) -1)
Packit 7838c8
			rowsperstrip = length;
Packit 7838c8
		TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
Packit 7838c8
	}
Packit 7838c8
	if (config != (uint16) -1)
Packit 7838c8
		TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
Packit 7838c8
	else
Packit 7838c8
		CopyField(TIFFTAG_PLANARCONFIG, config);
Packit 7838c8
	if (samplesperpixel <= 4)
Packit 7838c8
		CopyTag(TIFFTAG_TRANSFERFUNCTION, 4, TIFF_SHORT);
Packit 7838c8
	CopyTag(TIFFTAG_COLORMAP, 4, TIFF_SHORT);
Packit 7838c8
/* SMinSampleValue & SMaxSampleValue */
Packit 7838c8
	switch (compression) {
Packit 7838c8
		case COMPRESSION_JPEG:
Packit 7838c8
			TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
Packit 7838c8
			TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode);
Packit 7838c8
			break;
Packit 7838c8
		case COMPRESSION_JBIG:
Packit 7838c8
			CopyTag(TIFFTAG_FAXRECVPARAMS, 1, TIFF_LONG);
Packit 7838c8
			CopyTag(TIFFTAG_FAXRECVTIME, 1, TIFF_LONG);
Packit 7838c8
			CopyTag(TIFFTAG_FAXSUBADDRESS, 1, TIFF_ASCII);
Packit 7838c8
			CopyTag(TIFFTAG_FAXDCS, 1, TIFF_ASCII);
Packit 7838c8
			break;
Packit 7838c8
		case COMPRESSION_LZW:
Packit 7838c8
		case COMPRESSION_ADOBE_DEFLATE:
Packit 7838c8
		case COMPRESSION_DEFLATE:
Packit 7838c8
                case COMPRESSION_LZMA:
Packit 7838c8
			if (predictor != (uint16)-1)
Packit 7838c8
				TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
Packit 7838c8
			else
Packit 7838c8
				CopyField(TIFFTAG_PREDICTOR, predictor);
Packit 7838c8
			if (preset != -1) {
Packit 7838c8
                                if (compression == COMPRESSION_ADOBE_DEFLATE
Packit 7838c8
                                         || compression == COMPRESSION_DEFLATE)
Packit 7838c8
                                        TIFFSetField(out, TIFFTAG_ZIPQUALITY, preset);
Packit 7838c8
				else if (compression == COMPRESSION_LZMA)
Packit 7838c8
					TIFFSetField(out, TIFFTAG_LZMAPRESET, preset);
Packit 7838c8
                        }
Packit 7838c8
			break;
Packit 7838c8
		case COMPRESSION_CCITTFAX3:
Packit 7838c8
		case COMPRESSION_CCITTFAX4:
Packit 7838c8
			if (compression == COMPRESSION_CCITTFAX3) {
Packit 7838c8
				if (g3opts != (uint32) -1)
Packit 7838c8
					TIFFSetField(out, TIFFTAG_GROUP3OPTIONS,
Packit 7838c8
					    g3opts);
Packit 7838c8
				else
Packit 7838c8
					CopyField(TIFFTAG_GROUP3OPTIONS, g3opts);
Packit 7838c8
			} else
Packit 7838c8
				CopyTag(TIFFTAG_GROUP4OPTIONS, 1, TIFF_LONG);
Packit 7838c8
			CopyTag(TIFFTAG_BADFAXLINES, 1, TIFF_LONG);
Packit 7838c8
			CopyTag(TIFFTAG_CLEANFAXDATA, 1, TIFF_LONG);
Packit 7838c8
			CopyTag(TIFFTAG_CONSECUTIVEBADFAXLINES, 1, TIFF_LONG);
Packit 7838c8
			CopyTag(TIFFTAG_FAXRECVPARAMS, 1, TIFF_LONG);
Packit 7838c8
			CopyTag(TIFFTAG_FAXRECVTIME, 1, TIFF_LONG);
Packit 7838c8
			CopyTag(TIFFTAG_FAXSUBADDRESS, 1, TIFF_ASCII);
Packit 7838c8
			break;
Packit 7838c8
	}
Packit 7838c8
	{
Packit 7838c8
		uint32 len32;
Packit 7838c8
		void** data;
Packit 7838c8
		if (TIFFGetField(in, TIFFTAG_ICCPROFILE, &len32, &data))
Packit 7838c8
			TIFFSetField(out, TIFFTAG_ICCPROFILE, len32, data);
Packit 7838c8
	}
Packit 7838c8
	{
Packit 7838c8
		uint16 ninks;
Packit 7838c8
		const char* inknames;
Packit 7838c8
		if (TIFFGetField(in, TIFFTAG_NUMBEROFINKS, &ninks)) {
Packit 7838c8
			TIFFSetField(out, TIFFTAG_NUMBEROFINKS, ninks);
Packit 7838c8
			if (TIFFGetField(in, TIFFTAG_INKNAMES, &inknames)) {
Packit 7838c8
				int inknameslen = strlen(inknames) + 1;
Packit 7838c8
				const char* cp = inknames;
Packit 7838c8
				while (ninks > 1) {
Packit 7838c8
					cp = strchr(cp, '\0');
Packit 7838c8
                                        cp++;
Packit 7838c8
                                        inknameslen += (strlen(cp) + 1);
Packit 7838c8
					ninks--;
Packit 7838c8
				}
Packit 7838c8
				TIFFSetField(out, TIFFTAG_INKNAMES, inknameslen, inknames);
Packit 7838c8
			}
Packit 7838c8
		}
Packit 7838c8
	}
Packit 7838c8
	{
Packit 7838c8
		unsigned short pg0, pg1;
Packit 7838c8
Packit 7838c8
		if (pageInSeq == 1) {
Packit 7838c8
			if (pageNum < 0) /* only one input file */ {
Packit 7838c8
				if (TIFFGetField(in, TIFFTAG_PAGENUMBER, &pg0, &pg1))
Packit 7838c8
					TIFFSetField(out, TIFFTAG_PAGENUMBER, pg0, pg1);
Packit 7838c8
			} else
Packit 7838c8
				TIFFSetField(out, TIFFTAG_PAGENUMBER, pageNum++, 0);
Packit 7838c8
Packit 7838c8
		} else {
Packit 7838c8
			if (TIFFGetField(in, TIFFTAG_PAGENUMBER, &pg0, &pg1)) {
Packit 7838c8
				if (pageNum < 0) /* only one input file */
Packit 7838c8
					TIFFSetField(out, TIFFTAG_PAGENUMBER, pg0, pg1);
Packit 7838c8
				else
Packit 7838c8
					TIFFSetField(out, TIFFTAG_PAGENUMBER, pageNum++, 0);
Packit 7838c8
			}
Packit 7838c8
		}
Packit 7838c8
	}
Packit 7838c8
Packit 7838c8
	for (p = tags; p < &tags[NTAGS]; p++)
Packit 7838c8
		CopyTag(p->tag, p->count, p->type);
Packit 7838c8
Packit 7838c8
	cf = pickCopyFunc(in, out, bitspersample, samplesperpixel);
Packit 7838c8
	return (cf ? (*cf)(in, out, length, width, samplesperpixel) : FALSE);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Copy Functions.
Packit 7838c8
 */
Packit 7838c8
#define	DECLAREcpFunc(x) \
Packit 7838c8
static int x(TIFF* in, TIFF* out, \
Packit 7838c8
    uint32 imagelength, uint32 imagewidth, tsample_t spp)
Packit 7838c8
Packit 7838c8
#define	DECLAREreadFunc(x) \
Packit 7838c8
static int x(TIFF* in, \
Packit 7838c8
    uint8* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)
Packit 7838c8
typedef int (*readFunc)(TIFF*, uint8*, uint32, uint32, tsample_t);
Packit 7838c8
Packit 7838c8
#define	DECLAREwriteFunc(x) \
Packit 7838c8
static int x(TIFF* out, \
Packit 7838c8
    uint8* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)
Packit 7838c8
typedef int (*writeFunc)(TIFF*, uint8*, uint32, uint32, tsample_t);
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Contig -> contig by scanline for rows/strip change.
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpContig2ContigByRow)
Packit 7838c8
{
Packit 7838c8
	tsize_t scanlinesize = TIFFScanlineSize(in);
Packit 7838c8
	tdata_t buf;
Packit 7838c8
	uint32 row;
Packit 7838c8
Packit 7838c8
	buf = _TIFFmalloc(scanlinesize);
Packit 7838c8
	if (!buf)
Packit 7838c8
		return 0;
Packit 7838c8
	_TIFFmemset(buf, 0, scanlinesize);
Packit 7838c8
	(void) imagewidth; (void) spp;
Packit 7838c8
	for (row = 0; row < imagelength; row++) {
Packit 7838c8
		if (TIFFReadScanline(in, buf, row, 0) < 0 && !ignore) {
Packit 7838c8
			TIFFError(TIFFFileName(in),
Packit 7838c8
				  "Error, can't read scanline %lu",
Packit 7838c8
				  (unsigned long) row);
Packit 7838c8
			goto bad;
Packit 7838c8
		}
Packit 7838c8
		if (TIFFWriteScanline(out, buf, row, 0) < 0) {
Packit 7838c8
			TIFFError(TIFFFileName(out),
Packit 7838c8
				  "Error, can't write scanline %lu",
Packit 7838c8
				  (unsigned long) row);
Packit 7838c8
			goto bad;
Packit 7838c8
		}
Packit 7838c8
	}
Packit 7838c8
	_TIFFfree(buf);
Packit 7838c8
	return 1;
Packit 7838c8
bad:
Packit 7838c8
	_TIFFfree(buf);
Packit 7838c8
	return 0;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
Packit 7838c8
typedef void biasFn (void *image, void *bias, uint32 pixels);
Packit 7838c8
Packit 7838c8
#define subtract(bits) \
Packit 7838c8
static void subtract##bits (void *i, void *b, uint32 pixels)\
Packit 7838c8
{\
Packit 7838c8
   uint##bits *image = i;\
Packit 7838c8
   uint##bits *bias = b;\
Packit 7838c8
   while (pixels--) {\
Packit 7838c8
     *image = *image > *bias ? *image-*bias : 0;\
Packit 7838c8
     image++, bias++; \
Packit 7838c8
   } \
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
subtract(8)
Packit 7838c8
subtract(16)
Packit 7838c8
subtract(32)
Packit 7838c8
Packit 7838c8
static biasFn *lineSubtractFn (unsigned bits)
Packit 7838c8
{
Packit 7838c8
	switch (bits) {
Packit 7838c8
		case  8:  return subtract8;
Packit 7838c8
		case 16:  return subtract16;
Packit 7838c8
		case 32:  return subtract32;
Packit 7838c8
	}
Packit 7838c8
	return NULL;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Contig -> contig by scanline while subtracting a bias image.
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpBiasedContig2Contig)
Packit 7838c8
{
Packit 7838c8
	if (spp == 1) {
Packit 7838c8
		tsize_t biasSize = TIFFScanlineSize(bias);
Packit 7838c8
		tsize_t bufSize = TIFFScanlineSize(in);
Packit 7838c8
		tdata_t buf, biasBuf;
Packit 7838c8
		uint32 biasWidth = 0, biasLength = 0;
Packit 7838c8
		TIFFGetField(bias, TIFFTAG_IMAGEWIDTH, &biasWidth);
Packit 7838c8
		TIFFGetField(bias, TIFFTAG_IMAGELENGTH, &biasLength);
Packit 7838c8
		if (biasSize == bufSize &&
Packit 7838c8
		    imagelength == biasLength && imagewidth == biasWidth) {
Packit 7838c8
			uint16 sampleBits = 0;
Packit 7838c8
			biasFn *subtractLine;
Packit 7838c8
			TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &sampleBits);
Packit 7838c8
			subtractLine = lineSubtractFn (sampleBits);
Packit 7838c8
			if (subtractLine) {
Packit 7838c8
				uint32 row;
Packit 7838c8
				buf = _TIFFmalloc(bufSize);
Packit 7838c8
				biasBuf = _TIFFmalloc(bufSize);
Packit 7838c8
				for (row = 0; row < imagelength; row++) {
Packit 7838c8
					if (TIFFReadScanline(in, buf, row, 0) < 0
Packit 7838c8
					    && !ignore) {
Packit 7838c8
						TIFFError(TIFFFileName(in),
Packit 7838c8
						    "Error, can't read scanline %lu",
Packit 7838c8
						    (unsigned long) row);
Packit 7838c8
						goto bad;
Packit 7838c8
					}
Packit 7838c8
					if (TIFFReadScanline(bias, biasBuf, row, 0) < 0
Packit 7838c8
					    && !ignore) {
Packit 7838c8
						TIFFError(TIFFFileName(in),
Packit 7838c8
						    "Error, can't read biased scanline %lu",
Packit 7838c8
						    (unsigned long) row);
Packit 7838c8
						goto bad;
Packit 7838c8
					}
Packit 7838c8
					subtractLine (buf, biasBuf, imagewidth);
Packit 7838c8
					if (TIFFWriteScanline(out, buf, row, 0) < 0) {
Packit 7838c8
						TIFFError(TIFFFileName(out),
Packit 7838c8
						    "Error, can't write scanline %lu",
Packit 7838c8
						    (unsigned long) row);
Packit 7838c8
						goto bad;
Packit 7838c8
					}
Packit 7838c8
				}
Packit 7838c8
Packit 7838c8
				_TIFFfree(buf);
Packit 7838c8
				_TIFFfree(biasBuf);
Packit 7838c8
				TIFFSetDirectory(bias,
Packit 7838c8
				    TIFFCurrentDirectory(bias)); /* rewind */
Packit 7838c8
				return 1;
Packit 7838c8
bad:
Packit 7838c8
				_TIFFfree(buf);
Packit 7838c8
				_TIFFfree(biasBuf);
Packit 7838c8
				return 0;
Packit 7838c8
			} else {
Packit 7838c8
				TIFFError(TIFFFileName(in),
Packit 7838c8
				    "No support for biasing %d bit pixels\n",
Packit 7838c8
				    sampleBits);
Packit 7838c8
				return 0;
Packit 7838c8
			}
Packit 7838c8
		}
Packit 7838c8
		TIFFError(TIFFFileName(in),
Packit 7838c8
		    "Bias image %s,%d\nis not the same size as %s,%d\n",
Packit 7838c8
		    TIFFFileName(bias), TIFFCurrentDirectory(bias),
Packit 7838c8
		    TIFFFileName(in), TIFFCurrentDirectory(in));
Packit 7838c8
		return 0;
Packit 7838c8
	} else {
Packit 7838c8
		TIFFError(TIFFFileName(in),
Packit 7838c8
		    "Can't bias %s,%d as it has >1 Sample/Pixel\n",
Packit 7838c8
		    TIFFFileName(in), TIFFCurrentDirectory(in));
Packit 7838c8
		return 0;
Packit 7838c8
	}
Packit 7838c8
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Strip -> strip for change in encoding.
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpDecodedStrips)
Packit 7838c8
{
Packit 7838c8
	tsize_t stripsize  = TIFFStripSize(in);
Packit 7838c8
	tdata_t buf = _TIFFmalloc(stripsize);
Packit 7838c8
Packit 7838c8
	(void) imagewidth; (void) spp;
Packit 7838c8
	if (buf) {
Packit 7838c8
		tstrip_t s, ns = TIFFNumberOfStrips(in);
Packit 7838c8
		uint32 row = 0;
Packit 7838c8
		_TIFFmemset(buf, 0, stripsize);
Packit 7838c8
		for (s = 0; s < ns && row < imagelength; s++) {
Packit 7838c8
			tsize_t cc = (row + rowsperstrip > imagelength) ?
Packit 7838c8
			    TIFFVStripSize(in, imagelength - row) : stripsize;
Packit 7838c8
			if (TIFFReadEncodedStrip(in, s, buf, cc) < 0
Packit 7838c8
			    && !ignore) {
Packit 7838c8
				TIFFError(TIFFFileName(in),
Packit 7838c8
				    "Error, can't read strip %lu",
Packit 7838c8
				    (unsigned long) s);
Packit 7838c8
				goto bad;
Packit 7838c8
			}
Packit 7838c8
			if (TIFFWriteEncodedStrip(out, s, buf, cc) < 0) {
Packit 7838c8
				TIFFError(TIFFFileName(out),
Packit 7838c8
				    "Error, can't write strip %lu",
Packit 7838c8
				    (unsigned long) s);
Packit 7838c8
				goto bad;
Packit 7838c8
			}
Packit 7838c8
			row += rowsperstrip;
Packit 7838c8
		}
Packit 7838c8
		_TIFFfree(buf);
Packit 7838c8
		return 1;
Packit 7838c8
	} else {
Packit 7838c8
		TIFFError(TIFFFileName(in),
Packit 7838c8
		    "Error, can't allocate memory buffer of size %lu "
Packit 7838c8
		    "to read strips", (unsigned long) stripsize);
Packit 7838c8
		return 0;
Packit 7838c8
	}
Packit 7838c8
Packit 7838c8
bad:
Packit 7838c8
	_TIFFfree(buf);
Packit 7838c8
	return 0;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Separate -> separate by row for rows/strip change.
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpSeparate2SeparateByRow)
Packit 7838c8
{
Packit 7838c8
	tsize_t scanlinesize = TIFFScanlineSize(in);
Packit 7838c8
	tdata_t buf;
Packit 7838c8
	uint32 row;
Packit 7838c8
	tsample_t s;
Packit 7838c8
Packit 7838c8
	(void) imagewidth;
Packit 7838c8
	buf = _TIFFmalloc(scanlinesize);
Packit 7838c8
	if (!buf)
Packit 7838c8
		return 0;
Packit 7838c8
	_TIFFmemset(buf, 0, scanlinesize);
Packit 7838c8
	for (s = 0; s < spp; s++) {
Packit 7838c8
		for (row = 0; row < imagelength; row++) {
Packit 7838c8
			if (TIFFReadScanline(in, buf, row, s) < 0 && !ignore) {
Packit 7838c8
				TIFFError(TIFFFileName(in),
Packit 7838c8
				    "Error, can't read scanline %lu",
Packit 7838c8
				    (unsigned long) row);
Packit 7838c8
				goto bad;
Packit 7838c8
			}
Packit 7838c8
			if (TIFFWriteScanline(out, buf, row, s) < 0) {
Packit 7838c8
				TIFFError(TIFFFileName(out),
Packit 7838c8
				    "Error, can't write scanline %lu",
Packit 7838c8
				    (unsigned long) row);
Packit 7838c8
				goto bad;
Packit 7838c8
			}
Packit 7838c8
		}
Packit 7838c8
	}
Packit 7838c8
	_TIFFfree(buf);
Packit 7838c8
	return 1;
Packit 7838c8
bad:
Packit 7838c8
	_TIFFfree(buf);
Packit 7838c8
	return 0;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Contig -> separate by row.
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpContig2SeparateByRow)
Packit 7838c8
{
Packit 7838c8
	tsize_t scanlinesizein = TIFFScanlineSize(in);
Packit 7838c8
	tsize_t scanlinesizeout = TIFFScanlineSize(out);
Packit 7838c8
	tdata_t inbuf;
Packit 7838c8
	tdata_t outbuf;
Packit 7838c8
	register uint8 *inp, *outp;
Packit 7838c8
	register uint32 n;
Packit 7838c8
	uint32 row;
Packit 7838c8
	tsample_t s;
Packit 7838c8
        uint16 bps = 0;
Packit 7838c8
Packit 7838c8
        (void) TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bps;;
Packit 7838c8
        if( bps != 8 )
Packit 7838c8
        {
Packit 7838c8
            TIFFError(TIFFFileName(in),
Packit 7838c8
                      "Error, can only handle BitsPerSample=8 in %s",
Packit 7838c8
                      "cpContig2SeparateByRow");
Packit 7838c8
            return 0;
Packit 7838c8
        }
Packit 7838c8
Packit 7838c8
	inbuf = _TIFFmalloc(scanlinesizein);
Packit 7838c8
	outbuf = _TIFFmalloc(scanlinesizeout);
Packit 7838c8
	if (!inbuf || !outbuf)
Packit 7838c8
		goto bad;
Packit 7838c8
	_TIFFmemset(inbuf, 0, scanlinesizein);
Packit 7838c8
	_TIFFmemset(outbuf, 0, scanlinesizeout);
Packit 7838c8
	/* unpack channels */
Packit 7838c8
	for (s = 0; s < spp; s++) {
Packit 7838c8
		for (row = 0; row < imagelength; row++) {
Packit 7838c8
			if (TIFFReadScanline(in, inbuf, row, 0) < 0
Packit 7838c8
			    && !ignore) {
Packit 7838c8
				TIFFError(TIFFFileName(in),
Packit 7838c8
				    "Error, can't read scanline %lu",
Packit 7838c8
				    (unsigned long) row);
Packit 7838c8
				goto bad;
Packit 7838c8
			}
Packit 7838c8
			inp = ((uint8*)inbuf) + s;
Packit 7838c8
			outp = (uint8*)outbuf;
Packit 7838c8
			for (n = imagewidth; n-- > 0;) {
Packit 7838c8
				*outp++ = *inp;
Packit 7838c8
				inp += spp;
Packit 7838c8
			}
Packit 7838c8
			if (TIFFWriteScanline(out, outbuf, row, s) < 0) {
Packit 7838c8
				TIFFError(TIFFFileName(out),
Packit 7838c8
				    "Error, can't write scanline %lu",
Packit 7838c8
				    (unsigned long) row);
Packit 7838c8
				goto bad;
Packit 7838c8
			}
Packit 7838c8
		}
Packit 7838c8
	}
Packit 7838c8
	if (inbuf) _TIFFfree(inbuf);
Packit 7838c8
	if (outbuf) _TIFFfree(outbuf);
Packit 7838c8
	return 1;
Packit 7838c8
bad:
Packit 7838c8
	if (inbuf) _TIFFfree(inbuf);
Packit 7838c8
	if (outbuf) _TIFFfree(outbuf);
Packit 7838c8
	return 0;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Separate -> contig by row.
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpSeparate2ContigByRow)
Packit 7838c8
{
Packit 7838c8
	tsize_t scanlinesizein = TIFFScanlineSize(in);
Packit 7838c8
	tsize_t scanlinesizeout = TIFFScanlineSize(out);
Packit 7838c8
	tdata_t inbuf;
Packit 7838c8
	tdata_t outbuf;
Packit 7838c8
	register uint8 *inp, *outp;
Packit 7838c8
	register uint32 n;
Packit 7838c8
	uint32 row;
Packit 7838c8
	tsample_t s;
Packit 7838c8
        uint16 bps = 0;
Packit 7838c8
Packit 7838c8
        (void) TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bps;;
Packit 7838c8
        if( bps != 8 )
Packit 7838c8
        {
Packit 7838c8
            TIFFError(TIFFFileName(in),
Packit 7838c8
                      "Error, can only handle BitsPerSample=8 in %s",
Packit 7838c8
                      "cpSeparate2ContigByRow");
Packit 7838c8
            return 0;
Packit 7838c8
        }
Packit 7838c8
Packit 7838c8
	inbuf = _TIFFmalloc(scanlinesizein);
Packit 7838c8
	outbuf = _TIFFmalloc(scanlinesizeout);
Packit 7838c8
	if (!inbuf || !outbuf)
Packit 7838c8
                goto bad;
Packit 7838c8
	_TIFFmemset(inbuf, 0, scanlinesizein);
Packit 7838c8
	_TIFFmemset(outbuf, 0, scanlinesizeout);
Packit 7838c8
	for (row = 0; row < imagelength; row++) {
Packit 7838c8
		/* merge channels */
Packit 7838c8
		for (s = 0; s < spp; s++) {
Packit 7838c8
			if (TIFFReadScanline(in, inbuf, row, s) < 0
Packit 7838c8
			    && !ignore) {
Packit 7838c8
				TIFFError(TIFFFileName(in),
Packit 7838c8
				    "Error, can't read scanline %lu",
Packit 7838c8
				    (unsigned long) row);
Packit 7838c8
				goto bad;
Packit 7838c8
			}
Packit 7838c8
			inp = (uint8*)inbuf;
Packit 7838c8
			outp = ((uint8*)outbuf) + s;
Packit 7838c8
			for (n = imagewidth; n-- > 0;) {
Packit 7838c8
				*outp = *inp++;
Packit 7838c8
				outp += spp;
Packit 7838c8
			}
Packit 7838c8
		}
Packit 7838c8
		if (TIFFWriteScanline(out, outbuf, row, 0) < 0) {
Packit 7838c8
			TIFFError(TIFFFileName(out),
Packit 7838c8
			    "Error, can't write scanline %lu",
Packit 7838c8
			    (unsigned long) row);
Packit 7838c8
			goto bad;
Packit 7838c8
		}
Packit 7838c8
	}
Packit 7838c8
	if (inbuf) _TIFFfree(inbuf);
Packit 7838c8
	if (outbuf) _TIFFfree(outbuf);
Packit 7838c8
	return 1;
Packit 7838c8
bad:
Packit 7838c8
	if (inbuf) _TIFFfree(inbuf);
Packit 7838c8
	if (outbuf) _TIFFfree(outbuf);
Packit 7838c8
	return 0;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
static void
Packit 7838c8
cpStripToTile(uint8* out, uint8* in,
Packit 7838c8
    uint32 rows, uint32 cols, int outskew, int64 inskew)
Packit 7838c8
{
Packit 7838c8
	while (rows-- > 0) {
Packit 7838c8
		uint32 j = cols;
Packit 7838c8
		while (j-- > 0)
Packit 7838c8
			*out++ = *in++;
Packit 7838c8
		out += outskew;
Packit 7838c8
		in += inskew;
Packit 7838c8
	}
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
static void
Packit 7838c8
cpContigBufToSeparateBuf(uint8* out, uint8* in,
Packit 7838c8
    uint32 rows, uint32 cols, int outskew, int inskew, tsample_t spp,
Packit 7838c8
    int bytes_per_sample )
Packit 7838c8
{
Packit 7838c8
	while (rows-- > 0) {
Packit 7838c8
		uint32 j = cols;
Packit 7838c8
		while (j-- > 0)
Packit 7838c8
		{
Packit 7838c8
			int n = bytes_per_sample;
Packit 7838c8
Packit 7838c8
			while( n-- ) {
Packit 7838c8
				*out++ = *in++;
Packit 7838c8
			}
Packit 7838c8
			in += (spp-1) * bytes_per_sample;
Packit 7838c8
		}
Packit 7838c8
		out += outskew;
Packit 7838c8
		in += inskew;
Packit 7838c8
	}
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
static void
Packit 7838c8
cpSeparateBufToContigBuf(uint8* out, uint8* in,
Packit 7838c8
    uint32 rows, uint32 cols, int outskew, int inskew, tsample_t spp,
Packit 7838c8
    int bytes_per_sample)
Packit 7838c8
{
Packit 7838c8
	while (rows-- > 0) {
Packit 7838c8
		uint32 j = cols;
Packit 7838c8
		while (j-- > 0) {
Packit 7838c8
			int n = bytes_per_sample;
Packit 7838c8
Packit 7838c8
			while( n-- ) {
Packit 7838c8
				*out++ = *in++;
Packit 7838c8
			}
Packit 7838c8
			out += (spp-1)*bytes_per_sample;
Packit 7838c8
		}
Packit 7838c8
		out += outskew;
Packit 7838c8
		in += inskew;
Packit 7838c8
	}
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
static int
Packit 7838c8
cpImage(TIFF* in, TIFF* out, readFunc fin, writeFunc fout,
Packit 7838c8
	uint32 imagelength, uint32 imagewidth, tsample_t spp)
Packit 7838c8
{
Packit 7838c8
	int status = 0;
Packit 7838c8
	tdata_t buf = NULL;
Packit 7838c8
	tsize_t scanlinesize = TIFFRasterScanlineSize(in);
Packit 7838c8
	tsize_t bytes = scanlinesize * (tsize_t)imagelength;
Packit 7838c8
	/*
Packit 7838c8
	 * XXX: Check for integer overflow.
Packit 7838c8
	 */
Packit 7838c8
	if (scanlinesize
Packit 7838c8
	    && imagelength
Packit 7838c8
	    && bytes / (tsize_t)imagelength == scanlinesize) {
Packit 7838c8
		buf = _TIFFmalloc(bytes);
Packit 7838c8
		if (buf) {
Packit 7838c8
			if ((*fin)(in, (uint8*)buf, imagelength,
Packit 7838c8
			    imagewidth, spp)) {
Packit 7838c8
				status = (*fout)(out, (uint8*)buf,
Packit 7838c8
				    imagelength, imagewidth, spp);
Packit 7838c8
			}
Packit 7838c8
			_TIFFfree(buf);
Packit 7838c8
		} else {
Packit 7838c8
			TIFFError(TIFFFileName(in),
Packit 7838c8
			    "Error, can't allocate space for image buffer");
Packit 7838c8
		}
Packit 7838c8
	} else {
Packit 7838c8
		TIFFError(TIFFFileName(in), "Error, no space for image buffer");
Packit 7838c8
	}
Packit 7838c8
Packit 7838c8
	return status;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
DECLAREreadFunc(readContigStripsIntoBuffer)
Packit 7838c8
{
Packit 7838c8
	tsize_t scanlinesize = TIFFScanlineSize(in);
Packit 7838c8
	uint8* bufp = buf;
Packit 7838c8
	uint32 row;
Packit 7838c8
Packit 7838c8
	(void) imagewidth; (void) spp;
Packit 7838c8
	for (row = 0; row < imagelength; row++) {
Packit 7838c8
		if (TIFFReadScanline(in, (tdata_t) bufp, row, 0) < 0
Packit 7838c8
		    && !ignore) {
Packit 7838c8
			TIFFError(TIFFFileName(in),
Packit 7838c8
			    "Error, can't read scanline %lu",
Packit 7838c8
			    (unsigned long) row);
Packit 7838c8
			return 0;
Packit 7838c8
		}
Packit 7838c8
		bufp += scanlinesize;
Packit 7838c8
	}
Packit 7838c8
Packit 7838c8
	return 1;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
DECLAREreadFunc(readSeparateStripsIntoBuffer)
Packit 7838c8
{
Packit 7838c8
	int status = 1;
Packit 7838c8
	tsize_t scanlinesize = TIFFScanlineSize(in);
Packit 7838c8
	tdata_t scanline;
Packit 7838c8
	if (!scanlinesize)
Packit 7838c8
		return 0;
Packit 7838c8
Packit 7838c8
	scanline = _TIFFmalloc(scanlinesize);
Packit 7838c8
	if (!scanline)
Packit 7838c8
		return 0;
Packit 7838c8
	_TIFFmemset(scanline, 0, scanlinesize);
Packit 7838c8
	(void) imagewidth;
Packit 7838c8
	if (scanline) {
Packit 7838c8
		uint8* bufp = (uint8*) buf;
Packit 7838c8
		uint32 row;
Packit 7838c8
		tsample_t s;
Packit 7838c8
		for (row = 0; row < imagelength; row++) {
Packit 7838c8
			/* merge channels */
Packit 7838c8
			for (s = 0; s < spp; s++) {
Packit 7838c8
				uint8* bp = bufp + s;
Packit 7838c8
				tsize_t n = scanlinesize;
Packit 7838c8
				uint8* sbuf = scanline;
Packit 7838c8
Packit 7838c8
				if (TIFFReadScanline(in, scanline, row, s) < 0
Packit 7838c8
				    && !ignore) {
Packit 7838c8
					TIFFError(TIFFFileName(in),
Packit 7838c8
					    "Error, can't read scanline %lu",
Packit 7838c8
					    (unsigned long) row);
Packit 7838c8
					    status = 0;
Packit 7838c8
					goto done;
Packit 7838c8
				}
Packit 7838c8
				while (n-- > 0)
Packit 7838c8
					*bp = *sbuf++, bp += spp;
Packit 7838c8
			}
Packit 7838c8
			bufp += scanlinesize * spp;
Packit 7838c8
		}
Packit 7838c8
	}
Packit 7838c8
Packit 7838c8
done:
Packit 7838c8
	_TIFFfree(scanline);
Packit 7838c8
	return status;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
DECLAREreadFunc(readContigTilesIntoBuffer)
Packit 7838c8
{
Packit 7838c8
	int status = 1;
Packit 7838c8
	tsize_t tilesize = TIFFTileSize(in);
Packit 7838c8
	tdata_t tilebuf;
Packit 7838c8
	uint32 imagew = TIFFScanlineSize(in);
Packit 7838c8
	uint32 tilew  = TIFFTileRowSize(in);
Packit 7838c8
	int64 iskew = (int64)imagew - (int64)tilew;
Packit 7838c8
	uint8* bufp = (uint8*) buf;
Packit 7838c8
	uint32 tw, tl;
Packit 7838c8
	uint32 row;
Packit 7838c8
Packit 7838c8
	(void) spp;
Packit 7838c8
	tilebuf = _TIFFmalloc(tilesize);
Packit 7838c8
	if (tilebuf == 0)
Packit 7838c8
		return 0;
Packit 7838c8
	_TIFFmemset(tilebuf, 0, tilesize);
Packit 7838c8
	(void) TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
Packit 7838c8
	(void) TIFFGetField(in, TIFFTAG_TILELENGTH, &tl;;
Packit 7838c8
        
Packit 7838c8
	for (row = 0; row < imagelength; row += tl) {
Packit 7838c8
		uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
Packit 7838c8
		uint32 colb = 0;
Packit 7838c8
		uint32 col;
Packit 7838c8
Packit 7838c8
		for (col = 0; col < imagewidth && colb < imagew; col += tw) {
Packit 7838c8
			if (TIFFReadTile(in, tilebuf, col, row, 0, 0) < 0
Packit 7838c8
			    && !ignore) {
Packit 7838c8
				TIFFError(TIFFFileName(in),
Packit 7838c8
				    "Error, can't read tile at %lu %lu",
Packit 7838c8
				    (unsigned long) col,
Packit 7838c8
				    (unsigned long) row);
Packit 7838c8
				status = 0;
Packit 7838c8
				goto done;
Packit 7838c8
			}
Packit 7838c8
			if (colb > iskew) {
Packit 7838c8
				uint32 width = imagew - colb;
Packit 7838c8
				uint32 oskew = tilew - width;
Packit 7838c8
				cpStripToTile(bufp + colb,
Packit 7838c8
				    tilebuf, nrow, width,
Packit 7838c8
				    oskew + iskew, oskew );
Packit 7838c8
			} else
Packit 7838c8
				cpStripToTile(bufp + colb,
Packit 7838c8
				    tilebuf, nrow, tilew,
Packit 7838c8
				    iskew, 0);
Packit 7838c8
			colb += tilew;
Packit 7838c8
		}
Packit 7838c8
		bufp += imagew * nrow;
Packit 7838c8
	}
Packit 7838c8
done:
Packit 7838c8
	_TIFFfree(tilebuf);
Packit 7838c8
	return status;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
DECLAREreadFunc(readSeparateTilesIntoBuffer)
Packit 7838c8
{
Packit 7838c8
	int status = 1;
Packit 7838c8
	uint32 imagew = TIFFRasterScanlineSize(in);
Packit 7838c8
	uint32 tilew = TIFFTileRowSize(in);
Packit 7838c8
	int iskew  = imagew - tilew*spp;
Packit 7838c8
	tsize_t tilesize = TIFFTileSize(in);
Packit 7838c8
	tdata_t tilebuf;
Packit 7838c8
	uint8* bufp = (uint8*) buf;
Packit 7838c8
	uint32 tw, tl;
Packit 7838c8
	uint32 row;
Packit 7838c8
	uint16 bps = 0, bytes_per_sample;
Packit 7838c8
Packit 7838c8
	tilebuf = _TIFFmalloc(tilesize);
Packit 7838c8
	if (tilebuf == 0)
Packit 7838c8
		return 0;
Packit 7838c8
	_TIFFmemset(tilebuf, 0, tilesize);
Packit 7838c8
	(void) TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
Packit 7838c8
	(void) TIFFGetField(in, TIFFTAG_TILELENGTH, &tl;;
Packit 7838c8
	(void) TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bps;;
Packit 7838c8
        if( bps == 0 )
Packit 7838c8
        {
Packit 7838c8
            TIFFError(TIFFFileName(in), "Error, cannot read BitsPerSample");
Packit 7838c8
            status = 0;
Packit 7838c8
            goto done;
Packit 7838c8
        }
Packit 7838c8
        if( (bps % 8) != 0 )
Packit 7838c8
        {
Packit 7838c8
            TIFFError(TIFFFileName(in), "Error, cannot handle BitsPerSample that is not a multiple of 8");
Packit 7838c8
            status = 0;
Packit 7838c8
            goto done;
Packit 7838c8
        }
Packit 7838c8
	bytes_per_sample = bps/8;
Packit 7838c8
Packit 7838c8
	for (row = 0; row < imagelength; row += tl) {
Packit 7838c8
		uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
Packit 7838c8
		uint32 colb = 0;
Packit 7838c8
		uint32 col;
Packit 7838c8
Packit 7838c8
		for (col = 0; col < imagewidth; col += tw) {
Packit 7838c8
			tsample_t s;
Packit 7838c8
Packit 7838c8
			for (s = 0; s < spp; s++) {
Packit 7838c8
				if (TIFFReadTile(in, tilebuf, col, row, 0, s) < 0
Packit 7838c8
				    && !ignore) {
Packit 7838c8
					TIFFError(TIFFFileName(in),
Packit 7838c8
					    "Error, can't read tile at %lu %lu, "
Packit 7838c8
					    "sample %lu",
Packit 7838c8
					    (unsigned long) col,
Packit 7838c8
					    (unsigned long) row,
Packit 7838c8
					    (unsigned long) s);
Packit 7838c8
					status = 0;
Packit 7838c8
					goto done;
Packit 7838c8
				}
Packit 7838c8
				/*
Packit 7838c8
				 * Tile is clipped horizontally.  Calculate
Packit 7838c8
				 * visible portion and skewing factors.
Packit 7838c8
				 */
Packit 7838c8
				if (colb + tilew*spp > imagew) {
Packit 7838c8
					uint32 width = imagew - colb;
Packit 7838c8
					int oskew = tilew*spp - width;
Packit 7838c8
					cpSeparateBufToContigBuf(
Packit 7838c8
					    bufp+colb+s*bytes_per_sample,
Packit 7838c8
					    tilebuf, nrow,
Packit 7838c8
					    width/(spp*bytes_per_sample),
Packit 7838c8
					    oskew + iskew,
Packit 7838c8
					    oskew/spp, spp,
Packit 7838c8
					    bytes_per_sample);
Packit 7838c8
				} else
Packit 7838c8
					cpSeparateBufToContigBuf(
Packit 7838c8
					    bufp+colb+s*bytes_per_sample,
Packit 7838c8
					    tilebuf, nrow, tw,
Packit 7838c8
					    iskew, 0, spp,
Packit 7838c8
					    bytes_per_sample);
Packit 7838c8
			}
Packit 7838c8
			colb += tilew*spp;
Packit 7838c8
		}
Packit 7838c8
		bufp += imagew * nrow;
Packit 7838c8
	}
Packit 7838c8
done:
Packit 7838c8
	_TIFFfree(tilebuf);
Packit 7838c8
	return status;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
DECLAREwriteFunc(writeBufferToContigStrips)
Packit 7838c8
{
Packit 7838c8
	uint32 row, rowsperstrip;
Packit 7838c8
	tstrip_t strip = 0;
Packit 7838c8
Packit 7838c8
	(void) imagewidth; (void) spp;
Packit 7838c8
	(void) TIFFGetFieldDefaulted(out, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
Packit 7838c8
	for (row = 0; row < imagelength; row += rowsperstrip) {
Packit 7838c8
		uint32 nrows = (row+rowsperstrip > imagelength) ?
Packit 7838c8
		    imagelength-row : rowsperstrip;
Packit 7838c8
		tsize_t stripsize = TIFFVStripSize(out, nrows);
Packit 7838c8
		if (TIFFWriteEncodedStrip(out, strip++, buf, stripsize) < 0) {
Packit 7838c8
			TIFFError(TIFFFileName(out),
Packit 7838c8
			    "Error, can't write strip %u", strip - 1);
Packit 7838c8
			return 0;
Packit 7838c8
		}
Packit 7838c8
		buf += stripsize;
Packit 7838c8
	}
Packit 7838c8
	return 1;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
DECLAREwriteFunc(writeBufferToSeparateStrips)
Packit 7838c8
{
Packit 7838c8
	uint32 rowsize = imagewidth * spp;
Packit 7838c8
	uint32 rowsperstrip;
Packit 7838c8
	tsize_t stripsize = TIFFStripSize(out);
Packit 7838c8
	tdata_t obuf;
Packit 7838c8
	tstrip_t strip = 0;
Packit 7838c8
	tsample_t s;
Packit 7838c8
Packit 7838c8
	obuf = _TIFFmalloc(stripsize);
Packit 7838c8
	if (obuf == NULL)
Packit 7838c8
		return (0);
Packit 7838c8
	_TIFFmemset(obuf, 0, stripsize);
Packit 7838c8
	(void) TIFFGetFieldDefaulted(out, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
Packit 7838c8
	for (s = 0; s < spp; s++) {
Packit 7838c8
		uint32 row;
Packit 7838c8
		for (row = 0; row < imagelength; row += rowsperstrip) {
Packit 7838c8
			uint32 nrows = (row+rowsperstrip > imagelength) ?
Packit 7838c8
			    imagelength-row : rowsperstrip;
Packit 7838c8
			tsize_t stripsize = TIFFVStripSize(out, nrows);
Packit 7838c8
Packit 7838c8
			cpContigBufToSeparateBuf(
Packit 7838c8
			    obuf, (uint8*) buf + row*rowsize + s,
Packit 7838c8
			    nrows, imagewidth, 0, 0, spp, 1);
Packit 7838c8
			if (TIFFWriteEncodedStrip(out, strip++, obuf, stripsize) < 0) {
Packit 7838c8
				TIFFError(TIFFFileName(out),
Packit 7838c8
				    "Error, can't write strip %u",
Packit 7838c8
				    strip - 1);
Packit 7838c8
				_TIFFfree(obuf);
Packit 7838c8
				return 0;
Packit 7838c8
			}
Packit 7838c8
		}
Packit 7838c8
	}
Packit 7838c8
	_TIFFfree(obuf);
Packit 7838c8
	return 1;
Packit 7838c8
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
DECLAREwriteFunc(writeBufferToContigTiles)
Packit 7838c8
{
Packit 7838c8
	uint32 imagew = TIFFScanlineSize(out);
Packit 7838c8
	uint32 tilew  = TIFFTileRowSize(out);
Packit 7838c8
	int iskew = imagew - tilew;
Packit 7838c8
	tsize_t tilesize = TIFFTileSize(out);
Packit 7838c8
	tdata_t obuf;
Packit 7838c8
	uint8* bufp = (uint8*) buf;
Packit 7838c8
	uint32 tl, tw;
Packit 7838c8
	uint32 row;
Packit 7838c8
Packit 7838c8
	(void) spp;
Packit 7838c8
Packit 7838c8
	obuf = _TIFFmalloc(TIFFTileSize(out));
Packit 7838c8
	if (obuf == NULL)
Packit 7838c8
		return 0;
Packit 7838c8
	_TIFFmemset(obuf, 0, tilesize);
Packit 7838c8
	(void) TIFFGetField(out, TIFFTAG_TILELENGTH, &tl;;
Packit 7838c8
	(void) TIFFGetField(out, TIFFTAG_TILEWIDTH, &tw);
Packit 7838c8
	for (row = 0; row < imagelength; row += tilelength) {
Packit 7838c8
		uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
Packit 7838c8
		uint32 colb = 0;
Packit 7838c8
		uint32 col;
Packit 7838c8
Packit 7838c8
		for (col = 0; col < imagewidth && colb < imagew; col += tw) {
Packit 7838c8
			/*
Packit 7838c8
			 * Tile is clipped horizontally.  Calculate
Packit 7838c8
			 * visible portion and skewing factors.
Packit 7838c8
			 */
Packit 7838c8
			if (colb + tilew > imagew) {
Packit 7838c8
				uint32 width = imagew - colb;
Packit 7838c8
				int oskew = tilew - width;
Packit 7838c8
				cpStripToTile(obuf, bufp + colb, nrow, width,
Packit 7838c8
				    oskew, oskew + iskew);
Packit 7838c8
			} else
Packit 7838c8
				cpStripToTile(obuf, bufp + colb, nrow, tilew,
Packit 7838c8
				    0, iskew);
Packit 7838c8
			if (TIFFWriteTile(out, obuf, col, row, 0, 0) < 0) {
Packit 7838c8
				TIFFError(TIFFFileName(out),
Packit 7838c8
				    "Error, can't write tile at %lu %lu",
Packit 7838c8
				    (unsigned long) col,
Packit 7838c8
				    (unsigned long) row);
Packit 7838c8
				_TIFFfree(obuf);
Packit 7838c8
				return 0;
Packit 7838c8
			}
Packit 7838c8
			colb += tilew;
Packit 7838c8
		}
Packit 7838c8
		bufp += nrow * imagew;
Packit 7838c8
	}
Packit 7838c8
	_TIFFfree(obuf);
Packit 7838c8
	return 1;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
DECLAREwriteFunc(writeBufferToSeparateTiles)
Packit 7838c8
{
Packit 7838c8
	uint32 imagew = TIFFScanlineSize(out);
Packit 7838c8
	tsize_t tilew  = TIFFTileRowSize(out);
Packit 7838c8
	uint32 iimagew = TIFFRasterScanlineSize(out);
Packit 7838c8
	int iskew = iimagew - tilew*spp;
Packit 7838c8
	tsize_t tilesize = TIFFTileSize(out);
Packit 7838c8
	tdata_t obuf;
Packit 7838c8
	uint8* bufp = (uint8*) buf;
Packit 7838c8
	uint32 tl, tw;
Packit 7838c8
	uint32 row;
Packit 7838c8
	uint16 bps = 0, bytes_per_sample;
Packit 7838c8
Packit 7838c8
	obuf = _TIFFmalloc(TIFFTileSize(out));
Packit 7838c8
	if (obuf == NULL)
Packit 7838c8
		return 0;
Packit 7838c8
	_TIFFmemset(obuf, 0, tilesize);
Packit 7838c8
	(void) TIFFGetField(out, TIFFTAG_TILELENGTH, &tl;;
Packit 7838c8
	(void) TIFFGetField(out, TIFFTAG_TILEWIDTH, &tw);
Packit 7838c8
	(void) TIFFGetField(out, TIFFTAG_BITSPERSAMPLE, &bps;;
Packit 7838c8
        if( bps == 0 )
Packit 7838c8
        {
Packit 7838c8
            TIFFError(TIFFFileName(out), "Error, cannot read BitsPerSample");
Packit 7838c8
            _TIFFfree(obuf);
Packit 7838c8
            return 0;
Packit 7838c8
        }
Packit 7838c8
        if( (bps % 8) != 0 )
Packit 7838c8
        {
Packit 7838c8
            TIFFError(TIFFFileName(out), "Error, cannot handle BitsPerSample that is not a multiple of 8");
Packit 7838c8
            _TIFFfree(obuf);
Packit 7838c8
            return 0;
Packit 7838c8
        }
Packit 7838c8
	bytes_per_sample = bps/8;
Packit 7838c8
Packit 7838c8
	for (row = 0; row < imagelength; row += tl) {
Packit 7838c8
		uint32 nrow = (row+tl > imagelength) ? imagelength-row : tl;
Packit 7838c8
		uint32 colb = 0;
Packit 7838c8
		uint32 col;
Packit 7838c8
Packit 7838c8
		for (col = 0; col < imagewidth; col += tw) {
Packit 7838c8
			tsample_t s;
Packit 7838c8
			for (s = 0; s < spp; s++) {
Packit 7838c8
				/*
Packit 7838c8
				 * Tile is clipped horizontally.  Calculate
Packit 7838c8
				 * visible portion and skewing factors.
Packit 7838c8
				 */
Packit 7838c8
				if (colb + tilew > imagew) {
Packit 7838c8
					uint32 width = (imagew - colb);
Packit 7838c8
					int oskew = tilew - width;
Packit 7838c8
Packit 7838c8
					cpContigBufToSeparateBuf(obuf,
Packit 7838c8
					    bufp + (colb*spp) + s,
Packit 7838c8
					    nrow, width/bytes_per_sample,
Packit 7838c8
					    oskew, (oskew*spp)+iskew, spp,
Packit 7838c8
					    bytes_per_sample);
Packit 7838c8
				} else
Packit 7838c8
					cpContigBufToSeparateBuf(obuf,
Packit 7838c8
					    bufp + (colb*spp) + s,
Packit 7838c8
					    nrow, tilewidth,
Packit 7838c8
					    0, iskew, spp,
Packit 7838c8
					    bytes_per_sample);
Packit 7838c8
				if (TIFFWriteTile(out, obuf, col, row, 0, s) < 0) {
Packit 7838c8
					TIFFError(TIFFFileName(out),
Packit 7838c8
					    "Error, can't write tile at %lu %lu "
Packit 7838c8
					    "sample %lu",
Packit 7838c8
					    (unsigned long) col,
Packit 7838c8
					    (unsigned long) row,
Packit 7838c8
					    (unsigned long) s);
Packit 7838c8
					_TIFFfree(obuf);
Packit 7838c8
					return 0;
Packit 7838c8
				}
Packit 7838c8
			}
Packit 7838c8
			colb += tilew;
Packit 7838c8
		}
Packit 7838c8
		bufp += nrow * iimagew;
Packit 7838c8
	}
Packit 7838c8
	_TIFFfree(obuf);
Packit 7838c8
	return 1;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Contig strips -> contig tiles.
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpContigStrips2ContigTiles)
Packit 7838c8
{
Packit 7838c8
	return cpImage(in, out,
Packit 7838c8
	    readContigStripsIntoBuffer,
Packit 7838c8
	    writeBufferToContigTiles,
Packit 7838c8
	    imagelength, imagewidth, spp);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Contig strips -> separate tiles.
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpContigStrips2SeparateTiles)
Packit 7838c8
{
Packit 7838c8
	return cpImage(in, out,
Packit 7838c8
	    readContigStripsIntoBuffer,
Packit 7838c8
	    writeBufferToSeparateTiles,
Packit 7838c8
	    imagelength, imagewidth, spp);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Separate strips -> contig tiles.
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpSeparateStrips2ContigTiles)
Packit 7838c8
{
Packit 7838c8
	return cpImage(in, out,
Packit 7838c8
	    readSeparateStripsIntoBuffer,
Packit 7838c8
	    writeBufferToContigTiles,
Packit 7838c8
	    imagelength, imagewidth, spp);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Separate strips -> separate tiles.
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpSeparateStrips2SeparateTiles)
Packit 7838c8
{
Packit 7838c8
	return cpImage(in, out,
Packit 7838c8
	    readSeparateStripsIntoBuffer,
Packit 7838c8
	    writeBufferToSeparateTiles,
Packit 7838c8
	    imagelength, imagewidth, spp);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Contig strips -> contig tiles.
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpContigTiles2ContigTiles)
Packit 7838c8
{
Packit 7838c8
	return cpImage(in, out,
Packit 7838c8
	    readContigTilesIntoBuffer,
Packit 7838c8
	    writeBufferToContigTiles,
Packit 7838c8
	    imagelength, imagewidth, spp);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Contig tiles -> separate tiles.
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpContigTiles2SeparateTiles)
Packit 7838c8
{
Packit 7838c8
	return cpImage(in, out,
Packit 7838c8
	    readContigTilesIntoBuffer,
Packit 7838c8
	    writeBufferToSeparateTiles,
Packit 7838c8
	    imagelength, imagewidth, spp);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Separate tiles -> contig tiles.
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpSeparateTiles2ContigTiles)
Packit 7838c8
{
Packit 7838c8
	return cpImage(in, out,
Packit 7838c8
	    readSeparateTilesIntoBuffer,
Packit 7838c8
	    writeBufferToContigTiles,
Packit 7838c8
	    imagelength, imagewidth, spp);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Separate tiles -> separate tiles (tile dimension change).
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpSeparateTiles2SeparateTiles)
Packit 7838c8
{
Packit 7838c8
	return cpImage(in, out,
Packit 7838c8
	    readSeparateTilesIntoBuffer,
Packit 7838c8
	    writeBufferToSeparateTiles,
Packit 7838c8
	    imagelength, imagewidth, spp);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Contig tiles -> contig tiles (tile dimension change).
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpContigTiles2ContigStrips)
Packit 7838c8
{
Packit 7838c8
	return cpImage(in, out,
Packit 7838c8
	    readContigTilesIntoBuffer,
Packit 7838c8
	    writeBufferToContigStrips,
Packit 7838c8
	    imagelength, imagewidth, spp);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Contig tiles -> separate strips.
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpContigTiles2SeparateStrips)
Packit 7838c8
{
Packit 7838c8
	return cpImage(in, out,
Packit 7838c8
	    readContigTilesIntoBuffer,
Packit 7838c8
	    writeBufferToSeparateStrips,
Packit 7838c8
	    imagelength, imagewidth, spp);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Separate tiles -> contig strips.
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpSeparateTiles2ContigStrips)
Packit 7838c8
{
Packit 7838c8
	return cpImage(in, out,
Packit 7838c8
	    readSeparateTilesIntoBuffer,
Packit 7838c8
	    writeBufferToContigStrips,
Packit 7838c8
	    imagelength, imagewidth, spp);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Separate tiles -> separate strips.
Packit 7838c8
 */
Packit 7838c8
DECLAREcpFunc(cpSeparateTiles2SeparateStrips)
Packit 7838c8
{
Packit 7838c8
	return cpImage(in, out,
Packit 7838c8
	    readSeparateTilesIntoBuffer,
Packit 7838c8
	    writeBufferToSeparateStrips,
Packit 7838c8
	    imagelength, imagewidth, spp);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/*
Packit 7838c8
 * Select the appropriate copy function to use.
Packit 7838c8
 */
Packit 7838c8
static copyFunc
Packit 7838c8
pickCopyFunc(TIFF* in, TIFF* out, uint16 bitspersample, uint16 samplesperpixel)
Packit 7838c8
{
Packit 7838c8
	uint16 shortv;
Packit 7838c8
	uint32 w, l, tw, tl;
Packit 7838c8
	int bychunk;
Packit 7838c8
Packit 7838c8
	(void) TIFFGetFieldDefaulted(in, TIFFTAG_PLANARCONFIG, &shortv;;
Packit 7838c8
	if (shortv != config && bitspersample != 8 && samplesperpixel > 1) {
Packit 7838c8
		fprintf(stderr,
Packit 7838c8
		    "%s: Cannot handle different planar configuration w/ bits/sample != 8\n",
Packit 7838c8
		    TIFFFileName(in));
Packit 7838c8
		return (NULL);
Packit 7838c8
	}
Packit 7838c8
	TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &w);
Packit 7838c8
	TIFFGetField(in, TIFFTAG_IMAGELENGTH, &l);
Packit 7838c8
	if (!(TIFFIsTiled(out) || TIFFIsTiled(in))) {
Packit 7838c8
		uint32 irps = (uint32) -1L;
Packit 7838c8
		TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &irps);
Packit 7838c8
		/* if biased, force decoded copying to allow image subtraction */
Packit 7838c8
		bychunk = !bias && (rowsperstrip == irps);
Packit 7838c8
	}else{  /* either in or out is tiled */
Packit 7838c8
		if (bias) {
Packit 7838c8
			fprintf(stderr,
Packit 7838c8
			    "%s: Cannot handle tiled configuration w/bias image\n",
Packit 7838c8
			TIFFFileName(in));
Packit 7838c8
			return (NULL);
Packit 7838c8
		}
Packit 7838c8
		if (TIFFIsTiled(out)) {
Packit 7838c8
			if (!TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw))
Packit 7838c8
				tw = w;
Packit 7838c8
			if (!TIFFGetField(in, TIFFTAG_TILELENGTH, &tl))
Packit 7838c8
				tl = l;
Packit 7838c8
			bychunk = (tw == tilewidth && tl == tilelength);
Packit 7838c8
		} else {  /* out's not, so in must be tiled */
Packit 7838c8
			TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
Packit 7838c8
			TIFFGetField(in, TIFFTAG_TILELENGTH, &tl;;
Packit 7838c8
			bychunk = (tw == w && tl == rowsperstrip);
Packit 7838c8
		}
Packit 7838c8
	}
Packit 7838c8
#define	T 1
Packit 7838c8
#define	F 0
Packit 7838c8
#define pack(a,b,c,d,e)	((long)(((a)<<11)|((b)<<3)|((c)<<2)|((d)<<1)|(e)))
Packit 7838c8
	switch(pack(shortv,config,TIFFIsTiled(in),TIFFIsTiled(out),bychunk)) {
Packit 7838c8
		/* Strips -> Tiles */
Packit 7838c8
		case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,T,F):
Packit 7838c8
		case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,T,T):
Packit 7838c8
			return cpContigStrips2ContigTiles;
Packit 7838c8
		case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, F,T,F):
Packit 7838c8
		case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, F,T,T):
Packit 7838c8
			return cpContigStrips2SeparateTiles;
Packit 7838c8
		case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,T,F):
Packit 7838c8
		case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,T,T):
Packit 7838c8
			return cpSeparateStrips2ContigTiles;
Packit 7838c8
		case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,T,F):
Packit 7838c8
		case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,T,T):
Packit 7838c8
			return cpSeparateStrips2SeparateTiles;
Packit 7838c8
		/* Tiles -> Tiles */
Packit 7838c8
		case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,T,F):
Packit 7838c8
		case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,T,T):
Packit 7838c8
			return cpContigTiles2ContigTiles;
Packit 7838c8
		case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,T,F):
Packit 7838c8
		case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,T,T):
Packit 7838c8
			return cpContigTiles2SeparateTiles;
Packit 7838c8
		case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,T,F):
Packit 7838c8
		case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,T,T):
Packit 7838c8
			return cpSeparateTiles2ContigTiles;
Packit 7838c8
		case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,T,F):
Packit 7838c8
		case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,T,T):
Packit 7838c8
			return cpSeparateTiles2SeparateTiles;
Packit 7838c8
		/* Tiles -> Strips */
Packit 7838c8
		case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,F,F):
Packit 7838c8
		case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,F,T):
Packit 7838c8
			return cpContigTiles2ContigStrips;
Packit 7838c8
		case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,F,F):
Packit 7838c8
		case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,F,T):
Packit 7838c8
			return cpContigTiles2SeparateStrips;
Packit 7838c8
		case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,F,F):
Packit 7838c8
		case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,F,T):
Packit 7838c8
			return cpSeparateTiles2ContigStrips;
Packit 7838c8
		case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,F,F):
Packit 7838c8
		case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,F,T):
Packit 7838c8
			return cpSeparateTiles2SeparateStrips;
Packit 7838c8
		/* Strips -> Strips */
Packit 7838c8
		case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,F,F):
Packit 7838c8
			return bias ? cpBiasedContig2Contig : cpContig2ContigByRow;
Packit 7838c8
		case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,F,T):
Packit 7838c8
			return cpDecodedStrips;
Packit 7838c8
		case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE,   F,F,F):
Packit 7838c8
		case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE,   F,F,T):
Packit 7838c8
			return cpContig2SeparateByRow;
Packit 7838c8
		case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,F,F):
Packit 7838c8
		case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,F,T):
Packit 7838c8
			return cpSeparate2ContigByRow;
Packit 7838c8
		case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,F,F):
Packit 7838c8
		case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,F,T):
Packit 7838c8
			return cpSeparate2SeparateByRow;
Packit 7838c8
	}
Packit 7838c8
#undef pack
Packit 7838c8
#undef F
Packit 7838c8
#undef T
Packit 7838c8
	fprintf(stderr, "tiffcp: %s: Don't know how to copy/convert image.\n",
Packit 7838c8
	    TIFFFileName(in));
Packit 7838c8
	return (NULL);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
/* vim: set ts=8 sts=8 sw=8 noet: */
Packit 7838c8
/*
Packit 7838c8
 * Local Variables:
Packit 7838c8
 * mode: c
Packit 7838c8
 * c-basic-offset: 8
Packit 7838c8
 * fill-column: 78
Packit 7838c8
 * End:
Packit 7838c8
 */