예제 #1
0
int 
TIFFRewriteDirectory( TIFF *tif )
{
    static const char module[] = "TIFFRewriteDirectory";

    /* We don't need to do anything special if it hasn't been written. */
    if( tif->tif_diroff == 0 )
        return TIFFWriteDirectory( tif );

    /*
    ** Find and zero the pointer to this directory, so that TIFFLinkDirectory
    ** will cause it to be added after this directories current pre-link.
    */
    
    /* Is it the first directory in the file? */
    if (tif->tif_header.tiff_diroff == tif->tif_diroff) 
    {
        tif->tif_header.tiff_diroff = 0;
        tif->tif_diroff = 0;

        TIFFSeekFile(tif, (toff_t)(TIFF_MAGIC_SIZE+TIFF_VERSION_SIZE),
		     SEEK_SET);
        if (!WriteOK(tif, &(tif->tif_header.tiff_diroff), 
                     sizeof (tif->tif_diroff))) 
        {
            TIFFError(tif->tif_name, "Error updating TIFF header");
            return (0);
        }
    }
    else
    {
        toff_t  nextdir, off;

	nextdir = tif->tif_header.tiff_diroff;
	do {
		uint16 dircount;

		if (!SeekOK(tif, nextdir) ||
		    !ReadOK(tif, &dircount, sizeof (dircount))) {
			TIFFError(module, "Error fetching directory count");
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&dircount);
		(void) TIFFSeekFile(tif,
		    dircount * sizeof (TIFFDirEntry), SEEK_CUR);
		if (!ReadOK(tif, &nextdir, sizeof (nextdir))) {
			TIFFError(module, "Error fetching directory link");
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabLong(&nextdir);
	} while (nextdir != tif->tif_diroff && nextdir != 0);
        off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */
        (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET);
        tif->tif_diroff = 0;
	if (!WriteOK(tif, &(tif->tif_diroff), sizeof (nextdir))) {
		TIFFError(module, "Error writing directory link");
		return (0);
	}
    }

    /*
    ** Now use TIFFWriteDirectory() normally.
    */

    return TIFFWriteDirectory( tif );
}
예제 #2
0
/*
 * Link the current directory into the
 * directory chain for the file.
 */
static int
TIFFLinkDirectory(TIFF* tif)
{
	static const char module[] = "TIFFLinkDirectory";
	toff_t nextdir;
	toff_t diroff, off;

	tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1;
	diroff = tif->tif_diroff;
	if (tif->tif_flags & TIFF_SWAB)
		TIFFSwabLong(&diroff);
#if SUBIFD_SUPPORT
	if (tif->tif_flags & TIFF_INSUBIFD) {
		(void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET);
		if (!WriteOK(tif, &diroff, sizeof (diroff))) {
			TIFFError(module,
			    "%s: Error writing SubIFD directory link",
			    tif->tif_name);
			return (0);
		}
		/*
		 * Advance to the next SubIFD or, if this is
		 * the last one configured, revert back to the
		 * normal directory linkage.
		 */
		if (--tif->tif_nsubifd)
			tif->tif_subifdoff += sizeof (diroff);
		else
			tif->tif_flags &= ~TIFF_INSUBIFD;
		return (1);
	}
#endif
	if (tif->tif_header.tiff_diroff == 0) {
		/*
		 * First directory, overwrite offset in header.
		 */
		tif->tif_header.tiff_diroff = tif->tif_diroff;
#define	HDROFF(f)	((toff_t) &(((TIFFHeader*) 0)->f))
		(void) TIFFSeekFile(tif, HDROFF(tiff_diroff), SEEK_SET);
		if (!WriteOK(tif, &diroff, sizeof (diroff))) {
			TIFFError(tif->tif_name, "Error writing TIFF header");
			return (0);
		}
		return (1);
	}
	/*
	 * Not the first directory, search to the last and append.
	 */
	nextdir = tif->tif_header.tiff_diroff;
	do {
		uint16 dircount;

		if (!SeekOK(tif, nextdir) ||
		    !ReadOK(tif, &dircount, sizeof (dircount))) {
			TIFFError(module, "Error fetching directory count");
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&dircount);
		(void) TIFFSeekFile(tif,
		    dircount * sizeof (TIFFDirEntry), SEEK_CUR);
		if (!ReadOK(tif, &nextdir, sizeof (nextdir))) {
			TIFFError(module, "Error fetching directory link");
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabLong(&nextdir);
	} while (nextdir != 0);
        off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */
        (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET);
	if (!WriteOK(tif, &diroff, sizeof (diroff))) {
		TIFFError(module, "Error writing directory link");
		return (0);
	}
	return (1);
}
예제 #3
0
/*
 * Write the contents of the current directory
 * to the specified file.  This routine doesn't
 * handle overwriting a directory with auxiliary
 * storage that's been changed.
 */
static int
_TIFFWriteDirectory(TIFF* tif, int done)
{
	uint16 dircount;
	toff_t diroff;
	ttag_t tag;
	uint32 nfields;
	tsize_t dirsize;
	char* data;
	TIFFDirEntry* dir;
	TIFFDirectory* td;
	u_long b, fields[FIELD_SETLONGS];
	int fi, nfi;

	if (tif->tif_mode == O_RDONLY)
		return (1);
	/*
	 * Clear write state so that subsequent images with
	 * different characteristics get the right buffers
	 * setup for them.
	 */
	if (done)
	{
	    if (tif->tif_flags & TIFF_POSTENCODE) {
		    tif->tif_flags &= ~TIFF_POSTENCODE;
		    if (!(*tif->tif_postencode)(tif)) {
			    TIFFError(tif->tif_name,
				"Error post-encoding before directory write");
			    return (0);
		    }
	    }
	    (*tif->tif_close)(tif);		/* shutdown encoder */
	    /*
	     * Flush any data that might have been written
	     * by the compression close+cleanup routines.
	     */
	    if (tif->tif_rawcc > 0 && !TIFFFlushData1(tif)) {
		    TIFFError(tif->tif_name,
			"Error flushing data before directory write");
		    return (0);
	    }
	    if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) {
		    _TIFFfree(tif->tif_rawdata);
		    tif->tif_rawdata = NULL;
		    tif->tif_rawcc = 0;
		    tif->tif_rawdatasize = 0;
	    }
	    tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP);
	}

	td = &tif->tif_dir;
	/*
	 * 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 <= FIELD_LAST; b++)
		if (TIFFFieldSet(tif, b) && b != FIELD_CUSTOM)
			nfields += (b < FIELD_SUBFILETYPE ? 2 : 1);
        nfields += td->td_customValueCount;
	dirsize = nfields * sizeof (TIFFDirEntry);
	data = (char*) _TIFFmalloc(dirsize);
	if (data == NULL) {
		TIFFError(tif->tif_name,
		    "Cannot write directory, out of space");
		return (0);
	}
	/*
	 * Directory hasn't been placed yet, put
	 * it at the end of the file and link it
	 * into the existing directory structure.
	 */
	if (tif->tif_diroff == 0 && !TIFFLinkDirectory(tif))
		goto bad;
	tif->tif_dataoff = (toff_t)(
	    tif->tif_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.
	 */
	_TIFFmemcpy(fields, td->td_fieldsset, sizeof (fields));
	/*
	 * Write out ExtraSamples tag only if
	 * extra samples are present in the data.
	 */
	if (FieldSet(fields, FIELD_EXTRASAMPLES) && !td->td_extrasamples) {
		ResetFieldBit(fields, FIELD_EXTRASAMPLES);
		nfields--;
		dirsize -= sizeof (TIFFDirEntry);
	}								/*XXX*/
	for (fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) {
		const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi];

                /*
                ** For custom fields, we test to see if the custom field
                ** is set or not.  For normal fields, we just use the
                ** FieldSet test. 
                */
                if( fip->field_bit == FIELD_CUSTOM )
                {
                    int ci, is_set = FALSE;

                    for( ci = 0; ci < td->td_customValueCount; ci++ )
                        is_set |= (td->td_customValues[ci].info == fip);

                    if( !is_set )
                        continue;
                }
		else if (!FieldSet(fields, fip->field_bit))
                    continue;


                /*
                ** Handle other fields.
                */
		switch (fip->field_bit)
                {
		case FIELD_STRIPOFFSETS:
			/*
			 * We use one field bit for both strip and tile

			 * offsets, and so must be careful in selecting
			 * the appropriate field descriptor (so that tags
			 * are written in sorted order).
			 */
			tag = isTiled(tif) ?
			    TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS;
			if (tag != fip->field_tag)
				continue;
			if (!TIFFWriteLongArray(tif, TIFF_LONG, tag, dir,
			    (uint32) td->td_nstrips, td->td_stripoffset))
				goto bad;
			break;
		case FIELD_STRIPBYTECOUNTS:
			/*
			 * We use one field bit for both strip and tile
			 * byte counts, and so must be careful in selecting
			 * the appropriate field descriptor (so that tags
			 * are written in sorted order).
			 */
			tag = isTiled(tif) ?
			    TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS;
			if (tag != fip->field_tag)
				continue;
			if (!TIFFWriteLongArray(tif, TIFF_LONG, tag, dir,
			    (uint32) td->td_nstrips, td->td_stripbytecount))
				goto bad;
			break;
		case FIELD_ROWSPERSTRIP:
			TIFFSetupShortLong(tif, TIFFTAG_ROWSPERSTRIP,
			    dir, td->td_rowsperstrip);
			break;
		case FIELD_COLORMAP:
			if (!TIFFWriteShortTable(tif, TIFFTAG_COLORMAP, dir,
			    3, td->td_colormap))
				goto bad;
			break;
		case FIELD_IMAGEDIMENSIONS:
			TIFFSetupShortLong(tif, TIFFTAG_IMAGEWIDTH,
			    dir++, td->td_imagewidth);
			TIFFSetupShortLong(tif, TIFFTAG_IMAGELENGTH,
			    dir, td->td_imagelength);
			break;
		case FIELD_TILEDIMENSIONS:
			TIFFSetupShortLong(tif, TIFFTAG_TILEWIDTH,
			    dir++, td->td_tilewidth);
			TIFFSetupShortLong(tif, TIFFTAG_TILELENGTH,
			    dir, td->td_tilelength);
			break;
		case FIELD_COMPRESSION:
			TIFFSetupShort(tif, TIFFTAG_COMPRESSION,
			    dir, td->td_compression);
			break;
		case FIELD_PHOTOMETRIC:
			TIFFSetupShort(tif, TIFFTAG_PHOTOMETRIC,
			    dir, td->td_photometric);
			break;
		case FIELD_POSITION:
			WriteRationalPair(TIFF_RATIONAL,
			    TIFFTAG_XPOSITION, td->td_xposition,
			    TIFFTAG_YPOSITION, td->td_yposition);
			break;
		case FIELD_RESOLUTION:
			WriteRationalPair(TIFF_RATIONAL,
			    TIFFTAG_XRESOLUTION, td->td_xresolution,
			    TIFFTAG_YRESOLUTION, td->td_yresolution);
			break;
		case FIELD_BITSPERSAMPLE:
		case FIELD_MINSAMPLEVALUE:
		case FIELD_MAXSAMPLEVALUE:
		case FIELD_SAMPLEFORMAT:
			if (!TIFFWritePerSampleShorts(tif, fip->field_tag, dir))
				goto bad;
			break;
		case FIELD_SMINSAMPLEVALUE:
		case FIELD_SMAXSAMPLEVALUE:
			if (!TIFFWritePerSampleAnys(tif,
			    _TIFFSampleToTagType(tif), fip->field_tag, dir))
				goto bad;
			break;
		case FIELD_PAGENUMBER:
		case FIELD_HALFTONEHINTS:
#ifdef YCBCR_SUPPORT
		case FIELD_YCBCRSUBSAMPLING:
#endif
#ifdef CMYK_SUPPORT
		case FIELD_DOTRANGE:
#endif
			if (!TIFFSetupShortPair(tif, fip->field_tag, dir))
				goto bad;
			break;
#ifdef CMYK_SUPPORT
		case FIELD_INKNAMES:
			if (!TIFFWriteInkNames(tif, dir))
				goto bad;
			break;
#endif
#ifdef COLORIMETRY_SUPPORT
		case FIELD_TRANSFERFUNCTION:
			if (!TIFFWriteTransferFunction(tif, dir))
				goto bad;
			break;
#endif
#if SUBIFD_SUPPORT
		case FIELD_SUBIFD:
			if (!TIFFWriteNormalTag(tif, dir, fip))
				goto bad;
			/*
			 * Total hack: if this directory includes a SubIFD
			 * tag then force the next <n> directories to be
			 * written as ``sub directories'' of this one.  This
			 * is used to write things like thumbnails and
			 * image masks that one wants to keep out of the
			 * normal directory linkage access mechanism.
			 */
			if (dir->tdir_count > 0) {
				tif->tif_flags |= TIFF_INSUBIFD;
				tif->tif_nsubifd = (uint16) dir->tdir_count;
				if (dir->tdir_count > 1)
					tif->tif_subifdoff = dir->tdir_offset;
				else
					tif->tif_subifdoff = (uint32)(
					      tif->tif_diroff
					    + sizeof (uint16)
					    + ((char*)&dir->tdir_offset-data));
			}
			break;
#endif
		default:
			if (!TIFFWriteNormalTag(tif, dir, fip))
				goto bad;
			break;
		}
		dir++;
                
                if( fip->field_bit != FIELD_CUSTOM )
                    ResetFieldBit(fields, fip->field_bit);
	}

	/*
	 * Write directory.
	 */
	dircount = (uint16) nfields;
	diroff = (uint32) tif->tif_nextdiroff;
	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(&diroff);
	}
	(void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET);
	if (!WriteOK(tif, &dircount, sizeof (dircount))) {
		TIFFError(tif->tif_name, "Error writing directory count");
		goto bad;
	}
	if (!WriteOK(tif, data, dirsize)) {
		TIFFError(tif->tif_name, "Error writing directory contents");
		goto bad;
	}
	if (!WriteOK(tif, &diroff, sizeof (diroff))) {
		TIFFError(tif->tif_name, "Error writing directory link");
		goto bad;
	}
	if (done) {
		TIFFFreeDirectory(tif);
		tif->tif_flags &= ~TIFF_DIRTYDIRECT;
		(*tif->tif_cleanup)(tif);

		/*
		* Reset directory-related state for subsequent
		* directories.
		*/
		TIFFCreateDirectory(tif);
	}
	_TIFFfree(data);
	return (1);
