⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tif_pdsdirwrite.c

📁 非常详尽的传真编解码程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Header: /cvs/maptools/cvsroot/libtiff/contrib/pds/tif_pdsdirwrite.c,v 1.2 2003/11/17 15:09:39 dron Exp $ *//* When writing data to TIFF files, it is often useful to store application-   specific data in a private TIFF directory so that the tags don't need to   be registered and won't conflict with other people's user-defined tags.   One needs to have a registered public tag which contains some amount of   raw data. That raw data, however, is interpreted at an independent,   separate, private tiff directory. This file provides some routines which   will be useful for converting that data from its raw binary form into   the proper form for your application.*//* * Copyright (c) 1988-1996 Sam Leffler * Copyright (c) 1991-1996 Silicon Graphics, Inc. * Copyright (c( 1996 USAF Phillips Laboratory * * Permission to use, copy, modify, distribute, and sell this software and  * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. *  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.   *  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE  * OF THIS SOFTWARE. *//* * TIFF Library. * * These routines written by Conrad J. Poelman on a single late-night of * March 20-21, 1996. * * The entire purpose of this file is to provide a single external function, * TIFFWritePrivateDataSubDirectory(). This function is intended for use * in writing a private subdirectory structure into a TIFF file. The * actual reading of data from the structure is handled by the getFieldFn(), * which is passed to TIFFWritePrivateDataSubDirectory() as a parameter. The * idea is to enable any application wishing to read private subdirectories to * do so easily using this function, without modifying the TIFF library. * * The astute observer will notice that only two functions are at all different * from the original tif_dirwrite.c file: TIFFWritePrivateDataSubDirectory()and * TIFFWriteNormalSubTag(). All the other stuff that makes this file so huge * is only necessary because all of those functions are declared static in * tif_dirwrite.c, so we have to totally duplicate them in order to use them. * * Oh, also please note the bug-fix in the routine TIFFWriteNormalSubTag(), * which equally should be applied to TIFFWriteNormalTag(). * */#include "tiffiop.h"#if HAVE_IEEEFP#define	TIFFCvtNativeToIEEEFloat(tif, n, fp)#define	TIFFCvtNativeToIEEEDouble(tif, n, dp)#elseextern	void TIFFCvtNativeToIEEEFloat(TIFF*, uint32, float*);extern	void TIFFCvtNativeToIEEEDouble(TIFF*, uint32, double*);#endifstatic	int TIFFWriteNormalTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*);static	int TIFFWriteNormalSubTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*,				  int (*getFieldFn)(TIFF *tif,ttag_t tag,...));static	void TIFFSetupShortLong(TIFF*, ttag_t, TIFFDirEntry*, uint32);static	int TIFFSetupShortPair(TIFF*, ttag_t, TIFFDirEntry*);static	int TIFFWritePerSampleShorts(TIFF*, ttag_t, TIFFDirEntry*);static	int TIFFWritePerSampleAnys(TIFF*, TIFFDataType, ttag_t, TIFFDirEntry*);static	int TIFFWriteShortTable(TIFF*, ttag_t, TIFFDirEntry*, uint32, uint16**);static	int TIFFWriteShortArray(TIFF*,	    TIFFDataType, ttag_t, TIFFDirEntry*, uint32, uint16*);static	int TIFFWriteLongArray(TIFF *,	    TIFFDataType, ttag_t, TIFFDirEntry*, uint32, uint32*);static	int TIFFWriteRationalArray(TIFF *,	    TIFFDataType, ttag_t, TIFFDirEntry*, uint32, float*);static	int TIFFWriteFloatArray(TIFF *,	    TIFFDataType, ttag_t, TIFFDirEntry*, uint32, float*);static	int TIFFWriteDoubleArray(TIFF *,	    TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*);static	int TIFFWriteByteArray(TIFF*, TIFFDirEntry*, char*);static	int TIFFWriteAnyArray(TIFF*,	    TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*);#ifdef COLORIMETRY_SUPPORTstatic	int TIFFWriteTransferFunction(TIFF*, TIFFDirEntry*);#endifstatic	int TIFFWriteData(TIFF*, TIFFDirEntry*, char*);static	int TIFFLinkDirectory(TIFF*);#define	WriteRationalPair(type, tag1, v1, tag2, v2) {		\	if (!TIFFWriteRational(tif, type, tag1, dir, v1))	\		goto bad;					\	if (!TIFFWriteRational(tif, type, tag2, dir+1, v2))	\		goto bad;					\	dir++;							\}#define	TIFFWriteRational(tif, type, tag, dir, v) \	TIFFWriteRationalArray((tif), (type), (tag), (dir), 1, &(v))#ifndef TIFFWriteRationalstatic	int TIFFWriteRational(TIFF*,	    TIFFDataType, ttag_t, TIFFDirEntry*, float);#endif/* This function will write an entire directory to the disk, and return the   offset value indicating where in the file it wrote the beginning of the   directory structure. This is NOT the same as the offset value before   calling this function, because some of the fields may have caused various   data items to be written out BEFORE writing the directory structure.   This code was basically written by ripping of the TIFFWriteDirectory()    code and generalizing it, using RPS's TIFFWritePliIfd() code for   inspiration.  My original goal was to make this code general enough that   the original TIFFWriteDirectory() could be rewritten to just call this   function with the appropriate field and field-accessing arguments.   However, now I realize that there's a lot of code that gets executed for   the main, standard TIFF directories that does not apply to special   private subdirectories, so such a reimplementation for the sake of   eliminating redundant or duplicate code is probably not possible,   unless we also pass in a Main flag to indiciate which type of handling   to do, which would be kind of a hack. I've marked those places where I   changed or ripped out code which would have to be re-inserted to   generalize this function. If it can be done in a clean and graceful way,   it would be a great way to generalize the TIFF library. Otherwise, I'll   just leave this code here where it duplicates but remains on top of and   hopefully mostly independent of the main TIFF library.   The caller will probably want to free the sub directory structure after   returning from this call, since otherwise once written out, the user   is likely to forget about it and leave data lying around.*/toff_tTIFFWritePrivateDataSubDirectory(TIFF* tif,				 uint32 pdir_fieldsset[], int pdir_fields_last,				 TIFFFieldInfo *field_info,				 int (*getFieldFn)(TIFF *tif, ttag_t tag, ...)){	uint16 dircount;	uint32 diroff, nextdiroff;	ttag_t tag;	uint32 nfields;	tsize_t dirsize;	char* data;	TIFFDirEntry* dir;	u_long b, *fields, fields_size;	toff_t directory_offset;	TIFFFieldInfo* fip;	/*	 * Deleted out all of the encoder flushing and such code from here -	 * not necessary for subdirectories.	 */	/* Finish writing out any image data. */	TIFFFlushData(tif);	/*	 * Size the directory so that we can calculate	 * offsets for the data items that aren't kept	 * in-place in each field.	 */	nfields = 0;	for (b = 0; b <= pdir_fields_last; b++)		if (FieldSet(pdir_fieldsset, b))			/* Deleted code to make size of first 4 tags 2			   instead of 1. */			nfields += 1;	dirsize = nfields * sizeof (TIFFDirEntry);	data = (char*) _TIFFmalloc(dirsize);	if (data == NULL) {		TIFFError(tif->tif_name,		    "Cannot write private subdirectory, out of space");		return (0);	}	/*	 * Place directory in data section of the file. If there isn't one	 * yet, place it at the end of the file. The directory is treated as	 * data, so we don't link it into the directory structure at all.	 */	if (tif->tif_dataoff == 0)	    tif->tif_dataoff =(TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1;	diroff = tif->tif_dataoff;	tif->tif_dataoff = (toff_t)(	    diroff + sizeof (uint16) + dirsize + sizeof (toff_t));	if (tif->tif_dataoff & 1)		tif->tif_dataoff++;	(void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET);	/*tif->tif_curdir++;*/	dir = (TIFFDirEntry*) data;	/*	 * Setup external form of directory	 * entries and write data items.	 */	/*	 * We make a local copy of the fieldsset here so that we don't mess	 * up the original one when we call ResetFieldBit(). But I'm not sure	 * why the original code calls ResetFieldBit(), since we're already	 * going through the fields in order...	 *	 * fields_size is the number of uint32's we will need to hold the	 * bit-mask for all of the fields. If our highest field number is	 * 100, then we'll need 100 / (8*4)+1 == 4 uint32's to hold the	 * fieldset.	 *	 * Unlike the original code, we allocate fields dynamically based	 * on the requested pdir_fields_last value, allowing private	 * data subdirectories to contain more than the built-in code's limit	 * of 95 tags in a directory.	 */	fields_size = pdir_fields_last / (8*sizeof(uint32)) + 1;	fields = _TIFFmalloc(fields_size*sizeof(uint32));	_TIFFmemcpy(fields, pdir_fieldsset, fields_size * sizeof(uint32));	/* Deleted "write out extra samples tag" code here. */	/* Deleted code for checking a billion little special cases for the	 * standard TIFF tags. Should add a general mechanism for overloading	 * write function for each field, just like Brian kept telling me!!!	 */	for (fip = field_info; fip->field_tag; fip++) {		/* Deleted code to check for FIELD_IGNORE!! */		if (/* fip->field_bit == FIELD_IGNORE || */		    !FieldSet(fields, fip->field_bit))			continue;		if (!TIFFWriteNormalSubTag(tif, dir, fip, getFieldFn))			goto bad;		dir++;		ResetFieldBit(fields, fip->field_bit);	}	/* Now we've written all of the referenced data, and are about to	   write the main directory structure, so grab the tif_dataoff value	   now so we can remember where we wrote the directory. */	directory_offset = tif->tif_dataoff;	/*	 * Write directory.	 */	dircount = (uint16) nfields;	/* Deleted code to link to the next directory - we set it to zero! */	nextdiroff = 0;	if (tif->tif_flags & TIFF_SWAB) {		/*		 * The file's byte order is opposite to the		 * native machine architecture.  We overwrite		 * the directory information with impunity		 * because it'll be released below after we		 * write it to the file.  Note that all the		 * other tag construction routines assume that		 * we do this byte-swapping; i.e. they only		 * byte-swap indirect data.		 */		for (dir = (TIFFDirEntry*) data; dircount; dir++, dircount--) {			TIFFSwabArrayOfShort(&dir->tdir_tag, 2);			TIFFSwabArrayOfLong(&dir->tdir_count, 2);		}		dircount = (uint16) nfields;		TIFFSwabShort(&dircount);		TIFFSwabLong(&nextdiroff);	}	(void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET);	if (!WriteOK(tif, &dircount, sizeof (dircount))) {		TIFFError(tif->tif_name, "Error writing private subdirectory count");		goto bad;	}	if (!WriteOK(tif, data, dirsize)) {		TIFFError(tif->tif_name, "Error writing private subdirectory contents");		goto bad;	}	if (!WriteOK(tif, &nextdiroff, sizeof (nextdiroff))) {		TIFFError(tif->tif_name, "Error writing private subdirectory link");		goto bad;	}	tif->tif_dataoff += sizeof(dircount) + dirsize + sizeof(nextdiroff);	_TIFFfree(data);	_TIFFfree(fields);	tif->tif_flags &= ~TIFF_DIRTYDIRECT;#if (0)	/* This stuff commented out because I don't think we want it for	   subdirectories, but I could be wrong. */	(*tif->tif_cleanup)(tif);	/*	 * Reset directory-related state for subsequent	 * directories.	 */	TIFFDefaultDirectory(tif);	tif->tif_curoff = 0;	tif->tif_row = (uint32) -1;	tif->tif_curstrip = (tstrip_t) -1;#endif	return (directory_offset);bad:	_TIFFfree(data);	_TIFFfree(fields);	return (0);}#undef WriteRationalPair/* * Process tags that are not special cased. *//* The standard function TIFFWriteNormalTag() could definitely be replaced   with a simple call to this function, just adding TIFFGetField() as the   last argument. */static intTIFFWriteNormalSubTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip,		      int (*getFieldFn)(TIFF *tif, ttag_t tag, ...)){	u_short wc = (u_short) fip->field_writecount;	dir->tdir_tag = fip->field_tag;	dir->tdir_type = (u_short) fip->field_type;	dir->tdir_count = wc;#define	WRITEF(x,y)	x(tif, fip->field_type, fip->field_tag, dir, wc, y)	switch (fip->field_type) {	case TIFF_SHORT:	case TIFF_SSHORT:		if (wc > 1) {			uint16* wp;			if (wc == (u_short) TIFF_VARIABLE) {				(*getFieldFn)(tif, fip->field_tag, &wc, &wp);				dir->tdir_count = wc;			} else				(*getFieldFn)(tif, fip->field_tag, &wp);			if (!WRITEF(TIFFWriteShortArray, wp))				return (0);		} else {			uint16 sv;			(*getFieldFn)(tif, fip->field_tag, &sv);			dir->tdir_offset =			    TIFFInsertData(tif, dir->tdir_type, sv);		}		break;	case TIFF_LONG:	case TIFF_SLONG:		if (wc > 1) {			uint32* lp;			if (wc == (u_short) TIFF_VARIABLE) {				(*getFieldFn)(tif, fip->field_tag, &wc, &lp);				dir->tdir_count = wc;			} else				(*getFieldFn)(tif, fip->field_tag, &lp);			if (!WRITEF(TIFFWriteLongArray, lp))				return (0);		} else {			/* XXX handle LONG->SHORT conversion */			(*getFieldFn)(tif, fip->field_tag, &dir->tdir_offset);		}		break;	case TIFF_RATIONAL:	case TIFF_SRATIONAL:		if (wc > 1) {			float* fp;			if (wc == (u_short) TIFF_VARIABLE) {				(*getFieldFn)(tif, fip->field_tag, &wc, &fp);				dir->tdir_count = wc;			} else				(*getFieldFn)(tif, fip->field_tag, &fp);			if (!WRITEF(TIFFWriteRationalArray, fp))				return (0);		} else {			float fv;			(*getFieldFn)(tif, fip->field_tag, &fv);			if (!WRITEF(TIFFWriteRationalArray, &fv))				return (0);		}		break;	case TIFF_FLOAT:		if (wc > 1) {			float* fp;			if (wc == (u_short) TIFF_VARIABLE) {				(*getFieldFn)(tif, fip->field_tag, &wc, &fp);				dir->tdir_count = wc;			} else				(*getFieldFn)(tif, fip->field_tag, &fp);			if (!WRITEF(TIFFWriteFloatArray, fp))				return (0);		} else {			float fv;			(*getFieldFn)(tif, fip->field_tag, &fv);			if (!WRITEF(TIFFWriteFloatArray, &fv))				return (0);		}		break;	case TIFF_DOUBLE:		/* Hey - I think this is a bug, or at least a "gross		   inconsistency", in the TIFF library. Look at the original		   TIFF library code below within the "#if (0) ... #else".		   Just from the type of *dp, you can see that this code		   expects TIFFGetField() to be handed a double ** for		   any TIFF_DOUBLE tag, even for the constant wc==1 case.		   This is totally inconsistent with other fields (like		   TIFF_FLOAT, above) and is also inconsistent with the		   TIFFSetField() function for TIFF_DOUBLEs, which expects		   to be passed a single double by value for the wc==1 case.		   (See the handling of TIFFFetchNormalTag() in tif_dirread.c		   for an example.) Maybe this function was written before		   TIFFWriteDoubleArray() was written, not that that's an		   excuse. Anyway, the new code below is a trivial modification		   of the TIFF_FLOAT code above. The fact that even single		   doubles get written out in the data segment and get an		   offset value stored is irrelevant here - that is all		   handled by TIFFWriteDoubleArray(). */#if (0)		{ double* dp;		  if (wc == (u_short) TIFF_VARIABLE) {			(*getFieldFn)(tif, fip->field_tag, &wc, &dp);			dir->tdir_count = wc;		  } else			(*getFieldFn)(tif, fip->field_tag, &dp);		  TIFFCvtNativeToIEEEDouble(tif, wc, dp);		  if (!TIFFWriteData(tif, dir, (char*) dp))			return (0);		}#else		if (wc > 1) {			double* dp;			if (wc == (u_short) TIFF_VARIABLE) {				(*getFieldFn)(tif, fip->field_tag, &wc, &dp);				dir->tdir_count = wc;			} else				(*getFieldFn)(tif, fip->field_tag, &dp);			if (!WRITEF(TIFFWriteDoubleArray, dp))				return (0);		} else {			double dv;			(*getFieldFn)(tif, fip->field_tag, &dv);			if (!WRITEF(TIFFWriteDoubleArray, &dv))				return (0);		}#endif		break;	case TIFF_ASCII:		{ char* cp;		  (*getFieldFn)(tif, fip->field_tag, &cp);		  dir->tdir_count = (uint32) (strlen(cp) + 1);		  if (!TIFFWriteByteArray(tif, dir, cp))			return (0);		}		break;	case TIFF_UNDEFINED:		{ char* cp;		  if (wc == (u_short) TIFF_VARIABLE) {			(*getFieldFn)(tif, fip->field_tag, &wc, &cp);			dir->tdir_count = wc;		  } else 			(*getFieldFn)(tif, fip->field_tag, &cp);		  if (!TIFFWriteByteArray(tif, dir, cp))			return (0);		}		break;	}	return (1);}#undef WRITEF/* Everything after this is exactly duplicated from the standard tif_dirwrite.c   file, necessitated by the fact that they are declared static there so   we can't call them!*//* * Setup a directory entry with either a SHORT * or LONG type according to the value. */static voidTIFFSetupShortLong(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint32 v){	dir->tdir_tag = tag;	dir->tdir_count = 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -