kusano 7d535a
/* $Header: /cvs/maptools/cvsroot/libtiff/contrib/pds/tif_pdsdirwrite.c,v 1.4 2010-06-08 18:55:15 bfriesen Exp $ */
kusano 7d535a
kusano 7d535a
/* When writing data to TIFF files, it is often useful to store application-
kusano 7d535a
   specific data in a private TIFF directory so that the tags don't need to
kusano 7d535a
   be registered and won't conflict with other people's user-defined tags.
kusano 7d535a
   One needs to have a registered public tag which contains some amount of
kusano 7d535a
   raw data. That raw data, however, is interpreted at an independent,
kusano 7d535a
   separate, private tiff directory. This file provides some routines which
kusano 7d535a
   will be useful for converting that data from its raw binary form into
kusano 7d535a
   the proper form for your application.
kusano 7d535a
*/
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Copyright (c) 1988-1996 Sam Leffler
kusano 7d535a
 * Copyright (c) 1991-1996 Silicon Graphics, Inc.
kusano 7d535a
 * Copyright (c( 1996 USAF Phillips Laboratory
kusano 7d535a
 *
kusano 7d535a
 * Permission to use, copy, modify, distribute, and sell this software and 
kusano 7d535a
 * its documentation for any purpose is hereby granted without fee, provided
kusano 7d535a
 * that (i) the above copyright notices and this permission notice appear in
kusano 7d535a
 * all copies of the software and related documentation, and (ii) the names of
kusano 7d535a
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
kusano 7d535a
 * publicity relating to the software without the specific, prior written
kusano 7d535a
 * permission of Sam Leffler and Silicon Graphics.
kusano 7d535a
 * 
kusano 7d535a
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
kusano 7d535a
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
kusano 7d535a
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
kusano 7d535a
 * 
kusano 7d535a
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
kusano 7d535a
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
kusano 7d535a
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
kusano 7d535a
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
kusano 7d535a
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
kusano 7d535a
 * OF THIS SOFTWARE.
kusano 7d535a
 */
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * TIFF Library.
kusano 7d535a
 *
kusano 7d535a
 * These routines written by Conrad J. Poelman on a single late-night of
kusano 7d535a
 * March 20-21, 1996.
kusano 7d535a
 *
kusano 7d535a
 * The entire purpose of this file is to provide a single external function,
kusano 7d535a
 * TIFFWritePrivateDataSubDirectory(). This function is intended for use
kusano 7d535a
 * in writing a private subdirectory structure into a TIFF file. The
kusano 7d535a
 * actual reading of data from the structure is handled by the getFieldFn(),
kusano 7d535a
 * which is passed to TIFFWritePrivateDataSubDirectory() as a parameter. The
kusano 7d535a
 * idea is to enable any application wishing to read private subdirectories to
kusano 7d535a
 * do so easily using this function, without modifying the TIFF library.
kusano 7d535a
 *
kusano 7d535a
 * The astute observer will notice that only two functions are at all different
kusano 7d535a
 * from the original tif_dirwrite.c file: TIFFWritePrivateDataSubDirectory()and
kusano 7d535a
 * TIFFWriteNormalSubTag(). All the other stuff that makes this file so huge
kusano 7d535a
 * is only necessary because all of those functions are declared static in
kusano 7d535a
 * tif_dirwrite.c, so we have to totally duplicate them in order to use them.
kusano 7d535a
 *
kusano 7d535a
 * Oh, also please note the bug-fix in the routine TIFFWriteNormalSubTag(),
kusano 7d535a
 * which equally should be applied to TIFFWriteNormalTag().
kusano 7d535a
 *
kusano 7d535a
 */
kusano 7d535a
#include "tiffiop.h"
kusano 7d535a
kusano 7d535a
#if HAVE_IEEEFP
kusano 7d535a
#define	TIFFCvtNativeToIEEEFloat(tif, n, fp)
kusano 7d535a
#define	TIFFCvtNativeToIEEEDouble(tif, n, dp)
kusano 7d535a
#else
kusano 7d535a
extern	void TIFFCvtNativeToIEEEFloat(TIFF*, uint32, float*);
kusano 7d535a
extern	void TIFFCvtNativeToIEEEDouble(TIFF*, uint32, double*);
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
static	int TIFFWriteNormalTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*);
kusano 7d535a
static	int TIFFWriteNormalSubTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*,
kusano 7d535a
				  int (*getFieldFn)(TIFF *tif,ttag_t tag,...));
kusano 7d535a
static	void TIFFSetupShortLong(TIFF*, ttag_t, TIFFDirEntry*, uint32);
kusano 7d535a
static	int TIFFSetupShortPair(TIFF*, ttag_t, TIFFDirEntry*);
kusano 7d535a
static	int TIFFWritePerSampleShorts(TIFF*, ttag_t, TIFFDirEntry*);
kusano 7d535a
static	int TIFFWritePerSampleAnys(TIFF*, TIFFDataType, ttag_t, TIFFDirEntry*);
kusano 7d535a
static	int TIFFWriteShortTable(TIFF*, ttag_t, TIFFDirEntry*, uint32, uint16**);
kusano 7d535a
static	int TIFFWriteShortArray(TIFF*,
kusano 7d535a
	    TIFFDataType, ttag_t, TIFFDirEntry*, uint32, uint16*);
kusano 7d535a
static	int TIFFWriteLongArray(TIFF *,
kusano 7d535a
	    TIFFDataType, ttag_t, TIFFDirEntry*, uint32, uint32*);
kusano 7d535a
static	int TIFFWriteRationalArray(TIFF *,
kusano 7d535a
	    TIFFDataType, ttag_t, TIFFDirEntry*, uint32, float*);
kusano 7d535a
static	int TIFFWriteFloatArray(TIFF *,
kusano 7d535a
	    TIFFDataType, ttag_t, TIFFDirEntry*, uint32, float*);
kusano 7d535a
static	int TIFFWriteDoubleArray(TIFF *,
kusano 7d535a
	    TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*);
kusano 7d535a
static	int TIFFWriteByteArray(TIFF*, TIFFDirEntry*, char*);
kusano 7d535a
static	int TIFFWriteAnyArray(TIFF*,
kusano 7d535a
	    TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*);
kusano 7d535a
#ifdef COLORIMETRY_SUPPORT
kusano 7d535a
static	int TIFFWriteTransferFunction(TIFF*, TIFFDirEntry*);
kusano 7d535a
#endif
kusano 7d535a
static	int TIFFWriteData(TIFF*, TIFFDirEntry*, char*);
kusano 7d535a
static	int TIFFLinkDirectory(TIFF*);
kusano 7d535a
kusano 7d535a
#define	WriteRationalPair(type, tag1, v1, tag2, v2) {		\
kusano 7d535a
	if (!TIFFWriteRational(tif, type, tag1, dir, v1))	\
kusano 7d535a
		goto bad;					\