bad:
	_TIFFfree(data);
	return (0);
}
예제 #4
0
파일: tif_open.c 프로젝트: guozanhua/github
TIFF*
TIFFClientOpen(
	const char* name, const char* mode,
	thandle_t clientdata,
	TIFFReadWriteProc readproc,
	TIFFReadWriteProc writeproc,
	TIFFSeekProc seekproc,
	TIFFCloseProc closeproc,
	TIFFSizeProc sizeproc,
	TIFFMapFileProc mapproc,
	TIFFUnmapFileProc unmapproc
)
{
	static const char module[] = "TIFFClientOpen";
	TIFF *tif;
	int m;
	const char* cp;

	m = _TIFFgetMode(mode, module);
	if (m == -1)
		goto bad2;
	tif = (TIFF *)_TIFFmalloc(sizeof (TIFF) + strlen(name) + 1);
	if (tif == NULL) {
		TIFFErrorExt(clientdata, module, "%s: Out of memory (TIFF structure)", name);
		goto bad2;
	}
	_TIFFmemset(tif, 0, sizeof (*tif));
	tif->tif_name = (char *)tif + sizeof (TIFF);
	strcpy(tif->tif_name, name);
	tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
	tif->tif_curdir = (tdir_t) -1;		/* non-existent directory */
	tif->tif_curoff = 0;
	tif->tif_curstrip = (tstrip_t) -1;	/* invalid strip */
	tif->tif_row = (uint32) -1;		/* read/write pre-increment */
	tif->tif_clientdata = clientdata;
	if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) {
		TIFFErrorExt(clientdata, module,
			  "One of the client procedures is NULL pointer.");
		goto bad2;
	}
	tif->tif_readproc = readproc;
	tif->tif_writeproc = writeproc;
	tif->tif_seekproc = seekproc;
	tif->tif_closeproc = closeproc;
	tif->tif_sizeproc = sizeproc;
        if (mapproc)
		tif->tif_mapproc = mapproc;
	else
		tif->tif_mapproc = _tiffDummyMapProc;
	if (unmapproc)
		tif->tif_unmapproc = unmapproc;
	else
		tif->tif_unmapproc = _tiffDummyUnmapProc;
	_TIFFSetDefaultCompressionState(tif);	/* setup default state */
	/*
	 * Default is to return data MSB2LSB and enable the
	 * use of memory-mapped files and strip chopping when
	 * a file is opened read-only.
	 */
	tif->tif_flags = FILLORDER_MSB2LSB;
	if (m == O_RDONLY )
		tif->tif_flags |= TIFF_MAPPED;

#ifdef STRIPCHOP_DEFAULT
	if (m == O_RDONLY || m == O_RDWR)
		tif->tif_flags |= STRIPCHOP_DEFAULT;
