コード例 #1
0
ファイル: tiffgt.c プロジェクト: badwtg1111/tiff
static int
initImage(void)
{
        uint32 w, h;

        if (order)
                TIFFSetField(tif, TIFFTAG_FILLORDER, order);
        if (photo != (uint16) -1)
                TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photo);
        if (!TIFFRGBAImageBegin(&img, tif, stoponerr, title)) {
                TIFFError(filelist[fileindex], "%s", title);
                TIFFClose(tif);
                tif = NULL;
                return -1;
        }

        /*
         * Setup the image raster as required.
         */
        h = img.height;
        w = img.width;
        if (h > ymax) {
                w = (int)(w * ((float)ymax / h));
                h = ymax;
        }
        if (w > xmax) {
                h = (int)(h * ((float)xmax / w));
                w = xmax;
        }

	if (w != width || h != height) {
		uint32 rastersize =
			_TIFFMultiply32(tif, img.width, img.height, "allocating raster buffer");
		if (raster != NULL)
			_TIFFfree(raster), raster = NULL;
		raster = (uint32*) _TIFFCheckMalloc(tif, rastersize, sizeof (uint32),
						    "allocating raster buffer");
		if (raster == NULL) {
			width = height = 0;
			TIFFError(filelist[fileindex], "No space for raster buffer");
			cleanup_and_exit();
		}
		width = w;
		height = h;
	}
	TIFFRGBAImageGet(&img, raster, img.width, img.height);
#if HOST_BIGENDIAN
	TIFFSwabArrayOfLong(raster,img.width*img.height);