kusano 7d535a
	if (!TIFFWriteRational(tif, type, tag2, dir+1, v2))	\
kusano 7d535a
		goto bad;					\
kusano 7d535a
	dir++;							\
kusano 7d535a
}
kusano 7d535a
#define	TIFFWriteRational(tif, type, tag, dir, v) \
kusano 7d535a
	TIFFWriteRationalArray((tif), (type), (tag), (dir), 1, &(v))
kusano 7d535a
#ifndef TIFFWriteRational
kusano 7d535a
static	int TIFFWriteRational(TIFF*,
kusano 7d535a
	    TIFFDataType, ttag_t, TIFFDirEntry*, float);
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
/* This function will write an entire directory to the disk, and return the
kusano 7d535a
   offset value indicating where in the file it wrote the beginning of the
kusano 7d535a
   directory structure. This is NOT the same as the offset value before
kusano 7d535a
   calling this function, because some of the fields may have caused various
kusano 7d535a
   data items to be written out BEFORE writing the directory structure.
kusano 7d535a
kusano 7d535a
   This code was basically written by ripping of the TIFFWriteDirectory() 
kusano 7d535a
   code and generalizing it, using RPS's TIFFWritePliIfd() code for
kusano 7d535a
   inspiration.  My original goal was to make this code general enough that
kusano 7d535a
   the original TIFFWriteDirectory() could be rewritten to just call this
kusano 7d535a
   function with the appropriate field and field-accessing arguments.
kusano 7d535a
kusano 7d535a
   However, now I realize that there's a lot of code that gets executed for
kusano 7d535a
   the main, standard TIFF directories that does not apply to special
kusano 7d535a
   private subdirectories, so such a reimplementation for the sake of
kusano 7d535a
   eliminating redundant or duplicate code is probably not possible,
kusano 7d535a
   unless we also pass in a Main flag to indiciate which type of handling
kusano 7d535a
   to do, which would be kind of a hack. I've marked those places where I
kusano 7d535a
   changed or ripped out code which would have to be re-inserted to
kusano 7d535a
   generalize this function. If it can be done in a clean and graceful way,
kusano 7d535a
   it would be a great way to generalize the TIFF library. Otherwise, I'll
kusano 7d535a
   just leave this code here where it duplicates but remains on top of and
kusano 7d535a
   hopefully mostly independent of the main TIFF library.
kusano 7d535a
kusano 7d535a
   The caller will probably want to free the sub directory structure after
kusano 7d535a
   returning from this call, since otherwise once written out, the user
kusano 7d535a
   is likely to forget about it and leave data lying around.
kusano 7d535a
*/
kusano 7d535a
toff_t
kusano 7d535a
TIFFWritePrivateDataSubDirectory(TIFF* tif,
kusano 7d535a
				 uint32 pdir_fieldsset[], int pdir_fields_last,
kusano 7d535a
				 TIFFFieldInfo *field_info,
kusano 7d535a
				 int (*getFieldFn)(TIFF *tif, ttag_t tag, ...))
kusano 7d535a
{
kusano 7d535a
	uint16 dircount;
kusano 7d535a
	uint32 diroff, nextdiroff;
kusano 7d535a
	ttag_t tag;
kusano 7d535a
	uint32 nfields;
kusano 7d535a
	tsize_t dirsize;
kusano 7d535a
	char* data;
kusano 7d535a
	TIFFDirEntry* dir;
kusano 7d535a
	u_long b, *fields, fields_size;
kusano 7d535a
	toff_t directory_offset;
kusano 7d535a
	TIFFFieldInfo* fip;
kusano 7d535a
kusano 7d535a
	/*
kusano 7d535a
	 * Deleted out all of the encoder flushing and such code from here -
kusano 7d535a
	 * not necessary for subdirectories.
kusano 7d535a
	 */
kusano 7d535a
kusano 7d535a
	/* Finish writing out any image data. */
kusano 7d535a
	TIFFFlushData(tif);
kusano 7d535a
kusano 7d535a
	/*
kusano 7d535a
	 * Size the directory so that we can calculate
kusano 7d535a
	 * offsets for the data items that aren't kept
kusano 7d535a
	 * in-place in each field.
kusano 7d535a
	 */
kusano 7d535a
	nfields = 0;
kusano 7d535a
	for (b = 0; b <= pdir_fields_last; b++)
kusano 7d535a
		if (FieldSet(pdir_fieldsset, b))
kusano 7d535a
			/* Deleted code to make size of first 4 tags 2
kusano 7d535a
			   instead of 1. */
kusano 7d535a
			nfields += 1;
kusano 7d535a
	dirsize = nfields * sizeof (TIFFDirEntry);
kusano 7d535a
	data = (char*) _TIFFmalloc(dirsize);
kusano 7d535a
	if (data == NULL) {
kusano 7d535a
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
kusano 7d535a
		    "Cannot write private subdirectory, out of space");
kusano 7d535a
		return (0);
kusano 7d535a
	}
kusano 7d535a
	/*
kusano 7d535a
	 * Place directory in data section of the file. If there isn't one
kusano 7d535a
	 * yet, place it at the end of the file. The directory is treated as
kusano 7d535a
	 * data, so we don't link it into the directory structure at all.
kusano 7d535a
	 */
kusano 7d535a
	if (tif->tif_dataoff == 0)
kusano 7d535a
	    tif->tif_dataoff =(TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1;
kusano 7d535a
	diroff = tif->tif_dataoff;
kusano 7d535a
	tif->tif_dataoff = (toff_t)(
kusano 7d535a
	    diroff + sizeof (uint16) + dirsize + sizeof (toff_t));
kusano 7d535a
	if (tif->tif_dataoff & 1)
kusano 7d535a
		tif->tif_dataoff++;
kusano 7d535a
	(void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET);
kusano 7d535a
	/*tif->tif_curdir++;*/
kusano 7d535a
	dir = (TIFFDirEntry*) data;
kusano 7d535a
	/*
kusano 7d535a
	 * Setup external form of directory
kusano 7d535a
	 * entries and write data items.
kusano 7d535a
	 */
kusano 7d535a
	/*
kusano 7d535a
	 * We make a local copy of the fieldsset here so that we don't mess
kusano 7d535a
	 * up the original one when we call ResetFieldBit(). But I'm not sure
kusano 7d535a
	 * why the original code calls ResetFieldBit(), since we're already
kusano 7d535a
	 * going through the fields in order...
kusano 7d535a
	 *
kusano 7d535a
	 * fields_size is the number of uint32's we will need to hold the
kusano 7d535a
	 * bit-mask for all of the fields. If our highest field number is
kusano 7d535a
	 * 100, then we'll need 100 / (8*4)+1 == 4 uint32's to hold the
kusano 7d535a
	 * fieldset.
kusano 7d535a
	 *
kusano 7d535a
	 * Unlike the original code, we allocate fields dynamically based
kusano 7d535a
	 * on the requested pdir_fields_last value, allowing private
kusano 7d535a
	 * data subdirectories to contain more than the built-in code's limit
kusano 7d535a
	 * of 95 tags in a directory.
kusano 7d535a
	 */
kusano 7d535a
	fields_size = pdir_fields_last / (8*sizeof(uint32)) + 1;
kusano 7d535a
	fields = _TIFFmalloc(fields_size*sizeof(uint32));
kusano 7d535a
	_TIFFmemcpy(fields, pdir_fieldsset, fields_size * sizeof(uint32));
kusano 7d535a
kusano 7d535a
	/* Deleted "write out extra samples tag" code here. */
kusano 7d535a
kusano 7d535a
	/* Deleted code for checking a billion little special cases for the
kusano 7d535a
	 * standard TIFF tags. Should add a general mechanism for overloading
kusano 7d535a
	 * write function for each field, just like Brian kept telling me!!!
kusano 7d535a
	 */
kusano 7d535a
	for (fip = field_info; fip->field_tag; fip++) {
kusano 7d535a
		/* Deleted code to check for FIELD_IGNORE!! */
kusano 7d535a
		if (/* fip->field_bit == FIELD_IGNORE || */
kusano 7d535a
		    !FieldSet(fields, fip->field_bit))
kusano 7d535a
			continue;
kusano 7d535a
		if (!TIFFWriteNormalSubTag(tif, dir, fip, getFieldFn))
kusano 7d535a
			goto bad;
kusano 7d535a
		dir++;
kusano 7d535a
		ResetFieldBit(fields, fip->field_bit);
kusano 7d535a
	}
kusano 7d535a
kusano 7d535a
	/* Now we've written all of the referenced data, and are about to
kusano 7d535a
	   write the main directory structure, so grab the tif_dataoff value
kusano 7d535a
	   now so we can remember where we wrote the directory. */
kusano 7d535a
	directory_offset = tif->tif_dataoff;
kusano 7d535a
kusano 7d535a
	/*
kusano 7d535a
	 * Write directory.
kusano 7d535a
	 */
kusano 7d535a
	dircount = (uint16) nfields;
kusano 7d535a
	/* Deleted code to link to the next directory - we set it to zero! */
kusano 7d535a
	nextdiroff = 0;
kusano 7d535a
	if (tif->tif_flags & TIFF_SWAB) {
kusano 7d535a
		/*
kusano 7d535a
		 * The file's byte order is opposite to the
kusano 7d535a
		 * native machine architecture.  We overwrite
kusano 7d535a
		 * the directory information with impunity
kusano 7d535a
		 * because it'll be released below after we
kusano 7d535a
		 * write it to the file.  Note that all the
kusano 7d535a
		 * other tag construction routines assume that
kusano 7d535a
		 * we do this byte-swapping; i.e. they only
kusano 7d535a
		 * byte-swap indirect data.
kusano 7d535a
		 */
kusano 7d535a
		for (dir = (TIFFDirEntry*) data; dircount; dir++, dircount--) {
kusano 7d535a
			TIFFSwabArrayOfShort(&dir->tdir_tag, 2);
kusano 7d535a
			TIFFSwabArrayOfLong(&dir->tdir_count, 2);
kusano 7d535a
		}
kusano 7d535a
		dircount = (uint16) nfields;
kusano 7d535a
		TIFFSwabShort(&dircount);
kusano 7d535a
		TIFFSwabLong(&nextdiroff);
kusano 7d535a
	}
kusano 7d535a
kusano 7d535a
	(void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET);
kusano 7d535a
	if (!WriteOK(tif, &dircount, sizeof (dircount))) {
kusano 7d535a
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing private subdirectory count");
kusano 7d535a
		goto bad;
kusano 7d535a
	}
kusano 7d535a
	if (!WriteOK(tif, data, dirsize)) {
kusano 7d535a
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing private subdirectory contents");
kusano 7d535a
		goto bad;
kusano 7d535a
	}
kusano 7d535a
	if (!WriteOK(tif, &nextdiroff, sizeof (nextdiroff))) {
kusano 7d535a
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing private subdirectory link");
kusano 7d535a
		goto bad;
kusano 7d535a
	}
kusano 7d535a
	tif->tif_dataoff += sizeof(dircount) + dirsize + sizeof(nextdiroff);
kusano 7d535a
kusano 7d535a
	_TIFFfree(data);
kusano 7d535a
	_TIFFfree(fields);
kusano 7d535a
	tif->tif_flags &= ~TIFF_DIRTYDIRECT;
kusano 7d535a
kusano 7d535a
#if (0)
kusano 7d535a
	/* This stuff commented out because I don't think we want it for
kusano 7d535a
	   subdirectories, but I could be wrong. */
kusano 7d535a
	(*tif->tif_cleanup)(tif);
kusano 7d535a
kusano 7d535a
	/*
kusano 7d535a
	 * Reset directory-related state for subsequent
kusano 7d535a
	 * directories.
kusano 7d535a
	 */
kusano 7d535a
	TIFFDefaultDirectory(tif);
kusano 7d535a
	tif->tif_curoff = 0;
kusano 7d535a
	tif->tif_row = (uint32) -1;
kusano 7d535a
	tif->tif_curstrip = (tstrip_t) -1;
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
	return (directory_offset);
kusano 7d535a
bad:
kusano 7d535a
	_TIFFfree(data);
kusano 7d535a
	_TIFFfree(fields);
kusano 7d535a
	return (0);
kusano 7d535a
}
kusano 7d535a
#undef WriteRationalPair
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Process tags that are not special cased.
kusano 7d535a
 */
kusano 7d535a
/* The standard function TIFFWriteNormalTag() could definitely be replaced
kusano 7d535a
   with a simple call to this function, just adding TIFFGetField() as the
kusano 7d535a
   last argument. */
kusano 7d535a
static int
kusano 7d535a
TIFFWriteNormalSubTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip,
kusano 7d535a
		      int (*getFieldFn)(TIFF *tif, ttag_t tag, ...))
kusano 7d535a
{
kusano 7d535a
	u_short wc = (u_short) fip->field_writecount;
kusano 7d535a
kusano 7d535a
	dir->tdir_tag = fip->field_tag;
kusano 7d535a
	dir->tdir_type = (u_short) fip->field_type;
kusano 7d535a
	dir->tdir_count = wc;
kusano 7d535a
#define	WRITEF(x,y)	x(tif, fip->field_type, fip->field_tag, dir, wc, y)
kusano 7d535a
	switch (fip->field_type) {
kusano 7d535a
	case TIFF_SHORT:
kusano 7d535a
	case TIFF_SSHORT:
kusano 7d535a
		if (wc > 1) {
kusano 7d535a
			uint16* wp;
kusano 7d535a
			if (wc == (u_short) TIFF_VARIABLE) {
kusano 7d535a
				(*getFieldFn)(tif, fip->field_tag, &wc, &wp);
kusano 7d535a
				dir->tdir_count = wc;
kusano 7d535a
			} else
kusano 7d535a
				(*getFieldFn)(tif, fip->field_tag, &wp);
kusano 7d535a
			if (!WRITEF(TIFFWriteShortArray, wp))
kusano 7d535a
				return (0);
kusano 7d535a
		} else {
kusano 7d535a
			uint16 sv;
kusano 7d535a
			(*getFieldFn)(tif, fip->field_tag, &sv);
kusano 7d535a
			dir->tdir_offset =
kusano 7d535a
			    TIFFInsertData(tif, dir->tdir_type, sv);
kusano 7d535a
		}
kusano 7d535a
		break;
kusano 7d535a
	case TIFF_LONG:
kusano 7d535a
	case TIFF_SLONG:
kusano 7d535a
		if (wc > 1) {
kusano 7d535a
			uint32* lp;
kusano 7d535a
			if (wc == (u_short) TIFF_VARIABLE) {
kusano 7d535a
				(*getFieldFn)(tif, fip->field_tag, &wc, &lp);
kusano 7d535a
				dir->tdir_count = wc;
kusano 7d535a
			} else
kusano 7d535a
				(*getFieldFn)(tif, fip->field_tag, &lp);
kusano 7d535a
			if (!WRITEF(TIFFWriteLongArray, lp))
kusano 7d535a
				return (0);
kusano 7d535a
		} else {
kusano 7d535a
			/* XXX handle LONG->SHORT conversion */
kusano 7d535a
			(*getFieldFn)(tif, fip->field_tag, &dir->tdir_offset);
kusano 7d535a
		}
kusano 7d535a
		break;
kusano 7d535a
	case TIFF_RATIONAL:
kusano 7d535a
	case TIFF_SRATIONAL:
kusano 7d535a
		if (wc > 1) {
kusano 7d535a
			float* fp;
kusano 7d535a
			if (wc == (u_short) TIFF_VARIABLE) {
kusano 7d535a
				(*getFieldFn)(tif, fip->field_tag, &wc, &fp);
kusano 7d535a
				dir->tdir_count = wc;
kusano 7d535a
			} else
kusano 7d535a
				(*getFieldFn)(tif, fip->field_tag, &fp);
kusano 7d535a
			if (!WRITEF(TIFFWriteRationalArray, fp))
kusano 7d535a
				return (0);
kusano 7d535a
		} else {
kusano 7d535a
			float fv;
kusano 7d535a
			(*getFieldFn)(tif, fip->field_tag, &fv);
kusano 7d535a
			if (!WRITEF(TIFFWriteRationalArray, &fv))
kusano 7d535a
				return (0);
kusano 7d535a
		}
kusano 7d535a
		break;
kusano 7d535a
	case TIFF_FLOAT:
kusano 7d535a
		if (wc > 1) {
kusano 7d535a
			float* fp;
kusano 7d535a
			if (wc == (u_short) TIFF_VARIABLE) {
kusano 7d535a
				(*getFieldFn)(tif, fip->field_tag, &wc, &fp);
kusano 7d535a
				dir->tdir_count = wc;
kusano 7d535a
			} else
kusano 7d535a
				(*getFieldFn)(tif, fip->field_tag, &fp);
kusano 7d535a
			if (!WRITEF(TIFFWriteFloatArray, fp))
kusano 7d535a
				return (0);
kusano 7d535a
		} else {
kusano 7d535a
			float fv;
kusano 7d535a
			(*getFieldFn)(tif, fip->field_tag, &fv);
kusano 7d535a
			if (!WRITEF(TIFFWriteFloatArray, &fv))
kusano 7d535a
				return (0);
kusano 7d535a
		}
kusano 7d535a
		break;
kusano 7d535a
	case TIFF_DOUBLE:
kusano 7d535a
		/* Hey - I think this is a bug, or at least a "gross
kusano 7d535a
		   inconsistency", in the TIFF library. Look at the original
kusano 7d535a
		   TIFF library code below within the "#if (0) ... #else".
kusano 7d535a
		   Just from the type of *dp, you can see that this code
kusano 7d535a
		   expects TIFFGetField() to be handed a double ** for
kusano 7d535a
		   any TIFF_DOUBLE tag, even for the constant wc==1 case.
kusano 7d535a
		   This is totally inconsistent with other fields (like
kusano 7d535a
		   TIFF_FLOAT, above) and is also inconsistent with the
kusano 7d535a
		   TIFFSetField() function for TIFF_DOUBLEs, which expects
kusano 7d535a
		   to be passed a single double by value for the wc==1 case.
kusano 7d535a
		   (See the handling of TIFFFetchNormalTag() in tif_dirread.c
kusano 7d535a
		   for an example.) Maybe this function was written before
kusano 7d535a
		   TIFFWriteDoubleArray() was written, not that that's an
kusano 7d535a
		   excuse. Anyway, the new code below is a trivial modification
kusano 7d535a
		   of the TIFF_FLOAT code above. The fact that even single
kusano 7d535a
		   doubles get written out in the data segment and get an
kusano 7d535a
		   offset value stored is irrelevant here - that is all
kusano 7d535a
		   handled by TIFFWriteDoubleArray(). */
kusano 7d535a
#if (0)
kusano 7d535a
		{ double* dp;
kusano 7d535a
		  if (wc == (u_short) TIFF_VARIABLE) {
kusano 7d535a
			(*getFieldFn)(tif, fip->field_tag, &wc, &dp);
kusano 7d535a
			dir->tdir_count = wc;
kusano 7d535a
		  } else
kusano 7d535a
			(*getFieldFn)(tif, fip->field_tag, &dp);
kusano 7d535a
		  TIFFCvtNativeToIEEEDouble(tif, wc, dp);
kusano 7d535a
		  if (!TIFFWriteData(tif, dir, (char*) dp))
kusano 7d535a
			return (0);
kusano 7d535a
		}
kusano 7d535a
#else
kusano 7d535a
		if (wc > 1) {
kusano 7d535a
			double* dp;
kusano 7d535a
			if (wc == (u_short) TIFF_VARIABLE) {
kusano 7d535a
				(*getFieldFn)(tif, fip->field_tag, &wc, &dp);
kusano 7d535a
				dir->tdir_count = wc;
kusano 7d535a
			} else
kusano 7d535a
				(*getFieldFn)(tif, fip->field_tag, &dp);
kusano 7d535a
			if (!WRITEF(TIFFWriteDoubleArray, dp))
kusano 7d535a
				return (0);
kusano 7d535a
		} else {
kusano 7d535a
			double dv;
kusano 7d535a
			(*getFieldFn)(tif, fip->field_tag, &dv);
kusano 7d535a
			if (!WRITEF(TIFFWriteDoubleArray, &dv))
kusano 7d535a
				return (0);
kusano 7d535a
		}
kusano 7d535a
#endif
kusano 7d535a
		break;
kusano 7d535a
	case TIFF_ASCII:
kusano 7d535a
		{ char* cp;
kusano 7d535a
		  (*getFieldFn)(tif, fip->field_tag, &cp);
kusano 7d535a
		  dir->tdir_count = (uint32) (strlen(cp) + 1);
kusano 7d535a
		  if (!TIFFWriteByteArray(tif, dir, cp))
kusano 7d535a
			return (0);
kusano 7d535a
		}
kusano 7d535a
		break;
kusano 7d535a
	case TIFF_UNDEFINED:
kusano 7d535a
		{ char* cp;
kusano 7d535a
		  if (wc == (u_short) TIFF_VARIABLE) {
kusano 7d535a
			(*getFieldFn)(tif, fip->field_tag, &wc, &cp);
kusano 7d535a
			dir->tdir_count = wc;
kusano 7d535a
		  } else 
kusano 7d535a
			(*getFieldFn)(tif, fip->field_tag, &cp);
kusano 7d535a
		  if (!TIFFWriteByteArray(tif, dir, cp))
kusano 7d535a
			return (0);
kusano 7d535a
		}
kusano 7d535a
		break;
kusano 7d535a
	}
kusano 7d535a
	return (1);
kusano 7d535a
}
kusano 7d535a
#undef WRITEF
kusano 7d535a
kusano 7d535a
/* Everything after this is exactly duplicated from the standard tif_dirwrite.c
kusano 7d535a
   file, necessitated by the fact that they are declared static there so
kusano 7d535a
   we can't call them!
kusano 7d535a
*/
kusano 7d535a
/*
kusano 7d535a
 * Setup a directory entry with either a SHORT
kusano 7d535a
 * or LONG type according to the value.
kusano 7d535a
 */