#endif

	/*
	 * Process library-specific flags in the open mode string.
	 * The following flags may be used to control intrinsic library
	 * behaviour that may or may not be desirable (usually for
	 * compatibility with some application that claims to support
	 * TIFF but only supports some braindead idea of what the
	 * vendor thinks TIFF is):
	 *
	 * 'l'		use little-endian byte order for creating a file
	 * 'b'		use big-endian byte order for creating a file
	 * 'L'		read/write information using LSB2MSB bit order
	 * 'B'		read/write information using MSB2LSB bit order
	 * 'H'		read/write information using host bit order
	 * 'M'		enable use of memory-mapped files when supported
	 * 'm'		disable use of memory-mapped files
	 * 'C'		enable strip chopping support when reading
	 * 'c'		disable strip chopping support
	 * 'h'		read TIFF header only, do not load the first IFD
	 *
	 * The use of the 'l' and 'b' flags is strongly discouraged.
	 * These flags are provided solely because numerous vendors,
	 * typically on the PC, do not correctly support TIFF; they
	 * only support the Intel little-endian byte order.  This
	 * support is not configured by default because it supports
	 * the violation of the TIFF spec that says that readers *MUST*
	 * support both byte orders.  It is strongly recommended that
	 * you not use this feature except to deal with busted apps
	 * that write invalid TIFF.  And even in those cases you should
	 * bang on the vendors to fix their software.
	 *
	 * The 'L', 'B', and 'H' flags are intended for applications
	 * that can optimize operations on data by using a particular
	 * bit order.  By default the library returns data in MSB2LSB
	 * bit order for compatibiltiy with older versions of this
	 * library.  Returning data in the bit order of the native cpu
	 * makes the most sense but also requires applications to check
	 * the value of the FillOrder tag; something they probably do
	 * not do right now.
	 *
	 * The 'M' and 'm' flags are provided because some virtual memory
	 * systems exhibit poor behaviour when large images are mapped.
	 * These options permit clients to control the use of memory-mapped
	 * files on a per-file basis.
	 *
	 * The 'C' and 'c' flags are provided because the library support
	 * for chopping up large strips into multiple smaller strips is not
	 * application-transparent and as such can cause problems.  The 'c'
	 * option permits applications that only want to look at the tags,
	 * for example, to get the unadulterated TIFF tag information.
	 */
	for (cp = mode; *cp; cp++)
		switch (*cp) {
		case 'b':
#ifndef WORDS_BIGENDIAN
		    if (m&O_CREAT)
				tif->tif_flags |= TIFF_SWAB;
#endif
			break;
		case 'l':
#ifdef WORDS_BIGENDIAN
			if ((m&O_CREAT))
				tif->tif_flags |= TIFF_SWAB;
#endif
			break;
		case 'B':
			tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
			    FILLORDER_MSB2LSB;
			break;
		case 'L':
			tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
			    FILLORDER_LSB2MSB;
			break;
		case 'H':
			tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
			    HOST_FILLORDER;
			break;
		case 'M':
			if (m == O_RDONLY)
				tif->tif_flags |= TIFF_MAPPED;
			break;
		case 'm':
			if (m == O_RDONLY)
				tif->tif_flags &= ~TIFF_MAPPED;
			break;
		case 'C':
			if (m == O_RDONLY)
				tif->tif_flags |= TIFF_STRIPCHOP;
			break;
		case 'c':
			if (m == O_RDONLY)
				tif->tif_flags &= ~TIFF_STRIPCHOP;
			break;
		case 'h':
			tif->tif_flags |= TIFF_HEADERONLY;
			break;
		}
	/*
	 * Read in TIFF header.
	 */
	if (tif->tif_mode & O_TRUNC ||
	    !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
		if (tif->tif_mode == O_RDONLY) {
			TIFFErrorExt(tif->tif_clientdata, name,
				     "Cannot read TIFF header");
			goto bad;
		}
		/*
		 * Setup header and write.
		 */
#ifdef WORDS_BIGENDIAN
		tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB
		    ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN;
#else
		tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB
		    ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN;
#endif
		tif->tif_header.tiff_version = TIFF_VERSION;
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&tif->tif_header.tiff_version);
		tif->tif_header.tiff_diroff = 0;	/* filled in later */


                /*
                 * The doc for "fopen" for some STD_C_LIBs says that if you 
                 * open a file for modify ("+"), then you must fseek (or 
                 * fflush?) between any freads and fwrites.  This is not
                 * necessary on most systems, but has been shown to be needed
                 * on Solaris. 
                 */
                TIFFSeekFile( tif, 0, SEEK_SET );
               
		if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
			TIFFErrorExt(tif->tif_clientdata, name,
				     "Error writing TIFF header");
			goto bad;
		}
		/*
		 * Setup the byte order handling.
		 */
		TIFFInitOrder(tif, tif->tif_header.tiff_magic);
		/*
		 * Setup default directory.
		 */
		if (!TIFFDefaultDirectory(tif))
			goto bad;
		tif->tif_diroff = 0;
		tif->tif_dirlist = NULL;
		tif->tif_dirlistsize = 0;
		tif->tif_dirnumber = 0;
		return (tif);
	}
	/*
	 * Setup the byte order handling.
	 */
	if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN &&
	    tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN
#if MDI_SUPPORT
	    &&
#if HOST_BIGENDIAN
	    tif->tif_header.tiff_magic != MDI_BIGENDIAN
#else
	    tif->tif_header.tiff_magic != MDI_LITTLEENDIAN
#endif
	    ) {
		TIFFErrorExt(tif->tif_clientdata, name,
			"Not a TIFF or MDI file, bad magic number %d (0x%x)",
#else
	    ) {
		TIFFErrorExt(tif->tif_clientdata, name,
			     "Not a TIFF file, bad magic number %d (0x%x)",
#endif
		    tif->tif_header.tiff_magic,
		    tif->tif_header.tiff_magic);
		goto bad;
	}
	TIFFInitOrder(tif, tif->tif_header.tiff_magic);
	/*
	 * Swap header if required.
	 */
	if (tif->tif_flags & TIFF_SWAB) {
		TIFFSwabShort(&tif->tif_header.tiff_version);
		TIFFSwabLong(&tif->tif_header.tiff_diroff);
	}
	/*
	 * Now check version (if needed, it's been byte-swapped).
	 * Note that this isn't actually a version number, it's a
	 * magic number that doesn't change (stupid).
	 */
	if (tif->tif_header.tiff_version == TIFF_BIGTIFF_VERSION) {
		TIFFErrorExt(tif->tif_clientdata, name,
                          "This is a BigTIFF file.  This format not supported\n"
                          "by this version of libtiff." );
		goto bad;
	}
	if (tif->tif_header.tiff_version != TIFF_VERSION) {
		TIFFErrorExt(tif->tif_clientdata, name,
		    "Not a TIFF file, bad version number %d (0x%x)",
		    tif->tif_header.tiff_version,
		    tif->tif_header.tiff_version);
		goto bad;
	}
	tif->tif_flags |= TIFF_MYBUFFER;
	tif->tif_rawcp = tif->tif_rawdata = 0;
	tif->tif_rawdatasize = 0;

	/*
	 * Sometimes we do not want to read the first directory (for example,
	 * it may be broken) and want to proceed to other directories. I this
	 * case we use the TIFF_HEADERONLY flag to open file and return
	 * immediately after reading TIFF header.
	 */
	if (tif->tif_flags & TIFF_HEADERONLY)
		return (tif);

	/*
	 * Setup initial directory.
	 */
	switch (mode[0]) {
	case 'r':
		tif->tif_nextdiroff = tif->tif_header.tiff_diroff;
		/*
		 * Try to use a memory-mapped file if the client
		 * has not explicitly suppressed usage with the
		 * 'm' flag in the open mode (see above).
		 */
		if ((tif->tif_flags & TIFF_MAPPED) &&
	!TIFFMapFileContents(tif, (tdata_t*) &tif->tif_base, &tif->tif_size))
			tif->tif_flags &= ~TIFF_MAPPED;
		if (TIFFReadDirectory(tif)) {
			tif->tif_rawcc = -1;
			tif->tif_flags |= TIFF_BUFFERSETUP;
			return (tif);
		}
		break;
	case 'a':
		/*
		 * New directories are automatically append
		 * to the end of the directory chain when they
		 * are written out (see TIFFWriteDirectory).
		 */
		if (!TIFFDefaultDirectory(tif))
			goto bad;
		return (tif);
	}
bad:
	tif->tif_mode = O_RDONLY;	/* XXX avoid flush */
        TIFFCleanup(tif);
bad2:
	return ((TIFF*)0);
}
예제 #5
0
/* 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_t
TIFFWritePrivateDataSubDirectory(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);
}
예제 #6
0
/*
 * Function to convert standard TIFF file to BigTIFF file.  Loop through all directories in
 * current file (including subdirectories linked via SubIFD arrays) and create corresponding
 * new directories with 64-bit arrays.  The old 32-bit directories are left in the file as
 * dead space.  The data for directory entries are reused by default.  Some directory entries
 * require new data with 64-bit offsets (e.g. stripe/tile offsets and SubIFD arrays).
 *
 * Returns 1 if successful, 0 if cannot convert to BigTIFF (TIFF_NOBIGTIFF set 
 * or 32-bit API called).
 */