#endif
	return 0;
}
コード例 #2
0
ファイル: tif_dirinfo.c プロジェクト: hjmjohnson/vxl
int
_TIFFMergeFields(TIFF* tif, const TIFFField info[], uint32 n)
{
	static const char module[] = "_TIFFMergeFields";
	static const char reason[] = "for fields array";
	/* TIFFField** tp; */
	uint32 i;

        tif->tif_foundfield = NULL;

	if (tif->tif_fields && tif->tif_nfields > 0) {
		tif->tif_fields = (TIFFField**)
			_TIFFCheckRealloc(tif, tif->tif_fields,
					  (tif->tif_nfields + n),
					  sizeof(TIFFField *), reason);
	} else {
		tif->tif_fields = (TIFFField **)
			_TIFFCheckMalloc(tif, n, sizeof(TIFFField *),
					 reason);
	}
	if (!tif->tif_fields) {
		TIFFErrorExt(tif->tif_clientdata, module,
			     "Failed to allocate fields array");
		return 0;
	}

	/* tp = tif->tif_fields + tif->tif_nfields; */
	for (i = 0; i < n; i++) {
		const TIFFField *fip =
			TIFFFindField(tif, info[i].field_tag, TIFF_ANY);

                /* only add definitions that aren't already present */
		if (!fip) {
                        tif->tif_fields[tif->tif_nfields] = (TIFFField *) (info+i);
                        tif->tif_nfields++;
                }
	}

        /* Sort the field info by tag number */
	qsort(tif->tif_fields, tif->tif_nfields,
	      sizeof(TIFFField *), tagCompare);

	return n;
}
コード例 #3
0
ファイル: tif_dirinfo.c プロジェクト: dreamsxin/ultimatepp
int
_TIFFMergeFieldInfo(TIFF* tif, const TIFFFieldInfo info[], int n)
{
	static const char module[] = "_TIFFMergeFieldInfo";
	static const char reason[] = "for field info array";
	TIFFFieldInfo** tp;
	int i;

        tif->tif_foundfield = NULL;

	if (tif->tif_nfields > 0) {
		tif->tif_fieldinfo = (TIFFFieldInfo**)
			_TIFFCheckRealloc(tif, tif->tif_fieldinfo,
					  (tif->tif_nfields + n),
					  sizeof (TIFFFieldInfo*), reason);
	} else {
		tif->tif_fieldinfo = (TIFFFieldInfo**)
			_TIFFCheckMalloc(tif, n, sizeof (TIFFFieldInfo*),
					 reason);
	}
	if (!tif->tif_fieldinfo) {
		TIFFErrorExt(tif->tif_clientdata, module,
			     "Failed to allocate field info array");
		return 0;
	}
	tp = tif->tif_fieldinfo + tif->tif_nfields;
	for (i = 0; i < n; i++)
        {
            const TIFFFieldInfo *fip =
                _TIFFFindFieldInfo(tif, info[i].field_tag, info[i].field_type);

            /* only add definitions that aren't already present */
            if (!fip) {
                *tp++ = (TIFFFieldInfo*) (info + i);
                tif->tif_nfields++;
            }
        }

        /* Sort the field info by tag number */
        qsort(tif->tif_fieldinfo, tif->tif_nfields,
	      sizeof (TIFFFieldInfo*), tagCompare);

	return n;
}
コード例 #4
0
ファイル: tif_dirinfo.c プロジェクト: hjmjohnson/vxl
int
TIFFMergeFieldInfo(TIFF* tif, const TIFFFieldInfo info[], uint32 n)
{
	static const char module[] = "TIFFMergeFieldInfo";
	static const char reason[] = "for fields array";
	TIFFField *tp;
	size_t nfields;
	uint32 i;

	if (tif->tif_nfieldscompat > 0) {
		tif->tif_fieldscompat = (TIFFFieldArray *)
			_TIFFCheckRealloc(tif, tif->tif_fieldscompat,
					  tif->tif_nfieldscompat + 1,
					  sizeof(TIFFFieldArray), reason);
	} else {
		tif->tif_fieldscompat = (TIFFFieldArray *)
			_TIFFCheckMalloc(tif, 1, sizeof(TIFFFieldArray),
					 reason);
	}
	if (!tif->tif_fieldscompat) {
		TIFFErrorExt(tif->tif_clientdata, module,
			     "Failed to allocate fields array");
		return -1;
	}
	nfields = tif->tif_nfieldscompat++;

	tif->tif_fieldscompat[nfields].type = tfiatOther;
	tif->tif_fieldscompat[nfields].allocated_size = n;
	tif->tif_fieldscompat[nfields].count = n;
	tif->tif_fieldscompat[nfields].fields =
		(TIFFField *)_TIFFCheckMalloc(tif, n, sizeof(TIFFField),
					      reason);
	if (!tif->tif_fieldscompat[nfields].fields) {
		TIFFErrorExt(tif->tif_clientdata, module,
			     "Failed to allocate fields array");
		return -1;
	}

	tp = tif->tif_fieldscompat[nfields].fields;
	for (i = 0; i < n; i++) {
		tp->field_tag = info[i].field_tag;
		tp->field_readcount = info[i].field_readcount;
		tp->field_writecount = info[i].field_writecount;
		tp->field_type = info[i].field_type;
		tp->reserved = 0;
		tp->set_field_type =
		     _TIFFSetGetType(info[i].field_type,
				info[i].field_readcount,
				info[i].field_passcount);
		tp->get_field_type =
		     _TIFFSetGetType(info[i].field_type,
				info[i].field_readcount,
				info[i].field_passcount);
		tp->field_bit = info[i].field_bit;
		tp->field_oktochange = info[i].field_oktochange;
		tp->field_passcount = info[i].field_passcount;
		tp->field_name = info[i].field_name;
		tp->field_subfields = NULL;
		tp++;
	}

	if (!_TIFFMergeFields(tif, tif->tif_fieldscompat[nfields].fields, n)) {
		TIFFErrorExt(tif->tif_clientdata, module,
			     "Setting up field info failed");
		return -1;
	}

	return 0;
}
コード例 #5
0
static int
tiffcvt(TIFF* in, TIFF* out)
{
	uint32 width, height;		/* image width & height */
	uint32* raster;			/* retrieve RGBA image */
	uint16 shortv;
	float floatv;
	char *stringv;
	uint32 longv;

	size_t pixel_count;
	TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width);
	TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height);
	pixel_count = width * height;

	/* XXX: Check the integer overflow. */
	if (!width || !height || pixel_count / width != height) {
		TIFFError(TIFFFileName(in),
			  "Malformed input file; "
			  "can't allocate buffer for raster of %lux%lu size",
			  (unsigned long)width, (unsigned long)height);
		return 0;
	}

	raster = (uint32*)_TIFFCheckMalloc(in, pixel_count, sizeof(uint32),
					   "raster buffer");
	if (raster == 0) {
		TIFFError(TIFFFileName(in),
			  "Requested buffer size is %lu elements %lu each",
			  (unsigned long)pixel_count,
			  (unsigned long)sizeof(uint32));
		return (0);
	}

	if (!TIFFReadRGBAImage(in, width, height, raster, 0)) {
		_TIFFfree(raster);
		return (0);
	}

	CopyField(TIFFTAG_SUBFILETYPE, longv);
	TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
	TIFFSetField(out, TIFFTAG_IMAGELENGTH, height);
	TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8);
	TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
	TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
	if (compression == COMPRESSION_JPEG)
		TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RAW);
	CopyField(TIFFTAG_FILLORDER, shortv);
	TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
	TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 3);
	CopyField(TIFFTAG_XRESOLUTION, floatv);
	CopyField(TIFFTAG_YRESOLUTION, floatv);
	CopyField(TIFFTAG_RESOLUTIONUNIT, shortv);
	TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
	{ char buf[2048];
	  char *cp = strrchr(TIFFFileName(in), '/');
	  sprintf(buf, "YCbCr conversion of %s", cp ? cp+1 : TIFFFileName(in));
	  TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, buf);
	}
	TIFFSetField(out, TIFFTAG_SOFTWARE, TIFFGetVersion());
	CopyField(TIFFTAG_DOCUMENTNAME, stringv);

	TIFFSetField(out, TIFFTAG_REFERENCEBLACKWHITE, refBlackWhite);
	TIFFSetField(out, TIFFTAG_YCBCRSUBSAMPLING,
	    horizSubSampling, vertSubSampling);
	TIFFSetField(out, TIFFTAG_YCBCRPOSITIONING, YCBCRPOSITION_CENTERED);
	TIFFSetField(out, TIFFTAG_YCBCRCOEFFICIENTS, ycbcrCoeffs);
	rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip);
	TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);

	return (cvtRaster(out, raster, width, height));
}
コード例 #6
0
ファイル: tiff2rgba.c プロジェクト: ScaledLizard/ResIL
static int
cvt_whole_image( TIFF *in, TIFF *out )

