home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1988 by Sam Leffler.
- * All rights reserved.
- *
- * This file is provided for unrestricted use provided that this
- * legend is included on all tape media and as a part of the
- * software program in whole or part. Users may copy, modify or
- * distribute this file at will.
- */
-
- /*
- Directory Support Routines.
- */
-
- #include "tiffio.h"
- #include <sys/stat.h>
- #include <io.h>
- #include <alloc.h>
- #include <mem.h>
- #include <stdarg.h>
- #include <process.h>
- #include <string.h>
- #include "tiffio.h"
-
- #define ReadOK(fd, buf, size) (read(fd, (char *)buf, size) == size)
- #define WriteOK(fd, buf, size) (write(fd, (char *)buf, size) == size)
- #define SeekOK(fd, off) (lseek(fd, (long)off, SEEK_SET) == (long)off)
-
- #define howmany(x, y) (((x)+((y)-1))/(y))
- #define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
-
- #define FieldSet(fields, f) (fields[f/32] & (1L<<(f&0x1f)))
- #define ResetFieldBit(fields, f) (fields[f/32] &= ~(1L<<(f&0x1f)))
-
- #define TIFFExtractData(tif, type, v) \
- ((tif)->tif_header.tiff_magic == TIFF_BIGENDIAN ? \
- ((v) >> (tif)->tif_typeshift[type]) & (tif)->tif_typemask[type] : \
- (v) & (tif)->tif_typemask[type])
- #define TIFFInsertData(tif, type, v) \
- ((tif)->tif_header.tiff_magic == TIFF_BIGENDIAN ? \
- ((v) & (tif)->tif_typemask[type]) << (tif)->tif_typeshift[type] : \
- (v) & (tif)->tif_typemask[type])
-
-
- /*
- This array is assumed to be sorted by tag.
- */
- static TIFFFieldInfo FieldInfo[] =
- {
- { TIFFTAG_SUBFILETYPE, 1, LONG, FIELD_SUBFILETYPE,
- "SubfileType" },
- { TIFFTAG_OSUBFILETYPE, 1, SHORT, FIELD_SUBFILETYPE,
- "OldSubfileType" },
- { TIFFTAG_IMAGEWIDTH, 1, LONG, FIELD_IMAGEDIMENSIONS,
- "ImageWidth" },
- { TIFFTAG_IMAGEWIDTH, 1, SHORT, FIELD_IMAGEDIMENSIONS,
- "ImageWidth" },
- { TIFFTAG_IMAGELENGTH, 1, LONG, FIELD_IMAGEDIMENSIONS,
- "ImageLength" },
- { TIFFTAG_IMAGELENGTH, 1, SHORT, FIELD_IMAGEDIMENSIONS,
- "ImageLength" },
- { TIFFTAG_BITSPERSAMPLE, -1, SHORT, FIELD_BITSPERSAMPLE,
- "BitsPerSample" },
- { TIFFTAG_COMPRESSION, 1, SHORT, FIELD_COMPRESSION,
- "Compression" },
- { TIFFTAG_PHOTOMETRIC, 1, SHORT, FIELD_PHOTOMETRIC,
- "PhotometricInterpretation" },
- { TIFFTAG_THRESHHOLDING, 1, SHORT, FIELD_THRESHHOLDING,
- "Threshholding" },
- { TIFFTAG_CELLWIDTH, 1, SHORT, 0xffff,
- "CellWidth" },
- { TIFFTAG_CELLLENGTH, 1, SHORT, 0xffff,
- "CellLength" },
- { TIFFTAG_FILLORDER, 1, SHORT, 0xffff,
- "FillOrder" },
- { TIFFTAG_DOCUMENTNAME, -1, ASCII, FIELD_DOCUMENTNAME,
- "DocumentName" },
- { TIFFTAG_IMAGEDESCRIPTION, -1, ASCII, FIELD_IMAGEDESCRIPTION,
- "ImageDescription" },
- { TIFFTAG_MAKE, -1, ASCII, FIELD_MAKE,
- "Make" },
- { TIFFTAG_MODEL, -1, ASCII, FIELD_MODEL,
- "Model" },
- { TIFFTAG_STRIPOFFSETS, -1, LONG, FIELD_STRIPOFFSETS,
- "StripOffsets" },
- { TIFFTAG_STRIPOFFSETS, -1, SHORT, FIELD_STRIPOFFSETS,
- "StripOffsets" },
- { TIFFTAG_ORIENTATION, 1, SHORT, FIELD_ORIENTATION,
- "Orientation" },
- { TIFFTAG_SAMPLESPERPIXEL, 1, SHORT, FIELD_SAMPLESPERPIXEL,
- "SamplesPerPixel" },
- { TIFFTAG_ROWSPERSTRIP, 1, LONG, FIELD_ROWSPERSTRIP,
- "RowsPerStrip" },
- { TIFFTAG_ROWSPERSTRIP, 1, SHORT, FIELD_ROWSPERSTRIP,
- "RowsPerStrip" },
- { TIFFTAG_STRIPBYTECOUNTS, -1, LONG, FIELD_STRIPBYTECOUNTS,
- "StripByteCounts" },
- { TIFFTAG_STRIPBYTECOUNTS, -1, SHORT, FIELD_STRIPBYTECOUNTS,
- "StripByteCounts" },
- { TIFFTAG_MINSAMPLEVALUE, -1, SHORT, FIELD_MINSAMPLEVALUE,
- "MinSampleValue" },
- { TIFFTAG_MAXSAMPLEVALUE, -1, SHORT, FIELD_MAXSAMPLEVALUE,
- "MaxSampleValue" },
- { TIFFTAG_XRESOLUTION, 1, RATIONAL, FIELD_RESOLUTION,
- "XResolution" },
- { TIFFTAG_YRESOLUTION, 1, RATIONAL, FIELD_RESOLUTION,
- "YResolution" },
- { TIFFTAG_PLANARCONFIG, 1, SHORT, FIELD_PLANARCONFIG,
- "PlanarConfiguration" },
- { TIFFTAG_PAGENAME, -1, ASCII, FIELD_PAGENAME,
- "PageName" },
- { TIFFTAG_XPOSITION, 1, RATIONAL, FIELD_POSITION,
- "XPosition" },
- { TIFFTAG_YPOSITION, 1, RATIONAL, FIELD_POSITION,
- "YPosition" },
- { TIFFTAG_FREEOFFSETS, -1, LONG, 0xffff,
- "FreeOffsets" },
- { TIFFTAG_FREEBYTECOUNTS, -1, LONG, 0xffff,
- "FreeByteCounts" },
- { TIFFTAG_GRAYRESPONSEUNIT, 1, SHORT, FIELD_GRAYRESPONSEUNIT,
- "GrayResponseUnit" },
- { TIFFTAG_GRAYRESPONSECURVE,-1, SHORT, FIELD_GRAYRESPONSECURVE,
- "GrayResponseCurve" },
- { TIFFTAG_GROUP3OPTIONS, 1, LONG, FIELD_GROUP3OPTIONS,
- "Group3Options" },
- { TIFFTAG_GROUP4OPTIONS, 1, LONG, FIELD_GROUP4OPTIONS,
- "Group4Options" },
- { TIFFTAG_RESOLUTIONUNIT, 1, SHORT, FIELD_RESOLUTIONUNIT,
- "ResolutionUnit" },
- { TIFFTAG_PAGENUMBER, 2, SHORT, FIELD_PAGENUMBER,
- "PageNumber" },
- { TIFFTAG_COLORRESPONSEUNIT, 1, SHORT, FIELD_COLORRESPONSEUNIT,
- "ColorResponseUnit" },
- { TIFFTAG_COLORRESPONSECURVE,-1,SHORT, FIELD_COLORRESPONSECURVE,
- "ColorResponseCurve" },
- { TIFFTAG_SOFTWARE, -1, ASCII, FIELD_SOFTWARE,
- "Software" },
- { TIFFTAG_DATETIME, -1, ASCII, FIELD_DATETIME,
- "DateTime" },
- { TIFFTAG_ARTIST, -1, ASCII, FIELD_ARTIST,
- "Artist" },
- { TIFFTAG_HOSTCOMPUTER, -1, ASCII, FIELD_HOSTCOMPUTER,
- "HostComputer" },
- { TIFFTAG_PREDICTOR, 1, SHORT, FIELD_PREDICTOR,
- "Predictor" },
- { TIFFTAG_COLORMAP, -1, SHORT, FIELD_COLORMAP,
- "ColorMap" }
- };
- #define NFIELDINFO (sizeof (FieldInfo) / sizeof (FieldInfo[0]))
-
- #define IGNORE 0 /* tag placeholder used below */
-
- static unsigned datawidth[] =
- {
- 1, /* nothing */
- 1, /* BYTE */
- 1, /* ASCII */
- 2, /* SHORT */
- 4, /* LONG */
- 8, /* RATIONAL */
- };
-
-
- static TIFFFieldInfo *
- FieldWithTag(unsigned tag)
- {
- register TIFFFieldInfo *fip;
-
- for (fip = FieldInfo; fip < &FieldInfo[NFIELDINFO]; fip++)
- if (fip->field_tag == tag)
- return (fip);
- TIFFError("FieldWithTag", "Internal error, unknown tag 0x%x", tag);
- exit(-1);
- return((TIFFFieldInfo *) 0);
- }
-
- /*
- Record the value of a field in the
- internal directory structure. The
- field will be written to the file
- when/if the directory structure is
- updated.
- */
-
- CompletionCode TIFFSetField(TIFF *tif, unsigned tag, ...)
- {
- static char module[] = "TIFFSetField";
- TIFFDirectory *td = &tif->tif_dir;
- va_list ap;
- long v;
- int field = -1;
- int status = TRUE;
-
- if (tag != TIFFTAG_IMAGELENGTH && (tif->tif_flags & TIFF_BEENWRITING))
- {
- TIFFError(module,"%s: Cannot change TIFF directory while writing",
- tif->tif_name);
- return (FALSE);
- }
- va_start(ap,tag);
- switch (tag)
- {
- case TIFFTAG_SUBFILETYPE:
- td->td_subfiletype = va_arg(ap, unsigned long);
- field = FIELD_SUBFILETYPE;
- break;
- case TIFFTAG_IMAGEWIDTH:
- td->td_imagewidth = va_arg(ap, unsigned long);
- field = FIELD_IMAGEDIMENSIONS;
- break;
- case TIFFTAG_IMAGELENGTH:
- td->td_imagelength = va_arg(ap, unsigned long);
- field = FIELD_IMAGEDIMENSIONS;
- break;
- case TIFFTAG_BITSPERSAMPLE:
- td->td_bitspersample = va_arg(ap, unsigned);
- field = FIELD_BITSPERSAMPLE;
- break;
- case TIFFTAG_COMPRESSION:
- v = va_arg(ap, unsigned) & 0xffff;
- /*
- If we're changing the compression scheme,
- then notify the previous module so that it
- can cleanup any state it's setup.
- */
- if (TIFFFieldSet(tif, FIELD_COMPRESSION))
- {
- if (td->td_compression == v)
- break;
- if (tif->tif_cleanup)
- (*tif->tif_cleanup)(tif);
- }
- /* Setup new compression routine state. */
- if ((status = TIFFSetCompressionScheme(tif, (unsigned) v)) == TRUE)
- {
- td->td_compression = (unsigned) v;
- field = FIELD_COMPRESSION;
- }
- break;
- case TIFFTAG_PHOTOMETRIC:
- td->td_photometric = va_arg(ap, unsigned);
- field = FIELD_PHOTOMETRIC;
- break;
- case TIFFTAG_THRESHHOLDING:
- td->td_threshholding = va_arg(ap, unsigned);
- field = FIELD_THRESHHOLDING;
- break;
- case TIFFTAG_DOCUMENTNAME:
- td->td_documentname = va_arg(ap, char *);
- field = FIELD_DOCUMENTNAME;
- break;
- case TIFFTAG_ARTIST:
- td->td_artist = va_arg(ap, char *);
- field = FIELD_ARTIST;
- break;
- case TIFFTAG_DATETIME:
- td->td_datetime = va_arg(ap, char *);
- field = FIELD_DATETIME;
- break;
- case TIFFTAG_HOSTCOMPUTER:
- td->td_hostcomputer = va_arg(ap, char *);
- field = FIELD_HOSTCOMPUTER;
- break;
- case TIFFTAG_IMAGEDESCRIPTION:
- td->td_imagedescription = va_arg(ap, char *);
- field = FIELD_IMAGEDESCRIPTION;
- break;
- case TIFFTAG_MAKE:
- td->td_make = va_arg(ap, char *);
- field = FIELD_MAKE;
- break;
- case TIFFTAG_MODEL:
- td->td_model = va_arg(ap, char *);
- field = FIELD_MODEL;
- break;
- case TIFFTAG_SOFTWARE:
- td->td_software = va_arg(ap, char *);
- field = FIELD_SOFTWARE;
- break;
- case TIFFTAG_ORIENTATION:
- td->td_orientation = va_arg(ap, unsigned);
- field = FIELD_ORIENTATION;
- break;
- case TIFFTAG_SAMPLESPERPIXEL:
- v = va_arg(ap, unsigned);
- if (v == 0)
- goto badvalue;
- if (v > 4)
- {
- TIFFError(tif->tif_name,"Cannot handle %ld-channel data", v);
- goto bad;
- }
- td->td_samplesperpixel = (unsigned) v;
- field = FIELD_SAMPLESPERPIXEL;
- break;
- case TIFFTAG_ROWSPERSTRIP:
- v = va_arg(ap, long);
- if (v == 0)
- goto badvalue;
- td->td_rowsperstrip = v;
- field = FIELD_ROWSPERSTRIP;
- break;
- case TIFFTAG_MINSAMPLEVALUE:
- td->td_minsamplevalue = va_arg(ap, unsigned) & 0xffff;
- field = FIELD_MINSAMPLEVALUE;
- break;
- case TIFFTAG_MAXSAMPLEVALUE:
- td->td_maxsamplevalue = va_arg(ap, unsigned) & 0xffff;
- field = FIELD_MAXSAMPLEVALUE;
- break;
- case TIFFTAG_XRESOLUTION:
- td->td_xresolution = va_arg(ap, double);
- field = FIELD_RESOLUTION;
- break;
- case TIFFTAG_YRESOLUTION:
- td->td_yresolution = va_arg(ap, double);
- field = FIELD_RESOLUTION;
- break;
- case TIFFTAG_PLANARCONFIG:
- v = va_arg(ap, unsigned);
- td->td_planarconfig = (unsigned) v;
- field = FIELD_PLANARCONFIG;
- break;
- case TIFFTAG_PAGENAME:
- td->td_pagename = va_arg(ap, char *);
- field = FIELD_PAGENAME;
- break;
- case TIFFTAG_XPOSITION:
- td->td_xposition = va_arg(ap, double);
- field = FIELD_POSITION;
- break;
- case TIFFTAG_YPOSITION:
- td->td_yposition = va_arg(ap, double);
- field = FIELD_POSITION;
- break;
- case TIFFTAG_GRAYRESPONSEUNIT:
- td->td_grayresponseunit = va_arg(ap, unsigned);
- field = FIELD_GRAYRESPONSEUNIT;
- break;
- case TIFFTAG_GRAYRESPONSECURVE:
- td->td_grayresponsecurve = va_arg(ap, unsigned *);
- field = FIELD_GRAYRESPONSECURVE;
- break;
- case TIFFTAG_GROUP3OPTIONS:
- td->td_group3options = va_arg(ap, long);
- field = FIELD_GROUP3OPTIONS;
- break;
- case TIFFTAG_GROUP4OPTIONS:
- td->td_group4options = va_arg(ap, long);
- field = FIELD_GROUP4OPTIONS;
- break;
- case TIFFTAG_RESOLUTIONUNIT:
- td->td_resolutionunit = va_arg(ap, unsigned);
- field = FIELD_RESOLUTIONUNIT;
- break;
- case TIFFTAG_PAGENUMBER:
- td->td_pagenumber = va_arg(ap, unsigned);
- field = FIELD_PAGENUMBER;
- break;
- case TIFFTAG_COLORRESPONSEUNIT:
- td->td_colorresponseunit = va_arg(ap, unsigned);
- field = FIELD_COLORRESPONSEUNIT;
- break;
- case TIFFTAG_COLORRESPONSECURVE:
- td->td_redresponsecurve = va_arg(ap, unsigned *);
- td->td_greenresponsecurve = va_arg(ap, unsigned *);
- td->td_blueresponsecurve = va_arg(ap, unsigned *);
- field = FIELD_COLORRESPONSECURVE;
- break;
- case TIFFTAG_COLORMAP:
- td->td_redcolormap = va_arg(ap, unsigned *);
- td->td_greencolormap = va_arg(ap, unsigned *);
- td->td_bluecolormap = va_arg(ap, unsigned *);
- field = FIELD_COLORMAP;
- break;
- case TIFFTAG_PREDICTOR:
- td->td_predictor = va_arg(ap, unsigned);
- field = FIELD_PREDICTOR;
- break;
- }
- if (field >= 0)
- {
- TIFFSetFieldBit(tif, field);
- tif->tif_flags |= TIFF_DIRTYDIRECT;
- }
- va_end(ap);
- return (status);
- badvalue:
- TIFFError(tif->tif_name, "%d: Bad value for \"%s\"", v,
- FieldWithTag(tag)->field_name);
- bad:
- va_end(ap);
- return (FALSE);
- }
-
- static
- void MissingRequired(TIFF *tif, char *tagname)
- {
- TIFFError(tif->tif_name,
- "TIFF directory is missing required \"%s\" field", tagname);
- }
-
-
- /*
- Fetch a contiguous directory item.
- */
- static
- CompletionCode TIFFFetchData(TIFF *tif, TIFFDirEntry *dir, char *cp)
- {
- unsigned cc, w;
-
- w = datawidth[dir->tdir_type];
- cc = (unsigned)(dir->tdir_count * w);
-
- if (SeekOK(tif->tif_fd, dir->tdir_offset) && ReadOK(tif->tif_fd, cp, cc))
- {
- if (tif->tif_flags & TIFF_SWAB)
- {
- switch (dir->tdir_type)
- {
- case SHORT:
- TIFFSwabArrayOfShort((unsigned *) cp, (unsigned) dir->tdir_count);
- break;
- case LONG:
- TIFFSwabArrayOfLong((unsigned long *) cp, (unsigned)dir->tdir_count);
- break;
- case RATIONAL:
- TIFFSwabArrayOfLong((unsigned long *) cp, (unsigned)(2*dir->tdir_count));
- break;
- }
- }
- return (cc);
- }
- TIFFError(tif->tif_name, "Error fetching data for field \"%s\"",
- FieldWithTag(dir->tdir_tag)->field_name);
- return (FALSE);
- }
-
- /*
- Fetch a rational item from the file
- at offset off. We return the value
- as floating point number.
- */
- static double
- TIFFFetchRational(TIFF *tif, TIFFDirEntry *dir)
- {
- long l[2];
-
- if (!TIFFFetchData(tif, dir, (char *) l))
- return (1.0);
- if (l[1] == 0)
- {
- TIFFError(tif->tif_name, "%s: Rational with zero denominator",
- FieldWithTag(dir->tdir_tag)->field_name);
- return (1.0);
- }
- return ((double)l[0] / (double)l[1]);
- }
-
- static
- CompletionCode TIFFFetchPerSampleShorts(TIFF *tif, TIFFDirEntry *dir, long *pl)
- {
- unsigned v[4];
- unsigned i;
-
- switch ((unsigned) dir->tdir_count)
- {
- case 1:
- *pl = TIFFExtractData(tif, dir->tdir_type, dir->tdir_offset);
- return (TRUE); /* should check samplesperpixel */
- case 2:
- if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN)
- {
- v[0] = (unsigned) (dir->tdir_offset >> 16);
- v[1] = (unsigned) (dir->tdir_offset & 0xffff);
- }
- else
- {
- v[0] = (unsigned) (dir->tdir_offset & 0xffff);
- v[1] = (unsigned) (dir->tdir_offset >> 16);
- }
- break;
- default:
- if (!TIFFFetchData(tif, dir, (char *) v))
- return (FALSE);
- break;
- }
- if (tif->tif_dir.td_samplesperpixel != dir->tdir_count)
- {
- TIFFError(tif->tif_name, "Incorrect count %d for field \"%s\"",
- dir->tdir_count, FieldWithTag(dir->tdir_tag)->field_name);
- return (FALSE);
- }
- for (i = 1; i < dir->tdir_count; i++)
- if (v[i] != v[0])
- {
- TIFFError(tif->tif_name,"Cannot handle different per-sample values for field \"%s\"",
- FieldWithTag(dir->tdir_tag)->field_name);
- return (FALSE);
- }
- ok:
- *pl = v[0];
- return (TRUE);
- }
-
- static
- CompletionCode TIFFFetchStripThing(TIFF *tif, TIFFDirEntry *dir,
- long nstrips, unsigned long **lpp)
- {
- register unsigned long *lp;
- int status;
-
- if (nstrips != dir->tdir_count)
- {
- TIFFError(tif->tif_name,
- "Count mismatch for field \"%s\"; expecting %d, got %d",
- FieldWithTag(dir->tdir_tag)->field_name, nstrips,
- dir->tdir_count);
- return (FALSE);
- }
- /* Allocate space for strip information. */
- if (*lpp == NULL &&
- (*lpp = (unsigned long *)malloc((unsigned) (nstrips *
- sizeof (unsigned long)))) == NULL)
- {
- TIFFError(tif->tif_name, "No space for \"%s\" array",
- FieldWithTag(dir->tdir_tag)->field_name);
- return (FALSE);
- }
- lp = *lpp;
- status = 1;
- if (dir->tdir_type == (unsigned) SHORT)
- {
- /* Handle short->long expansion. */
- if (dir->tdir_count > 2)
- {
- char *dp = malloc((unsigned)(dir->tdir_count * datawidth[(unsigned)SHORT]));
- if (dp == NULL)
- {
- TIFFError(tif->tif_name,"No memory to fetch field \"%s\"",
- FieldWithTag(dir->tdir_tag)->field_name);
- return (FALSE);
- }
- status = TIFFFetchData(tif, dir, dp);
- if (status)
- {
- register unsigned *wp = (unsigned *)dp;
- while (nstrips-- > 0)
- *lp++ = *wp++;
- }
- free((char *) dp);
- }
- else
- {
- /* Extract data from offset field. */
- if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN)
- {
- *lp++ = dir->tdir_offset >> 16;
- *lp = dir->tdir_offset & 0xffff;
- }
- else
- {
- *lp++ = dir->tdir_offset & 0xffff;
- *lp = dir->tdir_offset >> 16;
- }
- }
- }
- else
- {
- if (dir->tdir_count > 1)
- status = TIFFFetchData(tif, dir, (char *) lp);
- else
- *lp = dir->tdir_offset;
- }
- return (status);
- }
-
-
- /*
- Read the next TIFF directory from a file
- and convert it to the internal format.
- We read directories sequentially.
- */
- CompletionCode TIFFReadDirectory(TIFF *tif)
- {
- register TIFFDirEntry *dp;
- register int n;
- register TIFFDirectory *td = NULL;
- TIFFDirEntry *dir = NULL;
- long v;
- TIFFFieldInfo *fip;
- unsigned dircount;
- char *cp;
- unsigned bytestoread;
-
- tif->tif_diroff = tif->tif_nextdiroff;
- if (tif->tif_diroff == 0) /* no more directories */
- return (FALSE);
-
- if (!SeekOK(tif->tif_fd, tif->tif_diroff))
- {
- TIFFError(tif->tif_name, "Seek error accessing TIFF directory");
- return (FALSE);
- }
- if (!ReadOK(tif->tif_fd, &dircount, sizeof (unsigned)))
- {
- TIFFError(tif->tif_name, "Can not read TIFF directory count");
- return (FALSE);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((unsigned *) &dircount);
-
- bytestoread = dircount * sizeof (TIFFDirEntry);
-
- dir = (TIFFDirEntry *)malloc(bytestoread);
- if (dir == NULL)
- {
- TIFFError(tif->tif_name, "No space to read TIFF directory");
- return (FALSE);
- }
- if (!ReadOK(tif->tif_fd, dir, bytestoread))
- {
- TIFFError(tif->tif_name, "Can not read TIFF directory");
- goto bad;
- }
- /* Read offset to next directory for sequential scans. */
- if (!ReadOK(tif->tif_fd, &tif->tif_nextdiroff, sizeof (long)))
- tif->tif_nextdiroff = 0;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong((unsigned long *) &tif->tif_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;
- if (tif->tif_diroff != tif->tif_header.tiff_diroff)
- {
- /* free any old stuff and reinit */
- TIFFFreeDirectory(tif);
- memset((char *)td, 0, sizeof (*td));
- }
- 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);
- for (fip = FieldInfo, dp = dir, n = dircount; n > 0; n--, dp++)
- {
- if (tif->tif_flags & TIFF_SWAB)
- {
- TIFFSwabArrayOfShort(&dp->tdir_tag, 2);
- TIFFSwabArrayOfLong(&dp->tdir_count, 2);
- }
- /*
- Find the field information entry for this tag.
- */
- while (fip < &FieldInfo[NFIELDINFO] && fip->field_tag < dp->tdir_tag)
- fip++;
- if (fip >= &FieldInfo[NFIELDINFO] || fip->field_tag != dp->tdir_tag)
- {
- /*
- Unknown field, should this be fatal?
- */
- TIFFWarning(tif->tif_name,"Ignoring unknown field with tag %d (0x%x)",
- dp->tdir_tag, dp->tdir_tag);
- dp->tdir_tag = IGNORE;
- continue;
- }
- /* Null out old tags that we ignore. */
- if (fip->field_bit == 0xffff)
- {
- dp->tdir_tag = IGNORE;
- continue;
- }
- /* Check data type. */
- while ((TIFFDataType)dp->tdir_type != fip->field_type)
- {
- fip++;
- if (fip >= &FieldInfo[NFIELDINFO] || fip->field_tag != dp->tdir_tag)
- {
- TIFFError(tif->tif_name,"Wrong data type %d for field \"%s\"",
- dp->tdir_type, fip->field_name);
- goto bad;
- }
- }
- switch (dp->tdir_tag)
- {
- case TIFFTAG_STRIPOFFSETS:
- case TIFFTAG_STRIPBYTECOUNTS:
- TIFFSetFieldBit(tif, fip->field_bit);
- break;
- case TIFFTAG_IMAGELENGTH:
- case TIFFTAG_PLANARCONFIG:
- case TIFFTAG_ROWSPERSTRIP:
- case TIFFTAG_SAMPLESPERPIXEL:
- if (!TIFFSetField(tif, dp->tdir_tag,
- TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset)))
- goto bad;
- 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;
- }
- if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS))
- {
- MissingRequired(tif, "StripOffsets");
- goto bad;
- }
- td->td_stripsperimage = (td->td_rowsperstrip == 0xffffffffL ?
- 1 : howmany(td->td_imagelength, td->td_rowsperstrip));
- td->td_nstrips = td->td_stripsperimage;
- if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
- td->td_nstrips *= td->td_samplesperpixel;
-
- /*
- Second pass: extract other information.
- Should do a better job of verifying values.
- */
-
- for (dp = dir, n = dircount; n > 0; n--, dp++)
- {
- if (dp->tdir_tag == IGNORE)
- continue;
-
- if (dp->tdir_type == ASCII)
- {
- if (dp->tdir_count > 0)
- {
- /* allocate space for string */
- cp = (char *) malloc((unsigned)dp->tdir_count+1);
- if (cp == NULL)
- goto bad;
- if (dp->tdir_count > 4)
- {
- /* get ASCII string located somewhere in file */
- if (TIFFFetchData(tif, dp, cp) == FALSE)
- goto bad;
- }
- else
- {
- /* ASCII is in offset field of tag */
- strcpy(cp,(char *) &(dp->tdir_offset));
- }
- /* in either case */
- if (!TIFFSetField(tif, dp->tdir_tag, cp))
- goto bad;
- }
- continue;
- }
- if (dp->tdir_type == (unsigned) RATIONAL)
- {
- if (!TIFFSetField(tif, dp->tdir_tag,TIFFFetchRational(tif, dp)))
- goto bad;
- continue;
- }
- 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, TIFFTAG_COMPRESSION, v))
- goto bad;
- break;
- }
- /* fall thru */
- case TIFFTAG_MINSAMPLEVALUE:
- case TIFFTAG_MAXSAMPLEVALUE:
- case TIFFTAG_BITSPERSAMPLE:
- if (!TIFFFetchPerSampleShorts(tif, dp, &v) ||
- !TIFFSetField(tif, dp->tdir_tag, v))
- goto bad;
- break;
- case TIFFTAG_STRIPOFFSETS:
- if (!TIFFFetchStripThing(tif, dp,td->td_nstrips, &td->td_stripoffset))
- goto bad;
- TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
- break;
- case TIFFTAG_STRIPBYTECOUNTS:
- if (!TIFFFetchStripThing(tif, dp,td->td_nstrips, &td->td_stripbytecount))
- goto bad;
- TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
- break;
- case TIFFTAG_IMAGELENGTH:
- case TIFFTAG_ROWSPERSTRIP:
- case TIFFTAG_SAMPLESPERPIXEL:
- case TIFFTAG_PLANARCONFIG:
- /* handled in first pass above */
- break;
- case TIFFTAG_GRAYRESPONSECURVE:
- case TIFFTAG_COLORRESPONSECURVE:
- case TIFFTAG_COLORMAP:
- v = (1<< (td->td_bitspersample * td->td_samplesperpixel)) * sizeof (unsigned);
- cp = malloc((unsigned) (dp->tdir_tag == TIFFTAG_GRAYRESPONSECURVE ?
- v : 3*v));
- if (cp == NULL)
- goto bad;
- if (!TIFFSetField(tif, dp->tdir_tag, (unsigned *) cp,
- (unsigned *)(cp+(unsigned) v),
- (unsigned *)(cp+2*(unsigned) v)) ||
- !TIFFFetchData(tif, dp, cp))
- goto bad;
- break;
-
- /* BEGIN REV 4.0 COMPATIBILITY */
-
- case TIFFTAG_OSUBFILETYPE:
- v = 0;
- switch ((unsigned)TIFFExtractData(tif, dp->tdir_type,dp->tdir_offset))
- {
- case OFILETYPE_REDUCEDIMAGE:
- v = FILETYPE_REDUCEDIMAGE;
- break;
- case OFILETYPE_PAGE:
- v = FILETYPE_PAGE;
- break;
- }
- if (!TIFFSetField(tif, dp->tdir_tag, v))
- goto bad;
- break;
-
- /* END REV 4.0 COMPATIBILITY */
-
- default:
- if (!TIFFSetField(tif, dp->tdir_tag,
- TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset)))
- goto bad;
- break;
- }
- }
- if (!TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS))
- {
- struct stat sb;
- int space;
- /*
- 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_nstrips > 1)
- {
- MissingRequired(tif, "StripByteCounts");
- goto bad;
- }
- TIFFWarning(tif->tif_name,
- "TIFF directory missing \"%s\" field, calculating from imagelength",
- FieldWithTag(TIFFTAG_STRIPBYTECOUNTS)->field_name);
- fstat(tif->tif_fd, &sb);
- td->td_stripbytecount = (unsigned long *)malloc(sizeof (unsigned long));
- space = sizeof (TIFFHeader) + sizeof (unsigned) +
- (dircount * sizeof (TIFFDirEntry)) + sizeof (long);
- /* calculate amount of space used by indirect values */
- for (dp = dir, n = dircount; n > 0; n--, dp++)
- {
- unsigned cc = (unsigned) (dp->tdir_count *
- datawidth[dp->tdir_type]);
- if (cc > sizeof (long))
- space += cc;
- }
- td->td_stripbytecount[0] = sb.st_size - space;
- TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
- if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP))
- td->td_rowsperstrip = td->td_imagelength;
- }
- if (dir)
- free((char *) dir);
- if (!TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE))
- td->td_maxsamplevalue = (1<<td->td_bitspersample)-1;
- /* Setup default compression scheme. */
- return (!TIFFFieldSet(tif, FIELD_COMPRESSION) ?
- TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE) : 1);
- bad:
- if (dir)
- free((char *) dir);
- return (FALSE);
- }
-
-
-
-
- void TIFFFreeDirectory(TIFF *tif)
- {
- register TIFFDirectory *td = &tif->tif_dir;
-
- if (td->td_stripoffset)
- free((char *) td->td_stripoffset);
- if (td->td_stripbytecount)
- free((char *) td->td_stripbytecount);
-
- /*
- Only dealloc fields which were for sure allocated.
- This conditional allows TIFF writing programs
- to clean up after themselves, but TIFF reading
- programs clean up automatically.
- */
- if (tif->tif_mode == O_RDONLY)
- {
- if (TIFFFieldSet(tif, FIELD_GRAYRESPONSECURVE))
- free((char *) td->td_grayresponsecurve);
- /*
- Whole COLORRESPONSECURVE allocated at one time. It
- must be freed in the same way.
- */
- if (TIFFFieldSet(tif, FIELD_COLORRESPONSECURVE))
- free((char *) td->td_redresponsecurve);
- /*
- Whole COLORMAP allocated at one time. It
- must be freed in the same way.
- */
- if (TIFFFieldSet(tif, FIELD_COLORMAP))
- free((char *) td->td_redcolormap);
- }
- }
-
- /*
- Setup a default directory structure.
- */
- CompletionCode TIFFDefaultDirectory(TIFF *tif)
- {
- register TIFFDirectory *td = &tif->tif_dir;
-
- td->td_bitspersample = 1;
- td->td_threshholding = THRESHHOLD_BILEVEL;
- td->td_orientation = ORIENTATION_TOPLEFT;
- td->td_samplesperpixel = 1;
- td->td_rowsperstrip = 0xfffffffL;
- td->td_grayresponseunit = GRAYRESPONSEUNIT_100S;
- td->td_resolutionunit = RESUNIT_INCH;
- td->td_colorresponseunit = COLORRESPONSEUNIT_100S;
- return (TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE));
- }
-
- static
- void TIFFGetField1(TIFFDirectory *td, unsigned tag, va_list ap)
- {
- switch (tag)
- {
- case TIFFTAG_SUBFILETYPE:
- *va_arg(ap, unsigned long *) = td->td_subfiletype;
- break;
- case TIFFTAG_IMAGEWIDTH:
- *va_arg(ap, unsigned long *) = td->td_imagewidth;
- break;
- case TIFFTAG_IMAGELENGTH:
- *va_arg(ap, unsigned long *) = td->td_imagelength;
- break;
- case TIFFTAG_BITSPERSAMPLE:
- *va_arg(ap, unsigned *) = td->td_bitspersample;
- break;
- case TIFFTAG_COMPRESSION:
- *va_arg(ap, unsigned *) = td->td_compression;
- break;
- case TIFFTAG_PHOTOMETRIC:
- *va_arg(ap, unsigned *) = td->td_photometric;
- break;
- case TIFFTAG_THRESHHOLDING:
- *va_arg(ap, unsigned *) = td->td_threshholding;
- break;
- case TIFFTAG_DOCUMENTNAME:
- *va_arg(ap, char **) = td->td_documentname;
- break;
- case TIFFTAG_ARTIST:
- *va_arg(ap, char **) = td->td_artist;
- break;
- case TIFFTAG_DATETIME:
- *va_arg(ap, char **) = td->td_datetime;
- break;
- case TIFFTAG_HOSTCOMPUTER:
- *va_arg(ap, char **) = td->td_hostcomputer;
- break;
- case TIFFTAG_IMAGEDESCRIPTION:
- *va_arg(ap, char **) = td->td_imagedescription;
- break;
- case TIFFTAG_MAKE:
- *va_arg(ap, char **) = td->td_make;
- break;
- case TIFFTAG_MODEL:
- *va_arg(ap, char **) = td->td_model;
- break;
- case TIFFTAG_SOFTWARE:
- *va_arg(ap, char **) = td->td_software;
- break;
- case TIFFTAG_ORIENTATION:
- *va_arg(ap, unsigned *) = td->td_orientation;
- break;
- case TIFFTAG_SAMPLESPERPIXEL:
- *va_arg(ap, unsigned *) = td->td_samplesperpixel;
- break;
- case TIFFTAG_ROWSPERSTRIP:
- *va_arg(ap, unsigned long *) = td->td_rowsperstrip;
- break;
- case TIFFTAG_MINSAMPLEVALUE:
- *va_arg(ap, unsigned *) = td->td_minsamplevalue;
- break;
- case TIFFTAG_MAXSAMPLEVALUE:
- *va_arg(ap, unsigned *) = td->td_maxsamplevalue;
- break;
- case TIFFTAG_XRESOLUTION:
- *va_arg(ap, float *) = td->td_xresolution;
- break;
- case TIFFTAG_YRESOLUTION:
- *va_arg(ap, float *) = td->td_yresolution;
- break;
- case TIFFTAG_PLANARCONFIG:
- *va_arg(ap, unsigned *) = td->td_planarconfig;
- break;
- case TIFFTAG_XPOSITION:
- *va_arg(ap, float *) = td->td_xposition;
- break;
- case TIFFTAG_YPOSITION:
- *va_arg(ap, float *) = td->td_yposition;
- break;
- case TIFFTAG_PAGENAME:
- *va_arg(ap, char **) = td->td_pagename;
- break;
- case TIFFTAG_GRAYRESPONSEUNIT:
- *va_arg(ap, unsigned *) = td->td_grayresponseunit;
- break;
- case TIFFTAG_GRAYRESPONSECURVE:
- *va_arg(ap, unsigned **) = td->td_grayresponsecurve;
- break;
- case TIFFTAG_GROUP3OPTIONS:
- *va_arg(ap, unsigned long *) = td->td_group3options;
- break;
- case TIFFTAG_GROUP4OPTIONS:
- *va_arg(ap, unsigned long *) = td->td_group4options;
- break;
- case TIFFTAG_RESOLUTIONUNIT:
- *va_arg(ap, unsigned *) = td->td_resolutionunit;
- break;
- case TIFFTAG_PAGENUMBER:
- *va_arg(ap, unsigned long *) = td->td_pagenumber;
- break;
- case TIFFTAG_COLORRESPONSEUNIT:
- *va_arg(ap, unsigned *) = td->td_colorresponseunit;
- break;
- case TIFFTAG_COLORRESPONSECURVE:
- *va_arg(ap, unsigned **) = td->td_redresponsecurve;
- *va_arg(ap, unsigned **) = td->td_greenresponsecurve;
- *va_arg(ap, unsigned **) = td->td_blueresponsecurve;
- break;
- case TIFFTAG_COLORMAP:
- *va_arg(ap, unsigned **) = td->td_redcolormap;
- *va_arg(ap, unsigned **) = td->td_greencolormap;
- *va_arg(ap, unsigned **) = td->td_bluecolormap;
- break;
- case TIFFTAG_PREDICTOR:
- *va_arg(ap, unsigned *) = td->td_predictor;
- break;
- case TIFFTAG_STRIPOFFSETS:
- *va_arg(ap, unsigned long **) = td->td_stripoffset;
- break;
- case TIFFTAG_STRIPBYTECOUNTS:
- *va_arg(ap, unsigned long **) = td->td_stripbytecount;
- break;
- }
- va_end(ap);
- }
-
-
- /*
- Return the value of a field in the
- internal directory structure.
- */
- CompletionCode TIFFGetField(TIFF *tif, unsigned tag, ...)
- {
- register TIFFFieldInfo *fip;
- TIFFDirectory *td = &tif->tif_dir;
- va_list ap;
-
- for (fip = FieldInfo; fip < &FieldInfo[NFIELDINFO]; fip++)
- if (fip->field_tag == tag)
- break;
- if (fip >= &FieldInfo[NFIELDINFO])
- {
- TIFFError("TIFFGetField", "Unknown field, tag 0x%x", tag);
- return (FALSE);
- }
- if (TIFFFieldSet(tif, fip->field_bit))
- {
- va_start(ap,tag);
- TIFFGetField1(td, tag, ap);
- va_end(ap);
- return (TRUE);
- }
- return (FALSE);
- }
-
-
- /*
- Internal interface to TIFFGetField...
- */
- static
- void TIFFgetfield(TIFFDirectory *td, unsigned tag, ...)
- {
- va_list ap;
-
- va_start(ap,tag);
- TIFFGetField1(td, tag, ap);
- va_end(ap);
- }
-
- /* shorthands for setting up and writing directory... */
- #define MakeShortDirent(tag, v) \
- dir->tdir_tag = tag; \
- dir->tdir_type = (unsigned)SHORT; \
- dir->tdir_count = 1; \
- dir->tdir_offset = TIFFInsertData(tif, (unsigned) SHORT, v); \
- dir++
- #define WriteRationalPair(tag1, v1, tag2, v2) \
- (TIFFWriteRational(tif, tag1, dir++, v1) && \
- TIFFWriteRational(tif, tag2, dir++, v2))
-
- static long dataoff;
-
- /*
- Link the current directory into the
- directory chain for the file.
- */
- static
- CompletionCode TIFFLinkDirectory(register TIFF *tif)
- {
- static char module[] = "TIFFLinkDirectory";
- short dircount;
- long nextdir;
-
- tif->tif_diroff = (lseek(tif->tif_fd, 0L, SEEK_END)+1) &~ 1;
- if (tif->tif_header.tiff_diroff == 0)
- {
- /* First directory, overwrite header. */
- tif->tif_header.tiff_diroff = tif->tif_diroff;
- lseek(tif->tif_fd, 0L, SEEK_SET);
- if (!WriteOK(tif->tif_fd, &tif->tif_header,sizeof (tif->tif_header)))
- {
- TIFFError(tif->tif_name, "Error writing TIFF header");
- return (FALSE);
- }
- return (TRUE);
- }
- /* Not the first directory, search to the last and append. */
- nextdir = tif->tif_header.tiff_diroff;
- do
- {
- if (!SeekOK(tif->tif_fd, nextdir) ||
- !ReadOK(tif->tif_fd, &dircount, sizeof (dircount)))
- {
- TIFFError(module, "Error fetching directory count");
- return (FALSE);
- }
- lseek(tif->tif_fd, dircount * sizeof (TIFFDirEntry), SEEK_CUR);
- if (!ReadOK(tif->tif_fd, &nextdir, sizeof (nextdir)))
- {
- TIFFError(module, "Error fetching directory link");
- return (FALSE);
- }
- } while (nextdir != 0);
- lseek(tif->tif_fd, -sizeof (nextdir), SEEK_CUR);
- if (!WriteOK(tif->tif_fd, &tif->tif_diroff, sizeof (tif->tif_diroff)))
- {
- TIFFError(module, "Error writing directory link");
- return (FALSE);
- }
- return (TRUE);
- }
-
-
- /*
- Write a contiguous directory item.
- */
- static
- CompletionCode TIFFWriteData(TIFF *tif, TIFFDirEntry *dir, char *cp)
- {
- unsigned cc;
-
- dir->tdir_offset = dataoff;
- cc = (unsigned)(dir->tdir_count * datawidth[dir->tdir_type]);
- if (SeekOK(tif->tif_fd, dir->tdir_offset) && WriteOK(tif->tif_fd, cp, cc))
- {
- dataoff += (cc + 1) & ~1;
- return (TRUE);
- }
- TIFFError(tif->tif_name, "Error writing data for field \"%s\"",
- FieldWithTag(dir->tdir_tag)->field_name);
- return (FALSE);
- }
-
-
- /*
- Set the n-th directory as the current directory.
- Directories are numbered starting at 0.
- */
- CompletionCode TIFFSetDirectory(register TIFF *tif, long n)
- {
- static char module[] = "TIFFSetDirectory";
- short dircount;
- long nextdir;
-
- nextdir = tif->tif_header.tiff_diroff;
- while (n-- > 0 && nextdir != 0)
- {
- if (!SeekOK(tif->tif_fd, nextdir) ||
- !ReadOK(tif->tif_fd, &dircount, sizeof (dircount)))
- {
- TIFFError(module, "%s: Error fetching directory count",
- tif->tif_name);
- return (FALSE);
- }
- lseek(tif->tif_fd, dircount*sizeof (TIFFDirEntry), SEEK_CUR);
- if (!ReadOK(tif->tif_fd, &nextdir, sizeof (nextdir)))
- {
- TIFFError(module, "%s: Error fetching directory link",
- tif->tif_name);
- return (FALSE);
- }
- }
- tif->tif_nextdiroff = nextdir;
- return (TIFFReadDirectory(tif));
- }
-
- static
- CompletionCode TIFFWriteStripThing(TIFF *tif, unsigned tag,
- TIFFDirEntry *dir, unsigned long *lp)
- {
- dir->tdir_tag = tag;
- dir->tdir_type = (unsigned)LONG; /* XXX */
- dir->tdir_count = tif->tif_dir.td_nstrips;
- if (dir->tdir_count > 1)
- return (TIFFWriteData(tif, dir, (char *) lp));
- dir->tdir_offset = *lp;
- return (TRUE);
- }
-
-
-
- static
- CompletionCode TIFFWriteRational(TIFF *tif, unsigned tag,
- TIFFDirEntry *dir, float v)
- {
- long t[2];
-
- dir->tdir_tag = tag;
- dir->tdir_type = (unsigned)RATIONAL;
- dir->tdir_count = 1;
- /* need algorithm to convert ... */
- t[0] = v * 10000.0;
- t[1] = 10000.0;
- return (TIFFWriteData(tif, dir, (char *) t));
- }
-
- static
- CompletionCode TIFFWritePerSampleShorts(TIFF *tif, unsigned tag,
- TIFFDirEntry *dir, short v)
- {
- unsigned w[4];
- unsigned i;
- unsigned samplesperpixel = tif->tif_dir.td_samplesperpixel;
-
- dir->tdir_tag = tag;
- dir->tdir_type = (unsigned)SHORT;
- dir->tdir_count = samplesperpixel;
- if (samplesperpixel <= 2)
- {
- if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN)
- {
- dir->tdir_offset = v << 16;
- if (samplesperpixel == 2)
- dir->tdir_offset |= v & 0xffff;
- }
- else
- {
- dir->tdir_offset = v & 0xffff;
- if (samplesperpixel == 2)
- dir->tdir_offset |= v << 16;
- }
- return (TRUE);
- }
- for (i = 0; i < samplesperpixel; i++)
- w[i] = v;
- return (TIFFWriteData(tif, dir, (char *) w));
- }
-
-
-
-
- /*
- 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.
- */
-
- #define WRITE(x) TIFFWriteData(tif, dir, x)
-
-
- CompletionCode TIFFWriteDirectory(TIFF *tif)
- {
- short dircount, v;
- unsigned b, nfields, dirsize;
- char *data, *cp;
- TIFFFieldInfo *fip;
- TIFFDirEntry *dir;
- TIFFDirectory *td;
- unsigned long off, fields[sizeof (td->td_fieldsset) / sizeof (unsigned long)];
-
- if (tif->tif_mode == O_RDONLY)
- return (1);
- 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))
- nfields += (b < FIELD_SUBFILETYPE ? 2 : 1);
- dirsize = nfields * sizeof (TIFFDirEntry);
- data = malloc(dirsize);
- if (data == NULL)
- {
- TIFFError(tif->tif_name,"Cannot write directory, out of space");
- return (FALSE);
- }
- /*
- 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))
- return (FALSE);
- dataoff = tif->tif_diroff + sizeof (unsigned) + dirsize + sizeof (long);
- if (dataoff & 1)
- dataoff++;
- lseek(tif->tif_fd, dataoff, SEEK_SET);
- dir = (TIFFDirEntry *)data;
- /*
- Setup external form of directory
- entries and write data items.
- */
- movmem(td->td_fieldsset, fields, sizeof (fields));
- for (fip = FieldInfo; fip < &FieldInfo[NFIELDINFO]; fip++)
- {
- if (fip->field_bit == 0xffff || !FieldSet(fields, fip->field_bit))
- continue;
- if (fip->field_type == ASCII)
- {
- TIFFgetfield(td, fip->field_tag, &cp);
- dir->tdir_tag = fip->field_tag;
- dir->tdir_type = (unsigned) ASCII;
- dir->tdir_count = strlen(cp) + 1;
- if (!TIFFWriteData(tif, dir++, cp))
- goto bad;
- ResetFieldBit(fields, fip->field_bit);
- continue;
- }
- switch (fip->field_bit)
- {
- case FIELD_STRIPOFFSETS:
- case FIELD_STRIPBYTECOUNTS:
- if (!TIFFWriteStripThing(tif,fip->field_tag, dir++,
- fip->field_bit == FIELD_STRIPOFFSETS ?
- td->td_stripoffset : td->td_stripbytecount))
- goto bad;
- break;
- case FIELD_GRAYRESPONSECURVE:
- dir->tdir_tag = fip->field_tag;
- dir->tdir_type = (unsigned)SHORT;
- dir->tdir_count =
- 1 << (td->td_bitspersample * td->td_samplesperpixel);
- if (!TIFFWriteData(tif, dir++,(char *) td->td_grayresponsecurve))
- goto bad;
- break;
- case FIELD_COLORRESPONSECURVE:
- case FIELD_COLORMAP:
- dir->tdir_tag = fip->field_tag;
- dir->tdir_type = (unsigned)SHORT;
- /* yech, fool TIFFWriteData */
- dir->tdir_count =
- 1 << (td->td_bitspersample * td->td_samplesperpixel);
- off = dataoff;
- if (fip->field_tag == TIFFTAG_COLORMAP)
- {
- if (!WRITE((char *) td->td_redcolormap) ||
- !WRITE((char *) td->td_greencolormap) ||
- !WRITE((char *) td->td_bluecolormap))
- goto bad;
- }
- else
- {
- if (!WRITE((char *) td->td_redresponsecurve) ||
- !WRITE((char *) td->td_greenresponsecurve) ||
- !WRITE((char *) td->td_blueresponsecurve))
- goto bad;
- }
- #undef WRITE
- dir->tdir_count *= 3;
- dir->tdir_offset = off;
- break;
- case FIELD_IMAGEDIMENSIONS:
- MakeShortDirent(TIFFTAG_IMAGEWIDTH, td->td_imagewidth);
- MakeShortDirent(TIFFTAG_IMAGELENGTH,td->td_imagelength);
- break;
- case FIELD_POSITION:
- if (!WriteRationalPair(TIFFTAG_XPOSITION, td->td_xposition,
- TIFFTAG_YPOSITION, td->td_yposition))
- goto bad;
- break;
- case FIELD_RESOLUTION:
- if (!WriteRationalPair(TIFFTAG_XRESOLUTION, td->td_xresolution,
- TIFFTAG_YRESOLUTION, td->td_yresolution))
- goto bad;
- break;
- case FIELD_BITSPERSAMPLE:
- case FIELD_MINSAMPLEVALUE:
- case FIELD_MAXSAMPLEVALUE:
- TIFFgetfield(td, fip->field_tag, &v);
- if (!TIFFWritePerSampleShorts(tif, fip->field_tag,dir++, v))
- goto bad;
- break;
- default:
- dir->tdir_tag = fip->field_tag;
- dir->tdir_type = (unsigned)fip->field_type;
- dir->tdir_count = fip->field_count;
- if (fip->field_type == SHORT)
- {
- TIFFgetfield(td, fip->field_tag, &v);
- dir->tdir_offset = TIFFInsertData(tif, dir->tdir_type, v);
- }
- else
- TIFFgetfield(td, fip->field_tag,&dir->tdir_offset);
- dir++;
- break;
- }
- ResetFieldBit(fields, fip->field_bit);
- }
- /* Write directory. */
- lseek(tif->tif_fd, tif->tif_diroff, SEEK_SET);
- dircount = nfields;
- if (!WriteOK(tif->tif_fd, &dircount, sizeof (unsigned)))
- {
- TIFFError(tif->tif_name, "Error writing directory count");
- goto bad;
- }
- if (!WriteOK(tif->tif_fd, data, dirsize))
- {
- TIFFError(tif->tif_name, "Error writing directory contents");
- goto bad;
- }
- if (!WriteOK(tif->tif_fd, &tif->tif_nextdiroff, sizeof (long)))
- {
- TIFFError(tif->tif_name, "Error writing directory link");
- goto bad;
- }
- free((char *) data);
- return (TRUE);
- bad:
- free((char *) data);
- return (FALSE);
- }
-