static int 
TIFFMakeBigTIFF(TIFF *tif)
{
	uint32	dirlink = TIFF_HEADER_DIROFF_S,
		diroff = tif->tif_header.s.tiff_diroff;
	toff_t	dirlinkB = TIFF_HEADER_DIROFF_B,
		diroffB;
	uint16	dircount, dirindex;
	uint64	dircountB;
	tsize_t	dirsize, dirsizeB;
	int	issubifd = 0;
	uint32	subifdcnt = 0;
	uint32	subifdlink;
	toff_t	subifdlinkB;
	char	*data, *dataB;
	TIFFDirEntry *dir, *dirB;

	/*
	 * Update flags and file header
	 */
	if (noBigTIFF(tif)) {
		TIFFErrorExt((tif)->tif_clientdata, 
			"TIFFCheckBigTIFF", "File > 2^32 and NO BigTIFF specified");
		return (0);
	}
	tif->tif_flags |= TIFF_ISBIGTIFF;
	tif->tif_header.b.tiff_version = TIFF_BIGTIFF_VERSION;
	tif->tif_header.b.tiff_offsize = 8;
	tif->tif_header.b.tiff_fill = 0;
	tif->tif_header.b.tiff_diroff = 0;
	if (tif->tif_flags & TIFF_SWAB) {
		TIFFSwabShort(&tif->tif_header.b.tiff_version);
		TIFFSwabShort(&tif->tif_header.b.tiff_offsize);
	}
	if (!SeekOK(tif, 0) ||
	    !WriteOK(tif, &tif->tif_header, sizeof(TIFFHeader))) {
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
			"Error updating TIFF header (%d)", TIFFGetErrno(tif));
		return (0);
	}
	if (tif->tif_flags & TIFF_SWAB) {
		TIFFSwabShort(&tif->tif_header.b.tiff_version);
		TIFFSwabShort(&tif->tif_header.b.tiff_offsize);
	}

	/*
	 * Loop through all directories and rewrite as BigTIFF with 64-bit offsets.  This
	 * begins with main IFD chain but may divert to SubIFD arrays as needed.
	 */
	while (diroff != 0 && diroff != tif->tif_diroff) {
		if (!SeekOK(tif, diroff) ||
		    !ReadOK(tif, &dircount, sizeof(dircount))) {
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
				"Error reading TIFF directory (%d)", TIFFGetErrno(tif));
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&dircount);
		dircountB = dircount;
		if (!(data = _TIFFmalloc(dirsize = dircount * TIFFDirEntryLenS)) ||
		    !(dataB = _TIFFmalloc(dirsizeB = dircount * TIFFDirEntryLenB))) {
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
				"Error allocating space for directory");
			return (0);
		}
		if (!SeekOK(tif, diroff + sizeof(dircount)) ||
		    !ReadOK(tif, data, dirsize)) {
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
				"Error reading TIFF directory (%d)", TIFFGetErrno(tif));
			goto error;
		}
		diroffB = tif->tif_dataoff;
		tif->tif_dataoff += sizeof(dircountB) + dirsizeB + sizeof(toff_t);

		for (dirindex = 0; dirindex < dircount; dirindex++) {
			dir = (TIFFDirEntry*) (data + dirindex * TIFFDirEntryLenS);
			dirB = (TIFFDirEntry*) (dataB + dirindex * TIFFDirEntryLenB);
			if (tif->tif_flags & TIFF_SWAB) {
				TIFFSwabShort(&dir->s.tdir_tag);
				TIFFSwabShort(&dir->s.tdir_type);
				TIFFSwabLong(&dir->s.tdir_count);
				TIFFSwabLong(&dir->s.tdir_offset);
			}
			dirB->b.tdir_tag = dir->s.tdir_tag;
			dirB->b.tdir_type = dir->s.tdir_type;
			dirB->b.tdir_count = dir->s.tdir_count;
			dirB->b.tdir_offset = 0;
			/*
			 * If data are in directory entry itself, copy data, else (data are pointed
			 * to by directory entry) copy pointer.  This is complicated by the fact that
			 * the old entry had 32-bits of space, and the new has 64-bits, so may have
			 * to read data pointed at by the old entry directly into the new entry.
			 */
			switch (dir->s.tdir_type) {
			case TIFF_UNDEFINED:
			case TIFF_BYTE:
			case TIFF_SBYTE:
			case TIFF_ASCII:
				if (dir->s.tdir_count <= sizeof(dir->s.tdir_offset))
					_TIFFmemcpy(&dirB->b.tdir_offset, &dir->s.tdir_offset, dir->s.tdir_count);
				else if (dir->s.tdir_count <= sizeof(dirB->b.tdir_count)) {
					TIFFSeekFile(tif, dir->s.tdir_offset, SEEK_SET);
					TIFFReadFile(tif, &dirB->b.tdir_offset, dir->s.tdir_count);
				} else
					dirB->b.tdir_offset = dir->s.tdir_offset;
				break;
			case TIFF_SHORT:
			case TIFF_SSHORT:
				if (dir->s.tdir_count <= sizeof(dir->s.tdir_offset) / sizeof(uint16))
					_TIFFmemcpy(&dirB->b.tdir_offset, &dir->s.tdir_offset, dir->s.tdir_count * sizeof(uint16));
				else if (dir->s.tdir_count <= sizeof(dirB->b.tdir_count) / sizeof(uint16)) {
					TIFFSeekFile(tif, dir->s.tdir_offset, SEEK_SET);
					TIFFReadFile(tif, &dirB->b.tdir_offset, dir->s.tdir_count * sizeof(uint16));
					if (tif->tif_flags & TIFF_SWAB)
						TIFFSwabArrayOfShort((uint16*) &dirB->b.tdir_offset, dir->s.tdir_count);
				} else
					dirB->b.tdir_offset = dir->s.tdir_offset;
				break;
			case TIFF_LONG:
			case TIFF_FLOAT:
			case TIFF_IFD:
				if (dir->s.tdir_count <= sizeof(dir->s.tdir_offset) / sizeof(uint32))
					_TIFFmemcpy(&dirB->b.tdir_offset, &dir->s.tdir_offset, dir->s.tdir_count * sizeof(uint32));
				else if (dir->s.tdir_count <= sizeof(dirB->b.tdir_count) / sizeof(uint32)) {
					TIFFSeekFile(tif, dir->s.tdir_offset, SEEK_SET);
					TIFFReadFile(tif, &dirB->b.tdir_offset, dir->s.tdir_count * sizeof(uint32));
					if (tif->tif_flags & TIFF_SWAB)
						TIFFSwabArrayOfLong((uint32*) &dirB->b.tdir_offset, dir->s.tdir_count);
				} else
					dirB->b.tdir_offset = dir->s.tdir_offset;
				break;
			case TIFF_RATIONAL:
			case TIFF_SRATIONAL:
				if (dir->s.tdir_count * 2 <= sizeof(dirB->b.tdir_offset) / sizeof(uint32)) {
					TIFFSeekFile(tif, dir->s.tdir_offset, SEEK_SET);
					TIFFReadFile(tif, &dirB->b.tdir_offset, dir->s.tdir_count * 2 * sizeof(uint32));
					if (tif->tif_flags & TIFF_SWAB)
						TIFFSwabArrayOfLong((uint32*) &dirB->b.tdir_offset, dir->s.tdir_count * 2);
				} else
					dirB->b.tdir_offset = dir->s.tdir_offset;
				break;
			default:
				dirB->b.tdir_offset = dir->s.tdir_offset;
				break;
			}
			/*
			 * Process special case of SUBIFD; must change data from 32-bit to 64-bit in 
			 * case new 64-bit directory offsets need to be added.
			 */
			switch (dirB->b.tdir_tag) {
			case TIFFTAG_SUBIFD:
				dirB->b.tdir_type = TIFF_IFD8;
				subifdcnt = dir->s.tdir_count;
				/*
				 * Set pointer to existing SubIFD array
				 */
				if (subifdcnt <= sizeof(dir->s.tdir_offset) / sizeof(uint32))
					subifdlink = diroff + sizeof(dircount) +
						(char*) &dir->s.tdir_offset - (char*) dir;
				else
					subifdlink = dir->s.tdir_offset;
				/*
				 * Initialize new SubIFD array, set pointer to it
				 */
				if (subifdcnt <= sizeof(dir->b.tdir_offset) / sizeof(toff_t)) {
					dir->b.tdir_offset = 0;
					subifdlinkB = diroffB + sizeof(dircountB) +
						(char*) &dir->b.tdir_offset - (char*) dirB;
				} else {
					toff_t *offB;

					if (!(offB = _TIFFmalloc(subifdcnt * sizeof(toff_t)))) {
						TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
							"Error allocating space for 64-bit SubIFDs");
						goto error;
					}
					_TIFFmemset(offB, 0, subifdcnt * sizeof(toff_t));
					TIFFWriteLong8Array(tif, dirB, offB);
					_TIFFfree(offB);
					subifdlinkB = dirB->b.tdir_offset;
					}
				break;
			}
			if (tif->tif_flags & TIFF_SWAB) {
				TIFFSwabShort(&dirB->b.tdir_tag);
				TIFFSwabShort(&dirB->b.tdir_type);
				TIFFSwabLong8(&dirB->b.tdir_count);
				TIFFSwabLong8(&dirB->b.tdir_offset);
			}
		}
		
		/*
		 * Write out new directory and chain to previous
		 */
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabLong8(&dircountB);
		if (!SeekOK(tif, diroffB) ||
		    !WriteOK(tif, &dircountB, sizeof(dircountB)) ||
		    !SeekOK(tif, diroffB + sizeof(dircountB)) ||
		    !WriteOK(tif, dataB, dirsizeB)) {
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
				"Error writing TIFF directory (%d)", TIFFGetErrno(tif));
			goto error;
		}

		/*
		 * If directory is SubIFD update array in host directory, else add to
		 * main directory chain
		 */
		if (tif->tif_nsubifd &&
			tif->tif_subifdoff == subifdlink)
			tif->tif_subifdoff = subifdlinkB;

		if (!issubifd && 
			dirlinkB == TIFF_HEADER_DIROFF_B)
			tif->tif_header.b.tiff_diroff = diroffB;
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabLong8(&diroffB);
		if (!SeekOK(tif, (issubifd ? subifdlinkB++ : dirlinkB)) ||
		    !WriteOK(tif, &diroffB, sizeof(diroffB))) {
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
				"Error writing directory link (%d)", TIFFGetErrno(tif));
			goto error;
		}

		if (issubifd)
			subifdcnt--;
		else {
			dirlink = diroff + sizeof(dircount) + dirsize;
			dirlinkB = diroffB + sizeof(dircountB) + dirsizeB;
		}
		issubifd = (subifdcnt > 0);

		if (!SeekOK(tif, (issubifd ? subifdlink++ : dirlink)) ||
		    !ReadOK(tif, &diroff, sizeof(diroff))) {
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
				"Error reading directory link (%d)", TIFFGetErrno(tif));
			goto error;
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabLong(&diroff);
		_TIFFfree(dataB);
		_TIFFfree(data);
	}

	/*
	 * Mark end of directory chain
	 */
	diroffB = 0;
	if (dirlinkB == TIFF_HEADER_DIROFF_B)
		tif->tif_header.b.tiff_diroff = diroffB;
	if (tif->tif_flags & TIFF_SWAB)
		TIFFSwabLong8(&diroffB);
	if (!SeekOK(tif, dirlinkB) ||
	    !WriteOK(tif, &diroffB, sizeof(diroffB))) {
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
			"Error writing directory link (%d)", TIFFGetErrno(tif));
		goto error;
	}

	return (1);