{
    uint32* raster;			/* retrieve RGBA image */
    uint32  width, height;		/* image width & height */
    uint32  row;
    size_t pixel_count;
        
    TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width);
    TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height);
    pixel_count = width * height;

    /* XXX: Check the integer overflow. */
    if (!width || !height || pixel_count / width != height) {
        TIFFError(TIFFFileName(in),
		  "Malformed input file; can't allocate buffer for raster of %lux%lu size",
		  (unsigned long)width, (unsigned long)height);
        return 0;
    }

    rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip);
    TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);

    raster = (uint32*)_TIFFCheckMalloc(in, pixel_count, sizeof(uint32), "raster buffer");
    if (raster == 0) {
        TIFFError(TIFFFileName(in), "Failed to allocate buffer (%lu elements of %lu each)",
		  (unsigned long)pixel_count, (unsigned long)sizeof(uint32));
        return (0);
    }

    /* Read the image in one chunk into an RGBA array */
    if (!TIFFReadRGBAImageOriented(in, width, height, raster,
                                   ORIENTATION_TOPLEFT, 0)) {
        _TIFFfree(raster);
        return (0);
    }

    /*
     * XXX: raster array has 4-byte unsigned integer type, that is why
     * we should rearrange it here.
     */
#if HOST_BIGENDIAN
    TIFFSwabArrayOfLong(raster, width * height);
#endif

    /*
     * Do we want to strip away alpha components?
     */
    if (no_alpha)
    {
        size_t count = pixel_count;
        unsigned char *src, *dst;

	src = dst = (unsigned char *) raster;
        while (count > 0)
        {
	    *(dst++) = *(src++);
	    *(dst++) = *(src++);
	    *(dst++) = *(src++);
	    src++;
	    count--;
        }
    }

    /*
     * Write out the result in strips
     */
    for (row = 0; row < height; row += rowsperstrip)
    {
        unsigned char * raster_strip;
        int	rows_to_write;
        int	bytes_per_pixel;

        if (no_alpha)
        {
            raster_strip = ((unsigned char *) raster) + 3 * row * width;
            bytes_per_pixel = 3;
        }
        else
        {
            raster_strip = (unsigned char *) (raster + row * width);
            bytes_per_pixel = 4;
        }

        if( row + rowsperstrip > height )
            rows_to_write = height - row;
        else
            rows_to_write = rowsperstrip;

        if( TIFFWriteEncodedStrip( out, row / rowsperstrip, raster_strip,
                             bytes_per_pixel * rows_to_write * width ) == -1 )
        {
            _TIFFfree( raster );
            return 0;
        }
    }

    _TIFFfree( raster );

    return 1;
}
コード例 #7
0
ファイル: tif_dirwrite.c プロジェクト: rajvikram/weaver
/*
 * 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)
{
	uint64 dircount;	/* 16-bit or 64-bit directory entry count */
	toff_t diroff;		/* 32-bit or 64-bit directory offset */
	ttag_t tag;
	uint32 nfields;
	tsize_t dirsize;
	char* data;
	TIFFDirEntry* dir;
	TIFFDirectory* td;
	unsigned 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)) {
				TIFFErrorExt(tif->tif_clientdata, 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)) {
			TIFFErrorExt(tif->tif_clientdata, 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);
	}


	/*
	 * Loop to allow retry in case transition to BigTIFF required
	 */
	while (1) {

	/*
	 * 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 bad2;

	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 * TDIREntryLen(tif);
	data = (char*) _TIFFmalloc(dirsize);
	if (data == NULL) {
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
		    "Cannot write directory, out of space");
		goto bad2;
	}
	_TIFFmemset(data, 0, dirsize);
	/*
	 * 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 -= TDIREntryLen(tif);
	}								/*XXX*/

	tif->tif_dataoff = tif->tif_diroff + TIFFDirCntLen(tif) + dirsize + TIFFDirOffLen(tif);
	(void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET);
	dir = (TIFFDirEntry*) data;
	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;
			
			dir->s.tdir_tag = (uint16) tag;
			TDIRSetEntryCount(tif,dir, (uint32) td->td_nstrips);
			/*
			 * If file is BigTIFF strip/tile offsets are written as 64-bit, 
			 * else convert to array of 32-bit offsets.
			 */
			if (isBigTIFF(tif)) {
				dir->s.tdir_type = (uint16) TIFF_LONG8;
				if (!TIFFWriteLong8Array(tif, dir, td->td_stripoffset))
					goto bad;
			} else {
				uint32 tdi;
				int status;
				uint32 *soff = _TIFFCheckMalloc(tif, td->td_nstrips, 
						sizeof(uint32), "32-bit offset array");

				dir->s.tdir_type = (uint16) TIFF_LONG;
				for (tdi = 0; tdi < td->td_nstrips; tdi++)
					soff[tdi] = (uint32) td->td_stripoffset[tdi];
				status = TIFFWriteLongArray(tif, dir, soff);
				_TIFFfree(soff);
				if (!status)
					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;
			dir->s.tdir_tag = (uint16) tag;
			dir->s.tdir_type = (uint16) TIFF_LONG;
			TDIRSetEntryCount(tif,dir, (uint32) td->td_nstrips);
			if (!TIFFWriteLongArray(tif, dir, 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);
			TDIREntryNext(tif,dir);
			TIFFSetupShortLong(tif, TIFFTAG_IMAGELENGTH,
			    dir, td->td_imagelength);
			break;
		case FIELD_TILEDIMENSIONS:
			TIFFSetupShortLong(tif, TIFFTAG_TILEWIDTH,
			    dir, td->td_tilewidth);
			TDIREntryNext(tif,dir);
			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:
		case FIELD_YCBCRSUBSAMPLING:
			if (!TIFFSetupShortPair(tif, fip->field_tag, dir))
				goto bad;
			break;
		case FIELD_INKNAMES:
			if (!TIFFWriteInkNames(tif, dir))
				goto bad;
			break;
		case FIELD_TRANSFERFUNCTION:
			if (!TIFFWriteTransferFunction(tif, dir))
				goto bad;
			break;
		case FIELD_SUBIFD:
			/*
			 * 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 file is BigTIFF subdirectory offsets are written as 64-bit, 
			 * else as array of 32-bit offsets.  At this point the actual
			 * offset values are unknown (will be set in TIFFLinkDirectory).
			 */
			dir->s.tdir_tag = (uint16) fip->field_tag;
			TDIRSetEntryCount(tif,dir, (uint32) td->td_nsubifd);
			TDIRSetEntryOff(tif,dir, 0);
			if (td->td_nsubifd > 0) {
				tif->tif_flags |= TIFF_INSUBIFD;
				if (isBigTIFF(tif)) {
					toff_t *doff = _TIFFCheckMalloc(tif, td->td_nsubifd, sizeof(toff_t),
						"Allocate SubIFD offset array");
					if (!doff) 
						goto bad;
					_TIFFmemset(doff, 0, td->td_nsubifd * sizeof(toff_t));
					dir->b.tdir_type = TIFF_IFD8;
					if (td->td_nsubifd > TIFFDirOffLen(tif) / sizeof(toff_t))
						tif->tif_subifdoff = tif->tif_dataoff;
					else
						tif->tif_subifdoff = tif->tif_diroff + TIFFDirCntLen(tif) + 
							(char*) &dir->b.tdir_offset - data;
					if (!TIFFWriteLong8Array(tif, dir, (toff_t*) doff))
						goto bad;
					_TIFFfree(doff);
				} else {
					uint32 *doff = _TIFFCheckMalloc(tif, td->td_nsubifd, sizeof(uint32),
						"Allocate SubIFD offset array");
					if (!doff) 
						goto bad;
					_TIFFmemset(doff, 0, td->td_nsubifd * sizeof(uint32));
					dir->b.tdir_type = TIFF_LONG;
					if (td->td_nsubifd > TIFFDirOffLen(tif) / sizeof(uint32))
						tif->tif_subifdoff = tif->tif_dataoff;
					else
						tif->tif_subifdoff = tif->tif_diroff + TIFFDirCntLen(tif) + 
							(char*) &dir->s.tdir_offset - data;
					if (!TIFFWriteLongArray(tif, dir, doff))
						goto bad;
					_TIFFfree(doff);
				}
			}
			break;
		default:
			/* XXX: Should be fixed and removed. */
			if (fip->field_tag == TIFFTAG_DOTRANGE) {
				if (!TIFFSetupShortPair(tif, fip->field_tag, dir))
					goto bad;
			}
			else if (!TIFFWriteNormalTag(tif, dir, fip))
				goto bad;
			break;
		}
		TDIREntryNext(tif,dir);
                
                if( fip->field_bit != FIELD_CUSTOM )
                    ResetFieldBit(fields, fip->field_bit);
	}

	/*
	 * Check if BigTIFF now required based on data location.  If so reset 
	 * data offset to overwrite already-written data for directory, then
	 * convert file to BigTIFF and loop to recreate directory.
	 */
	if (isBigTIFF(tif) || !isBigOff(tif->tif_dataoff + sizeof(uint32)))
		break;

	_TIFFfree(data);
	tif->tif_dataoff = tif->tif_diroff;
	if (!TIFFMakeBigTIFF(tif))
		goto bad2;
	tif->tif_diroff = 0;
	}			/* bottom of BigTIFF retry loop */

	/*
	 * Write directory.
	 */
	tif->tif_curdir++;
	TIFFSetDirCnt(tif,dircount, (uint32) nfields);
	TIFFSetDirOff(tif,diroff,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.
		 */
		uint32 di;
		for (dir = (TIFFDirEntry*) data, di = 0; di < nfields; TDIREntryNext(tif,dir), di++) {
			TIFFSwabShort(&dir->s.tdir_tag);
			TIFFSwabShort(&dir->s.tdir_type);
			TDIRSwabEntryCount(tif,dir);
			TDIRSwabEntryOff(tif,dir);
		}
		TIFFSwabDirCnt(tif,&dircount);
		TIFFSwabDirOff(tif,&diroff);
	}
	(void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET);
	if (!WriteOK(tif, &dircount, TIFFDirCntLen(tif))) {
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
			"Error writing directory count (%d)", TIFFGetErrno(tif));
		goto bad;
	}
	if (!WriteOK(tif, data, dirsize)) {
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
			"Error writing directory contents (%d)", TIFFGetErrno(tif));
		goto bad;
	}
	if (!WriteOK(tif, &diroff, TIFFDirOffLen(tif))) {
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 
			"Error writing directory link (%d)", TIFFGetErrno(tif));
		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);
bad2:
	return (0);
}