kusano 7d535a
static void
kusano 7d535a
TIFFSetupShortLong(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint32 v)
kusano 7d535a
{
kusano 7d535a
	dir->tdir_tag = tag;
kusano 7d535a
	dir->tdir_count = 1;
kusano 7d535a
	if (v > 0xffffL) {
kusano 7d535a
		dir->tdir_type = (short) TIFF_LONG;
kusano 7d535a
		dir->tdir_offset = v;
kusano 7d535a
	} else {
kusano 7d535a
		dir->tdir_type = (short) TIFF_SHORT;
kusano 7d535a
		dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v);
kusano 7d535a
	}
kusano 7d535a
}
kusano 7d535a
#undef MakeShortDirent
kusano 7d535a
kusano 7d535a
#ifndef TIFFWriteRational
kusano 7d535a
/*
kusano 7d535a
 * Setup a RATIONAL directory entry and
kusano 7d535a
 * write the associated indirect value.
kusano 7d535a
 */
kusano 7d535a
static int
kusano 7d535a
TIFFWriteRational(TIFF* tif,
kusano 7d535a
    TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, float v)
kusano 7d535a
{
kusano 7d535a
	return (TIFFWriteRationalArray(tif, type, tag, dir, 1, &v));
kusano 7d535a
}
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
#define	NITEMS(x)	(sizeof (x) / sizeof (x[0]))
kusano 7d535a
/*
kusano 7d535a
 * Setup a directory entry that references a
kusano 7d535a
 * samples/pixel array of SHORT values and
kusano 7d535a
 * (potentially) write the associated indirect
kusano 7d535a
 * values.
kusano 7d535a
 */
kusano 7d535a
static int
kusano 7d535a
TIFFWritePerSampleShorts(TIFF* tif, ttag_t tag, TIFFDirEntry* dir)
kusano 7d535a
{
kusano 7d535a
	uint16 buf[10], v;
kusano 7d535a
	uint16* w = buf;
kusano 7d535a
	int i, status, samples = tif->tif_dir.td_samplesperpixel;
kusano 7d535a
kusano 7d535a
	if (samples > NITEMS(buf))
kusano 7d535a
		w = (uint16*) _TIFFmalloc(samples * sizeof (uint16));
kusano 7d535a
	TIFFGetField(tif, tag, &v);
kusano 7d535a
	for (i = 0; i < samples; i++)
kusano 7d535a
		w[i] = v;
kusano 7d535a
	status = TIFFWriteShortArray(tif, TIFF_SHORT, tag, dir, samples, w);
kusano 7d535a
	if (w != buf)
kusano 7d535a
		_TIFFfree((char*) w);
kusano 7d535a
	return (status);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Setup a directory entry that references a samples/pixel array of ``type''
kusano 7d535a
 * values and (potentially) write the associated indirect values.  The source
kusano 7d535a
 * data from TIFFGetField() for the specified tag must be returned as double.
kusano 7d535a
 */
kusano 7d535a
static int
kusano 7d535a
TIFFWritePerSampleAnys(TIFF* tif,
kusano 7d535a
    TIFFDataType type, ttag_t tag, TIFFDirEntry* dir)
kusano 7d535a
{
kusano 7d535a
	double buf[10], v;
kusano 7d535a
	double* w = buf;
kusano 7d535a
	int i, status;
kusano 7d535a
	int samples = (int) tif->tif_dir.td_samplesperpixel;
kusano 7d535a
kusano 7d535a
	if (samples > NITEMS(buf))
kusano 7d535a
		w = (double*) _TIFFmalloc(samples * sizeof (double));
kusano 7d535a
	TIFFGetField(tif, tag, &v);
kusano 7d535a
	for (i = 0; i < samples; i++)
kusano 7d535a
		w[i] = v;
kusano 7d535a
	status = TIFFWriteAnyArray(tif, type, tag, dir, samples, w);
kusano 7d535a
	if (w != buf)
kusano 7d535a
		_TIFFfree(w);
kusano 7d535a
	return (status);
kusano 7d535a
}
kusano 7d535a
#undef NITEMS
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Setup a pair of shorts that are returned by
kusano 7d535a
 * value, rather than as a reference to an array.
kusano 7d535a
 */
kusano 7d535a
static int
kusano 7d535a
TIFFSetupShortPair(TIFF* tif, ttag_t tag, TIFFDirEntry* dir)
kusano 7d535a
{
kusano 7d535a
	uint16 v[2];
kusano 7d535a
kusano 7d535a
	TIFFGetField(tif, tag, &v[0], &v[1]);
kusano 7d535a
	return (TIFFWriteShortArray(tif, TIFF_SHORT, tag, dir, 2, v));
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Setup a directory entry for an NxM table of shorts,
kusano 7d535a
 * where M is known to be 2**bitspersample, and write
kusano 7d535a
 * the associated indirect data.
kusano 7d535a
 */
kusano 7d535a
static int
kusano 7d535a
TIFFWriteShortTable(TIFF* tif,
kusano 7d535a
    ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16** table)
kusano 7d535a
{
kusano 7d535a
	uint32 i, off;
kusano 7d535a
kusano 7d535a
	dir->tdir_tag = tag;
kusano 7d535a
	dir->tdir_type = (short) TIFF_SHORT;
kusano 7d535a
	/* XXX -- yech, fool TIFFWriteData */
kusano 7d535a
	dir->tdir_count = (uint32) (1L<<tif->tif_dir.td_bitspersample);</tif->
kusano 7d535a
	off = tif->tif_dataoff;
kusano 7d535a
	for (i = 0; i < n; i++)
kusano 7d535a
		if (!TIFFWriteData(tif, dir, (char *)table[i]))
kusano 7d535a
			return (0);
kusano 7d535a
	dir->tdir_count *= n;
kusano 7d535a
	dir->tdir_offset = off;
kusano 7d535a
	return (1);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Write/copy data associated with an ASCII or opaque tag value.
kusano 7d535a
 */
kusano 7d535a
static int
kusano 7d535a
TIFFWriteByteArray(TIFF* tif, TIFFDirEntry* dir, char* cp)
kusano 7d535a
{
kusano 7d535a
	if (dir->tdir_count > 4) {
kusano 7d535a
		if (!TIFFWriteData(tif, dir, cp))
kusano 7d535a
			return (0);
kusano 7d535a
	} else
kusano 7d535a
		_TIFFmemcpy(&dir->tdir_offset, cp, dir->tdir_count);
kusano 7d535a
	return (1);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Setup a directory entry of an array of SHORT
kusano 7d535a
 * or SSHORT and write the associated indirect values.
kusano 7d535a
 */
kusano 7d535a
static int
kusano 7d535a
TIFFWriteShortArray(TIFF* tif,
kusano 7d535a
    TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16* v)
kusano 7d535a
{
kusano 7d535a
	dir->tdir_tag = tag;
kusano 7d535a
	dir->tdir_type = (short) type;
kusano 7d535a
	dir->tdir_count = n;
kusano 7d535a
	if (n <= 2) {
kusano 7d535a
		if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
kusano 7d535a
			dir->tdir_offset = (uint32) ((long) v[0] << 16);
kusano 7d535a
			if (n == 2)
kusano 7d535a
				dir->tdir_offset |= v[1] & 0xffff;
kusano 7d535a
		} else {
kusano 7d535a
			dir->tdir_offset = v[0] & 0xffff;
kusano 7d535a
			if (n == 2)
kusano 7d535a
				dir->tdir_offset |= (long) v[1] << 16;
kusano 7d535a
		}
kusano 7d535a
		return (1);
kusano 7d535a
	} else
kusano 7d535a
		return (TIFFWriteData(tif, dir, (char*) v));
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Setup a directory entry of an array of LONG
kusano 7d535a
 * or SLONG and write the associated indirect values.
kusano 7d535a
 */
kusano 7d535a
static int
kusano 7d535a
TIFFWriteLongArray(TIFF* tif,
kusano 7d535a
    TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, uint32* v)
kusano 7d535a
{
kusano 7d535a
	dir->tdir_tag = tag;
kusano 7d535a
	dir->tdir_type = (short) type;
kusano 7d535a
	dir->tdir_count = n;
kusano 7d535a
	if (n == 1) {
kusano 7d535a
		dir->tdir_offset = v[0];
kusano 7d535a
		return (1);
kusano 7d535a
	} else
kusano 7d535a
		return (TIFFWriteData(tif, dir, (char*) v));
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Setup a directory entry of an array of RATIONAL
kusano 7d535a
 * or SRATIONAL and write the associated indirect values.
kusano 7d535a
 */
kusano 7d535a
static int
kusano 7d535a
TIFFWriteRationalArray(TIFF* tif,
kusano 7d535a
    TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, float* v)
kusano 7d535a
{
kusano 7d535a
	uint32 i;
kusano 7d535a
	uint32* t;
kusano 7d535a
	int status;
kusano 7d535a
kusano 7d535a
	dir->tdir_tag = tag;
kusano 7d535a
	dir->tdir_type = (short) type;
kusano 7d535a
	dir->tdir_count = n;
kusano 7d535a
	t = (uint32*) _TIFFmalloc(2*n * sizeof (uint32));
kusano 7d535a
	for (i = 0; i < n; i++) {
kusano 7d535a
		float fv = v[i];
kusano 7d535a
		int sign = 1;
kusano 7d535a
		uint32 den;
kusano 7d535a
kusano 7d535a
		if (fv < 0) {
kusano 7d535a
			if (type == TIFF_RATIONAL) {
kusano 7d535a
				TIFFWarning(tif->tif_name,
kusano 7d535a
	"\"%s\": Information lost writing value (%g) as (unsigned) RATIONAL",
kusano 7d535a
				_TIFFFieldWithTag(tif,tag)->field_name, v);
kusano 7d535a
				fv = 0;
kusano 7d535a
			} else
kusano 7d535a
				fv = -fv, sign = -1;
kusano 7d535a
		}
kusano 7d535a
		den = 1L;
kusano 7d535a
		if (fv > 0) {
kusano 7d535a
			while (fv < 1L<<(31-3) && den < 1L<<(31-3))
kusano 7d535a
				fv *= 1<<3, den *= 1L<<3;
kusano 7d535a
		}
kusano 7d535a
		t[2*i+0] = sign * (fv + 0.5);
kusano 7d535a
		t[2*i+1] = den;
kusano 7d535a
	}
kusano 7d535a
	status = TIFFWriteData(tif, dir, (char *)t);
kusano 7d535a
	_TIFFfree((char*) t);
kusano 7d535a
	return (status);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static int
kusano 7d535a
TIFFWriteFloatArray(TIFF* tif,
kusano 7d535a
    TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, float* v)
kusano 7d535a
{
kusano 7d535a
	dir->tdir_tag = tag;
kusano 7d535a
	dir->tdir_type = (short) type;
kusano 7d535a
	dir->tdir_count = n;
kusano 7d535a
	TIFFCvtNativeToIEEEFloat(tif, n, v);
kusano 7d535a
	if (n == 1) {
kusano 7d535a
		dir->tdir_offset = *(uint32*) &v[0];
kusano 7d535a
		return (1);
kusano 7d535a
	} else
kusano 7d535a
		return (TIFFWriteData(tif, dir, (char*) v));
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static int
kusano 7d535a
TIFFWriteDoubleArray(TIFF* tif,
kusano 7d535a
    TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, double* v)
kusano 7d535a
{
kusano 7d535a
	dir->tdir_tag = tag;
kusano 7d535a
	dir->tdir_type = (short) type;
kusano 7d535a
	dir->tdir_count = n;
kusano 7d535a
	TIFFCvtNativeToIEEEDouble(tif, n, v);
kusano 7d535a
	return (TIFFWriteData(tif, dir, (char*) v));
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Write an array of ``type'' values for a specified tag (i.e. this is a tag
kusano 7d535a
 * which is allowed to have different types, e.g. SMaxSampleType).
kusano 7d535a
 * Internally the data values are represented as double since a double can
kusano 7d535a
 * hold any of the TIFF tag types (yes, this should really be an abstract
kusano 7d535a
 * type tany_t for portability).  The data is converted into the specified
kusano 7d535a
 * type in a temporary buffer and then handed off to the appropriate array
kusano 7d535a
 * writer.
kusano 7d535a
 */
kusano 7d535a
static int
kusano 7d535a
TIFFWriteAnyArray(TIFF* tif,
kusano 7d535a
    TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, double* v)
kusano 7d535a
{
kusano 7d535a
	char buf[10 * sizeof(double)];
kusano 7d535a
	char* w = buf;
kusano 7d535a
	int i, status = 0;
kusano 7d535a
kusano 7d535a
	if (n * TIFFDataWidth(type) > sizeof buf)
kusano 7d535a
		w = (char*) _TIFFmalloc(n * TIFFDataWidth(type));
kusano 7d535a
	switch (type) {
kusano 7d535a
	case TIFF_BYTE:
kusano 7d535a
		{ unsigned char* bp = (unsigned char*) w;
kusano 7d535a
		  for (i = 0; i < n; i++)
kusano 7d535a
			bp[i] = (unsigned char) v[i];
kusano 7d535a
		  dir->tdir_tag = tag;
kusano 7d535a
		  dir->tdir_type = (short) type;
kusano 7d535a
		  dir->tdir_count = n;
kusano 7d535a
		  if (!TIFFWriteByteArray(tif, dir, (char*) bp))
kusano 7d535a
			goto out;
kusano 7d535a
		}
kusano 7d535a
		break;
kusano 7d535a
	case TIFF_SBYTE:
kusano 7d535a
		{ signed char* bp = (signed char*) w;
kusano 7d535a
		  for (i = 0; i < n; i++)
kusano 7d535a
			bp[i] = (signed char) v[i];
kusano 7d535a
		  dir->tdir_tag = tag;
kusano 7d535a
		  dir->tdir_type = (short) type;
kusano 7d535a
		  dir->tdir_count = n;
kusano 7d535a
		  if (!TIFFWriteByteArray(tif, dir, (char*) bp))
kusano 7d535a
			goto out;
kusano 7d535a
		}
kusano 7d535a
		break;
kusano 7d535a
	case TIFF_SHORT:
kusano 7d535a
		{ uint16* bp = (uint16*) w;
kusano 7d535a
		  for (i = 0; i < n; i++)
kusano 7d535a
			bp[i] = (uint16) v[i];
kusano 7d535a
		  if (!TIFFWriteShortArray(tif, type, tag, dir, n, (uint16*)bp))
kusano 7d535a
				goto out;
kusano 7d535a
		}
kusano 7d535a
		break;
kusano 7d535a
	case TIFF_SSHORT:
kusano 7d535a
		{ int16* bp = (int16*) w;
kusano 7d535a
		  for (i = 0; i < n; i++)
kusano 7d535a
			bp[i] = (int16) v[i];
kusano 7d535a
		  if (!TIFFWriteShortArray(tif, type, tag, dir, n, (uint16*)bp))
kusano 7d535a
			goto out;
kusano 7d535a
		}
kusano 7d535a
		break;
kusano 7d535a
	case TIFF_LONG:
kusano 7d535a
		{ uint32* bp = (uint32*) w;
kusano 7d535a
		  for (i = 0; i < n; i++)
kusano 7d535a
			bp[i] = (uint32) v[i];
kusano 7d535a
		  if (!TIFFWriteLongArray(tif, type, tag, dir, n, bp))
kusano 7d535a
			goto out;
kusano 7d535a
		}
kusano 7d535a
		break;
kusano 7d535a
	case TIFF_SLONG:
kusano 7d535a
		{ int32* bp = (int32*) w;
kusano 7d535a
		  for (i = 0; i < n; i++)
kusano 7d535a
			bp[i] = (int32) v[i];
kusano 7d535a
		  if (!TIFFWriteLongArray(tif, type, tag, dir, n, (uint32*) bp))
kusano 7d535a
			goto out;
kusano 7d535a
		}
kusano 7d535a
		break;
kusano 7d535a
	case TIFF_FLOAT:
kusano 7d535a
		{ float* bp = (float*) w;
kusano 7d535a
		  for (i = 0; i < n; i++)
kusano 7d535a
			bp[i] = (float) v[i];
kusano 7d535a
		  if (!TIFFWriteFloatArray(tif, type, tag, dir, n, bp))
kusano 7d535a
			goto out;
kusano 7d535a
		}
kusano 7d535a
		break;
kusano 7d535a
	case TIFF_DOUBLE:
kusano 7d535a
		return (TIFFWriteDoubleArray(tif, type, tag, dir, n, v));
kusano 7d535a
	default:
kusano 7d535a
		/* TIFF_NOTYPE */
kusano 7d535a
		/* TIFF_ASCII */
kusano 7d535a
		/* TIFF_UNDEFINED */
kusano 7d535a
		/* TIFF_RATIONAL */
kusano 7d535a
		/* TIFF_SRATIONAL */
kusano 7d535a
		goto out;
kusano 7d535a
	}
kusano 7d535a
	status = 1;
kusano 7d535a
 out:
kusano 7d535a
	if (w != buf)
kusano 7d535a
		_TIFFfree(w);
kusano 7d535a
	return (status);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
#ifdef COLORIMETRY_SUPPORT
kusano 7d535a
static int
kusano 7d535a
TIFFWriteTransferFunction(TIFF* tif, TIFFDirEntry* dir)
kusano 7d535a
{
kusano 7d535a
	TIFFDirectory* td = &tif->tif_dir;
kusano 7d535a
	tsize_t n = (1L<<td->td_bitspersample) * sizeof (uint16);</td->
kusano 7d535a
	uint16** tf = td->td_transferfunction;
kusano 7d535a
	int ncols;
kusano 7d535a
kusano 7d535a
	/*
kusano 7d535a
	 * Check if the table can be written as a single column,
kusano 7d535a
	 * or if it must be written as 3 columns.  Note that we
kusano 7d535a
	 * write a 3-column tag if there are 2 samples/pixel and
kusano 7d535a
	 * a single column of data won't suffice--hmm.
kusano 7d535a
	 */
kusano 7d535a
	switch (td->td_samplesperpixel - td->td_extrasamples) {
kusano 7d535a
	default:	if (_TIFFmemcmp(tf[0], tf[2], n)) { ncols = 3; break; }
kusano 7d535a
	case 2:		if (_TIFFmemcmp(tf[0], tf[1], n)) { ncols = 3; break; }
kusano 7d535a
	case 1: case 0:	ncols = 1;
kusano 7d535a
	}
kusano 7d535a
	return (TIFFWriteShortTable(tif,
kusano 7d535a
	    TIFFTAG_TRANSFERFUNCTION, dir, ncols, tf));
kusano 7d535a
}
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Write a contiguous directory item.
kusano 7d535a
 */
kusano 7d535a
static int
kusano 7d535a
TIFFWriteData(TIFF* tif, TIFFDirEntry* dir, char* cp)
kusano 7d535a
{
kusano 7d535a
	tsize_t cc;
kusano 7d535a
kusano 7d535a
	if (tif->tif_flags & TIFF_SWAB) {
kusano 7d535a
		switch (dir->tdir_type) {
kusano 7d535a
		case TIFF_SHORT:
kusano 7d535a
		case TIFF_SSHORT:
kusano 7d535a
			TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count);
kusano 7d535a
			break;
kusano 7d535a
		case TIFF_LONG:
kusano 7d535a
		case TIFF_SLONG:
kusano 7d535a
		case TIFF_FLOAT:
kusano 7d535a
			TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count);
kusano 7d535a
			break;
kusano 7d535a
		case TIFF_RATIONAL:
kusano 7d535a
		case TIFF_SRATIONAL:
kusano 7d535a
			TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count);
kusano 7d535a
			break;
kusano 7d535a
		case TIFF_DOUBLE:
kusano 7d535a
			TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count);
kusano 7d535a
			break;
kusano 7d535a
		}
kusano 7d535a
	}
kusano 7d535a
	dir->tdir_offset = tif->tif_dataoff;
kusano 7d535a
	cc = dir->tdir_count * TIFFDataWidth(dir->tdir_type);
kusano 7d535a
	if (SeekOK(tif, dir->tdir_offset) &&
kusano 7d535a
	    WriteOK(tif, cp, cc)) {
kusano 7d535a
		tif->tif_dataoff += (cc + 1) & ~1;
kusano 7d535a
		return (1);
kusano 7d535a
	}
kusano 7d535a
	TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing data for field \"%s\"",
kusano 7d535a
	    _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
kusano 7d535a
	return (0);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Link the current directory into the
kusano 7d535a
 * directory chain for the file.
kusano 7d535a
 */
kusano 7d535a
static int
kusano 7d535a
TIFFLinkDirectory(TIFF* tif)
kusano 7d535a
{
kusano 7d535a
	static const char module[] = "TIFFLinkDirectory";
kusano 7d535a
	uint32 nextdir;
kusano 7d535a
	uint32 diroff;
kusano 7d535a
kusano 7d535a
	tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1;
kusano 7d535a
	diroff = (uint32) tif->tif_diroff;
kusano 7d535a
	if (tif->tif_flags & TIFF_SWAB)
kusano 7d535a
		TIFFSwabLong(&diroff);
kusano 7d535a
#if SUBIFD_SUPPORT
kusano 7d535a
	if (tif->tif_flags & TIFF_INSUBIFD) {
kusano 7d535a
		(void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET);
kusano 7d535a
		if (!WriteOK(tif, &diroff, sizeof (diroff))) {
kusano 7d535a
			TIFFErrorExt(tif->tif_clientdata, module,
kusano 7d535a
			    "%s: Error writing SubIFD directory link",
kusano 7d535a
			    tif->tif_name);
kusano 7d535a
			return (0);
kusano 7d535a
		}
kusano 7d535a
		/*
kusano 7d535a
		 * Advance to the next SubIFD or, if this is
kusano 7d535a
		 * the last one configured, revert back to the
kusano 7d535a
		 * normal directory linkage.
kusano 7d535a
		 */
kusano 7d535a
		if (--tif->tif_nsubifd)
kusano 7d535a
			tif->tif_subifdoff += sizeof (diroff);
kusano 7d535a
		else
kusano 7d535a
			tif->tif_flags &= ~TIFF_INSUBIFD;
kusano 7d535a
		return (1);
kusano 7d535a
	}
kusano 7d535a
#endif
kusano 7d535a
	if (tif->tif_header.tiff_diroff == 0) {
kusano 7d535a
		/*
kusano 7d535a
		 * First directory, overwrite offset in header.
kusano 7d535a
		 */
kusano 7d535a
		tif->tif_header.tiff_diroff = (uint32) tif->tif_diroff;
kusano 7d535a
#define	HDROFF(f)	((toff_t) &(((TIFFHeader*) 0)->f))
kusano 7d535a
		(void) TIFFSeekFile(tif, HDROFF(tiff_diroff), SEEK_SET);
kusano 7d535a
		if (!WriteOK(tif, &diroff, sizeof (diroff))) {
kusano 7d535a
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing TIFF header");
kusano 7d535a
			return (0);
kusano 7d535a
		}
kusano 7d535a
		return (1);
kusano 7d535a
	}
kusano 7d535a
	/*
kusano 7d535a
	 * Not the first directory, search to the last and append.
kusano 7d535a
	 */
kusano 7d535a
	nextdir = tif->tif_header.tiff_diroff;
kusano 7d535a
	do {
kusano 7d535a
		uint16 dircount;
kusano 7d535a
kusano 7d535a
		if (!SeekOK(tif, nextdir) ||
kusano 7d535a
		    !ReadOK(tif, &dircount, sizeof (dircount))) {
kusano 7d535a
			TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory count");
kusano 7d535a
			return (0);
kusano 7d535a
		}
kusano 7d535a
		if (tif->tif_flags & TIFF_SWAB)
kusano 7d535a
			TIFFSwabShort(&dircount);
kusano 7d535a
		(void) TIFFSeekFile(tif,
kusano 7d535a
		    dircount * sizeof (TIFFDirEntry), SEEK_CUR);
kusano 7d535a
		if (!ReadOK(tif, &nextdir, sizeof (nextdir))) {
kusano 7d535a
			TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory link");
kusano 7d535a
			return (0);
kusano 7d535a
		}
kusano 7d535a
		if (tif->tif_flags & TIFF_SWAB)
kusano 7d535a
			TIFFSwabLong(&nextdir);
kusano 7d535a
	} while (nextdir != 0);
kusano 7d535a
	(void) TIFFSeekFile(tif, -(toff_t) sizeof (nextdir), SEEK_CUR);
kusano 7d535a
	if (!WriteOK(tif, &diroff, sizeof (diroff))) {
kusano 7d535a
		TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link");
kusano 7d535a
		return (0);
kusano 7d535a
	}
kusano 7d535a
	return (1);
kusano 7d535a
}
kusano 7d535a
/*
kusano 7d535a
 * Local Variables:
kusano 7d535a
 * mode: c
kusano 7d535a
 * c-basic-offset: 8
kusano 7d535a
 * fill-column: 78
kusano 7d535a
 * End:
kusano 7d535a
 */