error:
	_TIFFfree(dataB);
	_TIFFfree(data);
	return (0);
}
예제 #7
0
TIFF*
TIFFClientOpen(
	const char* name, const char* mode,
	thandle_t clientdata,
	TIFFReadWriteProc readproc,
	TIFFReadWriteProc writeproc,
	TIFFSeekProc seekproc,
	TIFFCloseProc closeproc,
	TIFFSizeProc sizeproc,
	TIFFMapFileProc mapproc,
	TIFFUnmapFileProc unmapproc
)
{
	static const char module[] = "TIFFClientOpen";
	TIFF *tif;
	int m, bigendian;

	m = _TIFFgetMode(mode, module);
	if (m == -1)
		goto bad2;
	tif = (TIFF *)_TIFFmalloc(sizeof (TIFF) + strlen(name) + 1);
	if (tif == NULL) {
		TIFFError(module, "%s: Out of memory (TIFF structure)", name);
		goto bad2;
	}
	_TIFFmemset(tif, 0, sizeof (*tif));
	tif->tif_name = (char *)tif + sizeof (TIFF);
	strcpy(tif->tif_name, name);
	tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
	tif->tif_curdir = (tdir_t) -1;		/* non-existent directory */
	tif->tif_curoff = 0;
	tif->tif_curstrip = (tstrip_t) -1;	/* invalid strip */
	tif->tif_row = (uint32)-1;		/* read/write pre-increment */
	tif->tif_clientdata = clientdata;
	tif->tif_readproc = readproc;
	tif->tif_writeproc = writeproc;
	tif->tif_seekproc = seekproc;
	tif->tif_closeproc = closeproc;
	tif->tif_sizeproc = sizeproc;
	tif->tif_mapproc = mapproc;
	tif->tif_unmapproc = unmapproc;

	{ union { int32 i; char c[4]; } u; u.i = 1; bigendian = u.c[0] == 0; }
#ifdef ENDIANHACK_SUPPORT
	/*
	 * Numerous vendors, typically on the PC, do not correctly
	 * support TIFF; they only support the Intel little-endian
	 * byte order.  If this hack is enabled, then applications
	 * can open a file with a specific byte-order by specifying
	 * either "wl" (for litt-endian byte order) or "wb" for
	 * (big-endian byte order).  This support is not configured
	 * by default because it supports the violation of the TIFF
	 * spec that says that readers *MUST* support both byte orders.
	 *
	 * It is strongly recommended that you not use this feature
	 * except to deal with busted apps that write invalid TIFF.
	 * And even in those cases you should bang on the vendors to
	 * fix their software.
	 */
	if ((m&O_CREAT) &&
	    ((bigendian && mode[1] == 'l') || (!bigendian && mode[1] == 'b')))
		tif->tif_flags |= TIFF_SWAB;
#endif
	/*
	 * Read in TIFF header.
	 */
	if (!ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
		if (tif->tif_mode == O_RDONLY) {
			TIFFError(name, "Cannot read TIFF header");
			goto bad;
		}
		/*
		 * Setup header and write.
		 */
		tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB
		    ? (bigendian ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN)
		    : (bigendian ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN);
		tif->tif_header.tiff_version = TIFF_VERSION;
		tif->tif_header.tiff_diroff = 0;	/* filled in later */
		if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
			TIFFError(name, "Error writing TIFF header");
			goto bad;
		}
		/*
		 * Setup the byte order handling.
		 */
		TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian);
		/*
		 * Setup default directory.
		 */
		if (!TIFFDefaultDirectory(tif))
			goto bad;
		tif->tif_diroff = 0;
		return (tif);
	}
	/*
	 * Setup the byte order handling.
	 */
	if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN &&
	    tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN) {
		TIFFError(name,  "Not a TIFF file, bad magic number %d (0x%x)",
		    tif->tif_header.tiff_magic,
		    tif->tif_header.tiff_magic);
		goto bad;
	}
	TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian);
	/*
	 * Swap header if required.
	 */
	if (tif->tif_flags & TIFF_SWAB) {
		TIFFSwabShort(&tif->tif_header.tiff_version);
		TIFFSwabLong(&tif->tif_header.tiff_diroff);
	}
	/*
	 * Now check version (if needed, it's been byte-swapped).
	 * Note that this isn't actually a version number, it's a
	 * magic number that doesn't change (stupid).
	 */
	if (tif->tif_header.tiff_version != TIFF_VERSION) {
		TIFFError(name,
		    "Not a TIFF file, bad version number %d (0x%x)",
		    tif->tif_header.tiff_version,
		    tif->tif_header.tiff_version); 
		goto bad;
	}
	tif->tif_flags |= TIFF_MYBUFFER;
	tif->tif_rawcp = tif->tif_rawdata = 0;
	tif->tif_rawdatasize = 0;
	/*
	 * Setup initial directory.
	 */
	switch (mode[0]) {
	case 'r':
		tif->tif_nextdiroff = tif->tif_header.tiff_diroff;
		if (TIFFMapFileContents(tif, (tdata_t*) &tif->tif_base, &tif->tif_size))
			tif->tif_flags |= TIFF_MAPPED;
		if (TIFFReadDirectory(tif)) {
			tif->tif_rawcc = -1;
			tif->tif_flags |= TIFF_BUFFERSETUP;
			return (tif);
		}
		break;
	case 'a':
		/*
		 * New directories are automatically append
		 * to the end of the directory chain when they
		 * are written out (see TIFFWriteDirectory).
		 */
		if (!TIFFDefaultDirectory(tif))
			goto bad;
		return (tif);
	}
bad:
	tif->tif_mode = O_RDONLY;	/* XXX avoid flush */
	TIFFClose(tif);
	return ((TIFF*)0);
