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