bad2:
	(void) (*closeproc)(clientdata);
	return ((TIFF*)0);
}
예제 #8
0
TIFF*
TIFFClientOpen(
    tdata_t lib,
	const char* name, const char* mode,
	thandle_t clientdata,
	TIFFReadWriteProc readproc,
	TIFFReadWriteProc writeproc,
	TIFFSeekProc seekproc,
	TIFFSizeProc sizeproc,
    TIFFCloseProc closeproc,
	TIFFMallocProc mallocproc,
    TIFFReallocProc reallocproc,
    TIFFFreeProc freeproc
)
{
	static const char module[] = "TIFFClientOpen";
	TIFF *tif, tmp, *t;
	int m, bigendian;
	const char* cp;

	m = _TIFFgetMode(mode, module);
	if (m == -1)
		goto bad2;
    if ( mallocproc ){
        tmp.lib = lib;
        tmp.tif_mallocproc = mallocproc;
        t = &tmp;
        tif = (TIFF *)TIFFMalloc ( t, sizeof (TIFF) + strlen(name) + 1 );
    } else {
        tif = (TIFF *)_TIFFmallocA(sizeof (TIFF) + strlen(name) + 1);
    }
	if (tif == NULL) {
		TIFFError(module, "%s: Out of memory (TIFF structure)", name);
		goto bad2;
	}
	_TIFFmemset(tif, 0, sizeof (*tif));
	tif->tif_name = (char *)tif + sizeof (TIFF);
	strcpy(tif->tif_name, name);
	tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
	tif->tif_curdir = (tdir_t) -1;		/* non-existent directory */
	tif->tif_curoff = 0;
	tif->tif_curstrip = (tstrip_t) -1;	/* invalid strip */
	tif->tif_row = (uint32) -1;		/* read/write pre-increment */
	tif->tif_clientdata = clientdata;
	tif->tif_readproc = readproc;
	tif->tif_writeproc = writeproc;
	tif->tif_seekproc = seekproc;
	tif->tif_sizeproc = sizeproc;
    tif->tif_closeproc = closeproc;
    tif->tif_mallocproc = mallocproc;
    tif->tif_reallocproc = reallocproc;
    tif->tif_freeproc = freeproc;
    tif->lib = lib;
	_TIFFSetDefaultCompressionState(tif);	/* setup default state */
	/*
	 * Default is to return data MSB2LSB and enable the
	 * use of memory-mapped files and strip chopping when
	 * a file is opened read-only.
	 */
	tif->tif_flags = FILLORDER_MSB2LSB;
	if (m == O_RDONLY )
            tif->tif_flags |= TIFF_MAPPED;

#ifdef STRIPCHOP_DEFAULT
	if (m == O_RDONLY || m == O_RDWR)
		tif->tif_flags |= STRIPCHOP_DEFAULT;
#endif

	{ union { int32 i; char c[4]; } u; u.i = 1; bigendian = u.c[0] == 0; }
	/*
	 * Process library-specific flags in the open mode string.
	 * The following flags may be used to control intrinsic library
	 * behaviour that may or may not be desirable (usually for
	 * compatibility with some application that claims to support
	 * TIFF but only supports some braindead idea of what the
	 * vendor thinks TIFF is):
	 *
	 * 'l'		use little-endian byte order for creating a file
	 * 'b'		use big-endian byte order for creating a file
	 * 'L'		read/write information using LSB2MSB bit order
	 * 'B'		read/write information using MSB2LSB bit order
	 * 'H'		read/write information using host bit order
	 * 'M'		enable use of memory-mapped files when supported
	 * 'm'		disable use of memory-mapped files
	 * 'C'		enable strip chopping support when reading
	 * 'c'		disable strip chopping support
	 *
	 * The use of the 'l' and 'b' flags is strongly discouraged.
	 * These flags are provided solely because numerous vendors,
	 * typically on the PC, do not correctly support TIFF; they
	 * only support the Intel little-endian byte order.  This
	 * support is not configured by default because it supports
	 * the violation of the TIFF spec that says that readers *MUST*
	 * support both byte orders.  It is strongly recommended that
	 * you not use this feature except to deal with busted apps
	 * that write invalid TIFF.  And even in those cases you should
	 * bang on the vendors to fix their software.
	 *
	 * The 'L', 'B', and 'H' flags are intended for applications
	 * that can optimize operations on data by using a particular
	 * bit order.  By default the library returns data in MSB2LSB
	 * bit order for compatibiltiy with older versions of this
	 * library.  Returning data in the bit order of the native cpu
	 * makes the most sense but also requires applications to check
	 * the value of the FillOrder tag; something they probabyl do
	 * not do right now.
	 *
	 * The 'M' and 'm' flags are provided because some virtual memory
	 * systems exhibit poor behaviour when large images are mapped.
	 * These options permit clients to control the use of memory-mapped
	 * files on a per-file basis.
	 *
	 * The 'C' and 'c' flags are provided because the library support
	 * for chopping up large strips into multiple smaller strips is not
	 * application-transparent and as such can cause problems.  The 'c'
	 * option permits applications that only want to look at the tags,
	 * for example, to get the unadulterated TIFF tag information.
	 */
	for (cp = mode; *cp; cp++)
		switch (*cp) {
		case 'b':
			if ((m&O_CREAT) && !bigendian)
				tif->tif_flags |= TIFF_SWAB;
			break;
		case 'l':
			if ((m&O_CREAT) && bigendian)
				tif->tif_flags |= TIFF_SWAB;
			break;
		case 'B':
			tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
			    FILLORDER_MSB2LSB;
			break;
		case 'L':
			tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
			    FILLORDER_LSB2MSB;
			break;
		case 'H':
			tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
			    HOST_FILLORDER;
			break;
		case 'M':
			if (m == O_RDONLY)
				tif->tif_flags |= TIFF_MAPPED;
			break;
		case 'm':
			if (m == O_RDONLY)
				tif->tif_flags &= ~TIFF_MAPPED;
			break;
		case 'C':
			if (m == O_RDONLY)
				tif->tif_flags |= TIFF_STRIPCHOP;
			break;
		case 'c':
			if (m == O_RDONLY)
				tif->tif_flags &= ~TIFF_STRIPCHOP;
			break;
		}
	/*
	 * Read in TIFF header.
	 */
    tif->tif_flags &= ~TIFF_MAPPED;
	if (!ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
		if (tif->tif_mode == O_RDONLY) {
			TIFFError(name, "Cannot read TIFF header");
			goto bad;
		}
		/*
		 * Setup header and write.
		 */
		tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB
		    ? (bigendian ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN)
		    : (bigendian ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN);
		tif->tif_header.tiff_version = TIFF_VERSION;
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&tif->tif_header.tiff_version);
		tif->tif_header.tiff_diroff = 0;	/* filled in later */

                /*
                 * This seek shouldn't be necessary, but I have had some
                 * crazy problems with a failed fseek() on Solaris leaving
                 * the current file pointer out of whack when an fwrite()
                 * is done. 
                 */
                TIFFSeekFile( tif, 0, SEEK_SET );

		if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
			TIFFError(name, "Error writing TIFF header");
			goto bad;
		}
		/*
		 * Setup the byte order handling.
		 */
		TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian);
		/*
		 * Setup default directory.
		 */
		if (!TIFFDefaultDirectory(tif))
			goto bad;
		tif->tif_diroff = 0;
		return (tif);
	}
	/*
	 * Setup the byte order handling.
	 */
	if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN &&
	    tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN) {
		TIFFError(name,  "Not a TIFF file, bad magic number %d (0x%x)",
		    tif->tif_header.tiff_magic,
		    tif->tif_header.tiff_magic);
		goto bad;
	}
	TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian);
	/*
	 * Swap header if required.
	 */
	if (tif->tif_flags & TIFF_SWAB) {
		TIFFSwabShort(&tif->tif_header.tiff_version);
		TIFFSwabLong(&tif->tif_header.tiff_diroff);
	}
	/*
	 * Now check version (if needed, it's been byte-swapped).
	 * Note that this isn't actually a version number, it's a
	 * magic number that doesn't change (stupid).
	 */
	if (tif->tif_header.tiff_version != TIFF_VERSION) {
		TIFFError(name,
		    "Not a TIFF file, bad version number %d (0x%x)",
		    tif->tif_header.tiff_version,
		    tif->tif_header.tiff_version); 
		goto bad;
	}
	tif->tif_flags |= TIFF_MYBUFFER;
	tif->tif_rawcp = tif->tif_rawdata = 0;
	tif->tif_rawdatasize = 0;
	/*
	 * Setup initial directory.
	 */
	switch (mode[0]) {
	case 'r':
		tif->tif_nextdiroff = tif->tif_header.tiff_diroff;
		/*
		 * Try to use a memory-mapped file if the client
		 * has not explicitly suppressed usage with the
		 * 'm' flag in the open mode (see above).
		 */
		if (TIFFReadDirectory(tif)) {
                        if( m != O_RDONLY 
                          && tif->tif_dir.td_compression != COMPRESSION_NONE )
                        {
                            TIFFError( name, 
                                       "Can't open a compressed TIFF file"
                                       " with compression for update." );
                            goto bad;
                        }
			tif->tif_rawcc = -1;
			tif->tif_flags |= TIFF_BUFFERSETUP;
			return (tif);
		}
		break;
	case 'a':
		/*
		 * New directories are automatically append
		 * to the end of the directory chain when they
		 * are written out (see TIFFWriteDirectory).
		 */
		if (!TIFFDefaultDirectory(tif))
			goto bad;
		return (tif);
	}
bad:
	tif->tif_mode = O_RDONLY;	/* XXX avoid flush */
	TIFFClose(tif);
	return ((TIFF*)0);
bad2:
    if ( closeproc )
        	(void) (*closeproc)(clientdata);
	return ((TIFF*)0);
}
예제 #9
0
static void
dump(int fd, uint64 diroff)
{
	unsigned i;

	lseek(fd, (off_t) 0, 0);
	if (read(fd, (char*) &hdr, sizeof (TIFFHeaderCommon)) != sizeof (TIFFHeaderCommon))
		ReadError("TIFF header");
	if (hdr.common.tiff_magic != TIFF_BIGENDIAN
	    && hdr.common.tiff_magic != TIFF_LITTLEENDIAN &&
#if HOST_BIGENDIAN
	    /* MDI is sensitive to the host byte order, unlike TIFF */
	    MDI_BIGENDIAN != hdr.common.tiff_magic
#else
	    MDI_LITTLEENDIAN != hdr.common.tiff_magic
#endif
	   ) {
		Fatal("Not a TIFF or MDI file, bad magic number %u (%#x)",
		    hdr.common.tiff_magic, hdr.common.tiff_magic);
	}
	if (hdr.common.tiff_magic == TIFF_BIGENDIAN
	    || hdr.common.tiff_magic == MDI_BIGENDIAN)
		swabflag = !bigendian;
	else
		swabflag = bigendian;
	if (swabflag)
		TIFFSwabShort(&hdr.common.tiff_version);
	if (hdr.common.tiff_version==42)
	{
		if (read(fd, (char*) &hdr.classic.tiff_diroff, 4) != 4)
			ReadError("TIFF header");
		if (swabflag)
			TIFFSwabLong(&hdr.classic.tiff_diroff);
		printf("Magic: %#x <%s-endian> Version: %#x <%s>\n",
		    hdr.classic.tiff_magic,
		    hdr.classic.tiff_magic == TIFF_BIGENDIAN ? "big" : "little",
		    42,"ClassicTIFF");
		if (diroff == 0)
			diroff = hdr.classic.tiff_diroff;
	}
	else if (hdr.common.tiff_version==43)
	{
		if (read(fd, (char*) &hdr.big.tiff_offsetsize, 12) != 12)
			ReadError("TIFF header");
		if (swabflag)
		{
			TIFFSwabShort(&hdr.big.tiff_offsetsize);
			TIFFSwabShort(&hdr.big.tiff_unused);
			TIFFSwabLong8(&hdr.big.tiff_diroff);
		}
		printf("Magic: %#x <%s-endian> Version: %#x <%s>\n",
		    hdr.big.tiff_magic,
		    hdr.big.tiff_magic == TIFF_BIGENDIAN ? "big" : "little",
		    43,"BigTIFF");
		printf("OffsetSize: %#x Unused: %#x\n",
		    hdr.big.tiff_offsetsize,hdr.big.tiff_unused);
		if (diroff == 0)
			diroff = hdr.big.tiff_diroff;
		bigtiff = 1;
	}
	else
		Fatal("Not a TIFF file, bad version number %u (%#x)",
		    hdr.common.tiff_version, hdr.common.tiff_version);
	for (i = 0; diroff != 0; i++) {
		if (i > 0)
			putchar('\n');
		diroff = ReadDirectory(fd, i, diroff);
	}
}
예제 #10
0
/*
 * Read the next TIFF directory from a file
 * and convert it to the internal format.
 * We read directories sequentially.
 */
int
TIFFReadDirectory(TIFF* tif)
{
	register TIFFDirEntry* dp;
	register int n;
	register TIFFDirectory* td;
	TIFFDirEntry* dir;
	int iv;
	long v;
	double dv;
	const TIFFFieldInfo* fip;
	int fix;
	uint16 dircount;
	toff_t nextdiroff;
	char* cp;
	int diroutoforderwarning = 0;

	tif->tif_diroff = tif->tif_nextdiroff;
	if (tif->tif_diroff == 0)		/* no more directories */
		return (0);
	/*
	 * Cleanup any previous compression state.
	 */
	(*tif->tif_cleanup)(tif);
	tif->tif_curdir++;
	nextdiroff = 0;
	if (!isMapped(tif)) {
		if (!SeekOK(tif, tif->tif_diroff)) {
			TIFFError(tif->tif_name,
			    "Seek error accessing TIFF directory");
			return (0);
		}
		if (!ReadOK(tif, &dircount, sizeof (uint16))) {
			TIFFError(tif->tif_name,
			    "Can not read TIFF directory count");
			return (0);
		}
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&dircount);
		dir = (TIFFDirEntry *)CheckMalloc(tif,
		    dircount * sizeof (TIFFDirEntry), "to read TIFF directory");
		if (dir == NULL)
			return (0);
		if (!ReadOK(tif, dir, dircount*sizeof (TIFFDirEntry))) {
			TIFFError(tif->tif_name, "Can not read TIFF directory");
			goto bad;
		}
		/*
		 * Read offset to next directory for sequential scans.
		 */
		(void) ReadOK(tif, &nextdiroff, sizeof (uint32));
	} else {
		toff_t off = tif->tif_diroff;

		if (off + sizeof (uint16) > tif->tif_size) {
			TIFFError(tif->tif_name,
			    "Can not read TIFF directory count");
			return (0);
		} else
			_TIFFmemcpy(&dircount, tif->tif_base + off, sizeof (uint16));
		off += sizeof (uint16);
		if (tif->tif_flags & TIFF_SWAB)
			TIFFSwabShort(&dircount);
		dir = (TIFFDirEntry *)CheckMalloc(tif,
		    dircount * sizeof (TIFFDirEntry), "to read TIFF directory");
		if (dir == NULL)
			return (0);
		if (off + dircount*sizeof (TIFFDirEntry) > tif->tif_size) {
			TIFFError(tif->tif_name, "Can not read TIFF directory");
			goto bad;
		} else
			_TIFFmemcpy(dir, tif->tif_base + off,
			    dircount*sizeof (TIFFDirEntry));
		off += dircount* sizeof (TIFFDirEntry);
		if (off + sizeof (uint32) <= tif->tif_size)
			_TIFFmemcpy(&nextdiroff, tif->tif_base+off, sizeof (uint32));
	}
	if (tif->tif_flags & TIFF_SWAB)
		TIFFSwabLong(&nextdiroff);
	tif->tif_nextdiroff = nextdiroff;

	tif->tif_flags &= ~TIFF_BEENWRITING;	/* reset before new dir */
	/*
	 * Setup default value and then make a pass over
	 * the fields to check type and tag information,
	 * and to extract info required to size data
	 * structures.  A second pass is made afterwards
	 * to read in everthing not taken in the first pass.
	 */
	td = &tif->tif_dir;
	/* free any old stuff and reinit */
	TIFFFreeDirectory(tif);
	TIFFDefaultDirectory(tif);
	/*
	 * Electronic Arts writes gray-scale TIFF files
	 * without a PlanarConfiguration directory entry.
	 * Thus we setup a default value here, even though
	 * the TIFF spec says there is no default value.
	 */
	TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);

	/*
	 * Sigh, we must make a separate pass through the
	 * directory for the following reason:
	 *
	 * We must process the Compression tag in the first pass
	 * in order to merge in codec-private tag definitions (otherwise
	 * we may get complaints about unknown tags).  However, the
	 * Compression tag may be dependent on the SamplesPerPixel
	 * tag value because older TIFF specs permited Compression
	 * to be written as a SamplesPerPixel-count tag entry.
	 * Thus if we don't first figure out the correct SamplesPerPixel
	 * tag value then we may end up ignoring the Compression tag
	 * value because it has an incorrect count value (if the
	 * true value of SamplesPerPixel is not 1).
	 *
	 * It sure would have been nice if Aldus had really thought
	 * this stuff through carefully.
	 */ 
	for (dp = dir, n = dircount; n > 0; n--, dp++) {
		if (tif->tif_flags & TIFF_SWAB) {
			TIFFSwabArrayOfShort(&dp->tdir_tag, 2);
			TIFFSwabArrayOfLong(&dp->tdir_count, 2);
		}
		if (dp->tdir_tag == TIFFTAG_SAMPLESPERPIXEL) {
			if (!TIFFFetchNormalTag(tif, dp))
				goto bad;
			dp->tdir_tag = IGNORE;
		}
	}
	/*
	 * First real pass over the directory.
	 */
	fix = 0;
	for (dp = dir, n = dircount; n > 0; n--, dp++) {

                /*
                 * Find the field information entry for this tag.
		 * Added check for tags to ignore ... [BFC]
                 */
		if( TIFFReassignTagToIgnore(TIS_EXTRACT, dp->tdir_tag) )
                    dp->tdir_tag = IGNORE;

		if (dp->tdir_tag == IGNORE)
                    continue;
                
		/*
		 * Silicon Beach (at least) writes unordered
		 * directory tags (violating the spec).  Handle
		 * it here, but be obnoxious (maybe they'll fix it?).
		 */
		if (dp->tdir_tag < tif->tif_fieldinfo[fix]->field_tag) {
			if (!diroutoforderwarning) {
				TIFFWarning(tif->tif_name,
	"invalid TIFF directory; tags are not sorted in ascending order");
				diroutoforderwarning = 1;
			}
			fix = 0;			/* O(n^2) */
		}
		while (fix < tif->tif_nfields &&
		    tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag)
			fix++;
		if (fix == tif->tif_nfields ||
		    tif->tif_fieldinfo[fix]->field_tag != dp->tdir_tag) {
			TIFFWarning(tif->tif_name,
			    "unknown field with tag %d (0x%x) ignored",
			    dp->tdir_tag,  dp->tdir_tag);
			dp->tdir_tag = IGNORE;
			fix = 0;			/* restart search */
			continue;
		}
		/*
		 * Null out old tags that we ignore.
		 */
		if (tif->tif_fieldinfo[fix]->field_bit == FIELD_IGNORE) {
	ignore:
			dp->tdir_tag = IGNORE;
			continue;
		}
		/*
		 * Check data type.
		 */
		fip = tif->tif_fieldinfo[fix];
		while (dp->tdir_type != (u_short) fip->field_type) {
			if (fip->field_type == TIFF_ANY)	/* wildcard */
				break;
			fip++, fix++;
			if (fix == tif->tif_nfields ||
			    fip->field_tag != dp->tdir_tag) {
				TIFFWarning(tif->tif_name,
				   "wrong data type %d for \"%s\"; tag ignored",
				    dp->tdir_type, fip[-1].field_name);
				goto ignore;
			}
		}
		/*
		 * Check count if known in advance.
		 */
		if (fip->field_readcount != TIFF_VARIABLE) {
			uint32 expected = (fip->field_readcount == TIFF_SPP) ?
			    (uint32) td->td_samplesperpixel :
			    (uint32) fip->field_readcount;
			if (!CheckDirCount(tif, dp, expected))
				goto ignore;
		}

		switch (dp->tdir_tag) {
		case TIFFTAG_COMPRESSION:
			/*
			 * The 5.0 spec says the Compression tag has
			 * one value, while earlier specs say it has
			 * one value per sample.  Because of this, we
			 * accept the tag if one value is supplied.
			 */
			if (dp->tdir_count == 1) {
				v = TIFFExtractData(tif,
				    dp->tdir_type, dp->tdir_offset);
				if (!TIFFSetField(tif, dp->tdir_tag, (int)v))
					goto bad;
				break;
			}
			if (!TIFFFetchPerSampleShorts(tif, dp, &iv) ||
			    !TIFFSetField(tif, dp->tdir_tag, iv))
				goto bad;
			dp->tdir_tag = IGNORE;
			break;
		case TIFFTAG_STRIPOFFSETS:
		case TIFFTAG_STRIPBYTECOUNTS:
		case TIFFTAG_TILEOFFSETS:
		case TIFFTAG_TILEBYTECOUNTS:
			TIFFSetFieldBit(tif, fip->field_bit);
			break;
		case TIFFTAG_IMAGEWIDTH:
		case TIFFTAG_IMAGELENGTH:
		case TIFFTAG_IMAGEDEPTH:
		case TIFFTAG_TILELENGTH:
		case TIFFTAG_TILEWIDTH:
		case TIFFTAG_TILEDEPTH:
		case TIFFTAG_PLANARCONFIG:
		case TIFFTAG_ROWSPERSTRIP:
			if (!TIFFFetchNormalTag(tif, dp))
				goto bad;
			dp->tdir_tag = IGNORE;
			break;
		case TIFFTAG_EXTRASAMPLES:
			(void) TIFFFetchExtraSamples(tif, dp);
			dp->tdir_tag = IGNORE;
			break;
		}
	}

	/*
	 * Allocate directory structure and setup defaults.
	 */
	if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
		MissingRequired(tif, "ImageLength");
		goto bad;
	}
	if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
		MissingRequired(tif, "PlanarConfiguration");
		goto bad;
	}
	/* 
 	 * Setup appropriate structures (by strip or by tile)
	 */
	if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) {
		td->td_nstrips = TIFFNumberOfStrips(tif);
		td->td_tilewidth = td->td_imagewidth;
		td->td_tilelength = td->td_rowsperstrip;
		td->td_tiledepth = td->td_imagedepth;
		tif->tif_flags &= ~TIFF_ISTILED;
	} else {
		td->td_nstrips = TIFFNumberOfTiles(tif);
		tif->tif_flags |= TIFF_ISTILED;
	}
	td->td_stripsperimage = td->td_nstrips;
	if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
		td->td_stripsperimage /= td->td_samplesperpixel;
	if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) {
		MissingRequired(tif,
		    isTiled(tif) ? "TileOffsets" : "StripOffsets");
		goto bad;
	}

	/*
	 * Second pass: extract other information.
	 */
	for (dp = dir, n = dircount; n > 0; n--, dp++) {
		if (dp->tdir_tag == IGNORE)
			continue;
		switch (dp->tdir_tag) {
		case TIFFTAG_MINSAMPLEVALUE:
		case TIFFTAG_MAXSAMPLEVALUE:
		case TIFFTAG_BITSPERSAMPLE:
			/*
			 * The 5.0 spec says the Compression tag has
			 * one value, while earlier specs say it has
			 * one value per sample.  Because of this, we
			 * accept the tag if one value is supplied.
			 *
			 * The MinSampleValue, MaxSampleValue and
			 * BitsPerSample tags are supposed to be written
			 * as one value/sample, but some vendors incorrectly
			 * write one value only -- so we accept that
			 * as well (yech).
			 */
			if (dp->tdir_count == 1) {
				v = TIFFExtractData(tif,
				    dp->tdir_type, dp->tdir_offset);
				if (!TIFFSetField(tif, dp->tdir_tag, (int)v))
					goto bad;
				break;
			}
			/* fall thru... */
		case TIFFTAG_DATATYPE:
		case TIFFTAG_SAMPLEFORMAT:
			if (!TIFFFetchPerSampleShorts(tif, dp, &iv) ||
			    !TIFFSetField(tif, dp->tdir_tag, iv))
				goto bad;
			break;
		case TIFFTAG_SMINSAMPLEVALUE:
		case TIFFTAG_SMAXSAMPLEVALUE:
			if (!TIFFFetchPerSampleAnys(tif, dp, &dv) ||
			    !TIFFSetField(tif, dp->tdir_tag, dv))
				goto bad;
			break;
		case TIFFTAG_STRIPOFFSETS:
		case TIFFTAG_TILEOFFSETS:
			if (!TIFFFetchStripThing(tif, dp,
			    td->td_nstrips, &td->td_stripoffset))
				goto bad;
			break;
		case TIFFTAG_STRIPBYTECOUNTS:
		case TIFFTAG_TILEBYTECOUNTS:
			if (!TIFFFetchStripThing(tif, dp,
			    td->td_nstrips, &td->td_stripbytecount))
				goto bad;
			break;
		case TIFFTAG_COLORMAP:
		case TIFFTAG_TRANSFERFUNCTION:
			/*
			 * TransferFunction can have either 1x or 3x data
			 * values; Colormap can have only 3x items.
			 */
			v = 1L<<td->td_bitspersample;
			if (dp->tdir_tag == TIFFTAG_COLORMAP ||
			    dp->tdir_count != (uint32) v) {
				if (!CheckDirCount(tif, dp, (uint32)(3*v)))
					break;
			}
			v *= sizeof (uint16);
			cp = CheckMalloc(tif, dp->tdir_count * sizeof (uint16),
			    "to read \"TransferFunction\" tag");
			if (cp != NULL) {
				if (TIFFFetchData(tif, dp, cp)) {
					/*
					 * This deals with there being only
					 * one array to apply to all samples.
					 */
					uint32 c =
					    (uint32)1 << td->td_bitspersample;
					if (dp->tdir_count == c)
						v = 0;
					TIFFSetField(tif, dp->tdir_tag,
					    cp, cp+v, cp+2*v);
				}
				_TIFFfree(cp);
			}
			break;
		case TIFFTAG_PAGENUMBER:
		case TIFFTAG_HALFTONEHINTS:
		case TIFFTAG_YCBCRSUBSAMPLING:
		case TIFFTAG_DOTRANGE:
			(void) TIFFFetchShortPair(tif, dp);
			break;
#ifdef COLORIMETRY_SUPPORT
		case TIFFTAG_REFERENCEBLACKWHITE:
			(void) TIFFFetchRefBlackWhite(tif, dp);
			break;
#endif
/* BEGIN REV 4.0 COMPATIBILITY */
		case TIFFTAG_OSUBFILETYPE:
			v = 0;
			switch (TIFFExtractData(tif, dp->tdir_type,
			    dp->tdir_offset)) {
			case OFILETYPE_REDUCEDIMAGE:
				v = FILETYPE_REDUCEDIMAGE;
				break;
			case OFILETYPE_PAGE:
				v = FILETYPE_PAGE;
				break;
			}
			if (v)
				(void) TIFFSetField(tif,
				    TIFFTAG_SUBFILETYPE, (int)v);
			break;
/* END REV 4.0 COMPATIBILITY */
		default:
			(void) TIFFFetchNormalTag(tif, dp);
			break;
		}
	}
	/*
	 * Verify Palette image has a Colormap.
	 */
	if (td->td_photometric == PHOTOMETRIC_PALETTE &&
	    !TIFFFieldSet(tif, FIELD_COLORMAP)) {
		MissingRequired(tif, "Colormap");
		goto bad;
	}
	/*
	 * Attempt to deal with a missing StripByteCounts tag.
	 */
	if (!TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS)) {
		/*
		 * Some manufacturers violate the spec by not giving
		 * the size of the strips.  In this case, assume there
		 * is one uncompressed strip of data.
		 */
		if ((td->td_planarconfig == PLANARCONFIG_CONTIG &&
		    td->td_nstrips > 1) ||
		    (td->td_planarconfig == PLANARCONFIG_SEPARATE &&
		     td->td_nstrips != td->td_samplesperpixel)) {
		    MissingRequired(tif, "StripByteCounts");
		    goto bad;
		}
		TIFFWarning(tif->tif_name,
			"TIFF directory is missing required \"%s\" field, calculating from imagelength",
		    _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name);
		EstimateStripByteCounts(tif, dir, dircount);
#define	BYTECOUNTLOOKSBAD \
    ((td->td_stripbytecount[0] == 0 && td->td_stripoffset[0] != 0) || \
    (td->td_compression == COMPRESSION_NONE && \
     td->td_stripbytecount[0] > TIFFGetFileSize(tif) - td->td_stripoffset[0]))
	} else if (td->td_nstrips == 1 && BYTECOUNTLOOKSBAD) {
		/*
		 * Plexus (and others) sometimes give a value
		 * of zero for a tag when they don't know what
		 * the correct value is!  Try and handle the
		 * simple case of estimating the size of a one
		 * strip image.
		 */
		TIFFWarning(tif->tif_name,
	    "Bogus \"%s\" field, ignoring and calculating from imagelength",
		    _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name);
		EstimateStripByteCounts(tif, dir, dircount);
	}
	if (dir)
		_TIFFfree((char *)dir);
	if (!TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE))
		td->td_maxsamplevalue = (uint16)((1L<<td->td_bitspersample)-1);
	/*
	 * Setup default compression scheme.
	 */
	if (!TIFFFieldSet(tif, FIELD_COMPRESSION))
		TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
        /*
         * Some manufacturers make life difficult by writing
	 * large amounts of uncompressed data as a single strip.
	 * This is contrary to the recommendations of the spec.
         * The following makes an attempt at breaking such images
	 * into strips closer to the recommended 8k bytes.  A
	 * side effect, however, is that the RowsPerStrip tag
	 * value may be changed.
         */
	if (td->td_nstrips == 1 && td->td_compression == COMPRESSION_NONE &&
	    (tif->tif_flags & (TIFF_STRIPCHOP|TIFF_ISTILED)) == TIFF_STRIPCHOP)
		ChopUpSingleUncompressedStrip(tif);
	/*
	 * Reinitialize i/o since we are starting on a new directory.
	 */
	tif->tif_row = (uint32) -1;
	tif->tif_curstrip = (tstrip_t) -1;
	tif->tif_col = (uint32) -1;
	tif->tif_curtile = (ttile_t) -1;
	tif->tif_tilesize = TIFFTileSize(tif);
	tif->tif_scanlinesize = TIFFScanlineSize(tif);
	return (1);
bad:
	if (dir)
		_TIFFfree(dir);
	return (0);
}