summaryrefslogtreecommitdiff
path: root/src/libtiff/tif_dirwrite.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libtiff/tif_dirwrite.c')
-rw-r--r--src/libtiff/tif_dirwrite.c326
1 files changed, 247 insertions, 79 deletions
diff --git a/src/libtiff/tif_dirwrite.c b/src/libtiff/tif_dirwrite.c
index d775354..7d5ca71 100644
--- a/src/libtiff/tif_dirwrite.c
+++ b/src/libtiff/tif_dirwrite.c
@@ -1,4 +1,4 @@
-/* $Id: tif_dirwrite.c,v 1.1 2008/10/17 06:16:07 scuri Exp $ */
+/* $Id: tif_dirwrite.c,v 1.2 2009/08/21 04:01:59 scuri Exp $ */
/*
* Copyright (c) 1988-1997 Sam Leffler
@@ -100,31 +100,39 @@ _TIFFWriteDirectory(TIFF* tif, int done)
*/
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,
+ tsize_t orig_rawcc = tif->tif_rawcc;
+
+ 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)) {
+ return (0);
+ }
+ }
+ (*tif->tif_close)(tif); /* shutdown encoder */
+ /*
+ * Flush any data that might have been written
+ * by the compression close+cleanup routines. But
+ * be careful not to write stuff if we didn't add data
+ * in the previous steps as the "rawcc" data may well be
+ * a previously read tile/strip in mixed read/write mode.
+ */
+ if (tif->tif_rawcc > 0 && tif->tif_rawcc != orig_rawcc
+ && (tif->tif_flags & TIFF_BEENWRITING) != 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);
+ "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;
@@ -137,12 +145,12 @@ _TIFFWriteDirectory(TIFF* tif, int done)
for (b = 0; b <= FIELD_LAST; b++)
if (TIFFFieldSet(tif, b) && b != FIELD_CUSTOM)
nfields += (b < FIELD_SUBFILETYPE ? 2 : 1);
- nfields += td->td_customValueCount;
+ nfields += td->td_customValueCount;
dirsize = nfields * sizeof (TIFFDirEntry);
data = (char*) _TIFFmalloc(dirsize);
if (data == NULL) {
TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
- "Cannot write directory, out of space");
+ "Cannot write directory, out of space");
return (0);
}
/*
@@ -176,30 +184,29 @@ _TIFFWriteDirectory(TIFF* tif, int done)
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 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);
+ for( ci = 0; ci < td->td_customValueCount; ci++ )
+ is_set |= (td->td_customValues[ci].info == fip);
- if( !is_set )
- continue;
- }
+ if( !is_set )
+ continue;
+ }
else if (!FieldSet(fields, fip->field_bit))
- continue;
-
+ continue;
- /*
- ** Handle other fields.
- */
+ /*
+ * Handle other fields.
+ */
switch (fip->field_bit)
- {
+ {
case FIELD_STRIPOFFSETS:
/*
* We use one field bit for both strip and tile
@@ -234,8 +241,7 @@ _TIFFWriteDirectory(TIFF* tif, int done)
dir->tdir_tag = (uint16) tag;
dir->tdir_type = (uint16) TIFF_LONG;
dir->tdir_count = (uint32) td->td_nstrips;
- if (!TIFFWriteLongArray(tif, dir,
- td->td_stripbytecount))
+ if (!TIFFWriteLongArray(tif, dir, td->td_stripbytecount))
goto bad;
break;
case FIELD_ROWSPERSTRIP:
@@ -346,8 +352,8 @@ _TIFFWriteDirectory(TIFF* tif, int done)
}
dir++;
- if( fip->field_bit != FIELD_CUSTOM )
- ResetFieldBit(fields, fip->field_bit);
+ if( fip->field_bit != FIELD_CUSTOM )
+ ResetFieldBit(fields, fip->field_bit);
}
/*
@@ -376,15 +382,18 @@ _TIFFWriteDirectory(TIFF* tif, int done)
}
(void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET);
if (!WriteOK(tif, &dircount, sizeof (dircount))) {
- TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing directory count");
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error writing directory count");
goto bad;
}
if (!WriteOK(tif, data, dirsize)) {
- TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing directory contents");
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error writing directory contents");
goto bad;
}
- if (!WriteOK(tif, &diroff, sizeof (diroff))) {
- TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing directory link");
+ if (!WriteOK(tif, &diroff, sizeof (uint32))) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error writing directory link");
goto bad;
}
if (done) {
@@ -430,6 +439,133 @@ TIFFCheckpointDirectory(TIFF* tif)
return rc;
}
+static int
+_TIFFWriteCustomDirectory(TIFF* tif, toff_t *pdiroff)
+{
+ uint16 dircount;
+ 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);
+
+ 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) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Cannot write directory, out of space");
+ return (0);
+ }
+ /*
+ * Put the directory at the end of the file.
+ */
+ tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1;
+ 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);
+ dir = (TIFFDirEntry*) data;
+ /*
+ * Setup external form of directory
+ * entries and write data items.
+ */
+ _TIFFmemcpy(fields, td->td_fieldsset, sizeof (fields));
+
+ 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;
+
+ if( fip->field_bit != FIELD_CUSTOM )
+ ResetFieldBit(fields, fip->field_bit);
+ }
+
+ /*
+ * Write directory.
+ */
+ dircount = (uint16) nfields;
+ *pdiroff = (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(pdiroff);
+ }
+ (void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET);
+ if (!WriteOK(tif, &dircount, sizeof (dircount))) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error writing directory count");
+ goto bad;
+ }
+ if (!WriteOK(tif, data, dirsize)) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error writing directory contents");
+ goto bad;
+ }
+ if (!WriteOK(tif, pdiroff, sizeof (uint32))) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error writing directory link");
+ goto bad;
+ }
+ _TIFFfree(data);
+ return (1);
+bad:
+ _TIFFfree(data);
+ return (0);
+}
+
+int
+TIFFWriteCustomDirectory(TIFF* tif, toff_t *pdiroff)
+{
+ return _TIFFWriteCustomDirectory(tif, pdiroff);
+}
+
/*
* Process tags that are not special cased.
*/
@@ -581,7 +717,12 @@ TIFFWriteNormalTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip)
{
char* cp;
if (fip->field_passcount)
- TIFFGetField(tif, fip->field_tag, &wc, &cp);
+ {
+ if( wc == (uint16) TIFF_VARIABLE2 )
+ TIFFGetField(tif, fip->field_tag, &wc2, &cp);
+ else
+ TIFFGetField(tif, fip->field_tag, &wc, &cp);
+ }
else
TIFFGetField(tif, fip->field_tag, &cp);
@@ -786,12 +927,27 @@ TIFFWriteShortTable(TIFF* tif,
static int
TIFFWriteByteArray(TIFF* tif, TIFFDirEntry* dir, char* cp)
{
- if (dir->tdir_count > 4) {
- if (!TIFFWriteData(tif, dir, cp))
- return (0);
+ if (dir->tdir_count <= 4) {
+ if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
+ dir->tdir_offset = (uint32)cp[0] << 24;
+ if (dir->tdir_count >= 2)
+ dir->tdir_offset |= (uint32)cp[1] << 16;
+ if (dir->tdir_count >= 3)
+ dir->tdir_offset |= (uint32)cp[2] << 8;
+ if (dir->tdir_count == 4)
+ dir->tdir_offset |= cp[3];
+ } else {
+ dir->tdir_offset = cp[0];
+ if (dir->tdir_count >= 2)
+ dir->tdir_offset |= (uint32) cp[1] << 8;
+ if (dir->tdir_count >= 3)
+ dir->tdir_offset |= (uint32) cp[2] << 16;
+ if (dir->tdir_count == 4)
+ dir->tdir_offset |= (uint32) cp[3] << 24;
+ }
+ return 1;
} else
- _TIFFmemcpy(&dir->tdir_offset, cp, dir->tdir_count);
- return (1);
+ return TIFFWriteData(tif, dir, cp);
}
/*
@@ -803,13 +959,13 @@ TIFFWriteShortArray(TIFF* tif, TIFFDirEntry* dir, uint16* v)
{
if (dir->tdir_count <= 2) {
if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
- dir->tdir_offset = (uint32) ((long) v[0] << 16);
+ dir->tdir_offset = (uint32) v[0] << 16;
if (dir->tdir_count == 2)
dir->tdir_offset |= v[1] & 0xffff;
} else {
dir->tdir_offset = v[0] & 0xffff;
if (dir->tdir_count == 2)
- dir->tdir_offset |= (long) v[1] << 16;
+ dir->tdir_offset |= (uint32) v[1] << 16;
}
return (1);
} else
@@ -854,10 +1010,11 @@ TIFFWriteRationalArray(TIFF* tif, TIFFDirEntry* dir, float* v)
if (fv < 0) {
if (dir->tdir_type == TIFF_RATIONAL) {
- TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
+ TIFFWarningExt(tif->tif_clientdata,
+ tif->tif_name,
"\"%s\": Information lost writing value (%g) as (unsigned) RATIONAL",
_TIFFFieldWithTag(tif,dir->tdir_tag)->field_name,
- fv);
+ fv);
fv = 0;
} else
fv = -fv, sign = -1;
@@ -914,7 +1071,7 @@ TIFFWriteAnyArray(TIFF* tif,
w = (char*) _TIFFmalloc(n * TIFFDataWidth(type));
if (w == NULL) {
TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
- "No space to write array");
+ "No space to write array");
return (0);
}
}
@@ -988,7 +1145,10 @@ TIFFWriteAnyArray(TIFF* tif,
}
break;
case TIFF_DOUBLE:
- return (TIFFWriteDoubleArray(tif, dir, v));
+ {
+ if( !TIFFWriteDoubleArray(tif, dir, v))
+ goto out;
+ }
default:
/* TIFF_NOTYPE */
/* TIFF_ASCII */
@@ -1073,8 +1233,9 @@ TIFFWriteData(TIFF* tif, TIFFDirEntry* dir, char* cp)
tif->tif_dataoff += (cc + 1) & ~1;
return (1);
}
- TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing data for field \"%s\"",
- _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error writing data for field \"%s\"",
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
return (0);
}
@@ -1110,7 +1271,8 @@ TIFFRewriteDirectory( TIFF *tif )
if (!WriteOK(tif, &(tif->tif_header.tiff_diroff),
sizeof (tif->tif_diroff)))
{
- TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error updating TIFF header");
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error updating TIFF header");
return (0);
}
}
@@ -1124,7 +1286,8 @@ TIFFRewriteDirectory( TIFF *tif )
if (!SeekOK(tif, nextdir) ||
!ReadOK(tif, &dircount, sizeof (dircount))) {
- TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory count");
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error fetching directory count");
return (0);
}
if (tif->tif_flags & TIFF_SWAB)
@@ -1132,7 +1295,8 @@ TIFFRewriteDirectory( TIFF *tif )
(void) TIFFSeekFile(tif,
dircount * sizeof (TIFFDirEntry), SEEK_CUR);
if (!ReadOK(tif, &nextdir, sizeof (nextdir))) {
- TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory link");
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error fetching directory link");
return (0);
}
if (tif->tif_flags & TIFF_SWAB)
@@ -1142,7 +1306,8 @@ TIFFRewriteDirectory( TIFF *tif )
(void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET);
tif->tif_diroff = 0;
if (!WriteOK(tif, &(tif->tif_diroff), sizeof (nextdir))) {
- TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link");
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error writing directory link");
return (0);
}
}
@@ -1156,8 +1321,7 @@ TIFFRewriteDirectory( TIFF *tif )
/*
- * Link the current directory into the
- * directory chain for the file.
+ * Link the current directory into the directory chain for the file.
*/
static int
TIFFLinkDirectory(TIFF* tif)
@@ -1178,8 +1342,8 @@ TIFFLinkDirectory(TIFF* tif)
(void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET);
if (!WriteOK(tif, &diroff, sizeof (diroff))) {
TIFFErrorExt(tif->tif_clientdata, module,
- "%s: Error writing SubIFD directory link",
- tif->tif_name);
+ "%s: Error writing SubIFD directory link",
+ tif->tif_name);
return (0);
}
/*
@@ -1203,7 +1367,8 @@ TIFFLinkDirectory(TIFF* tif)
(toff_t)(TIFF_MAGIC_SIZE+TIFF_VERSION_SIZE),
SEEK_SET);
if (!WriteOK(tif, &diroff, sizeof (diroff))) {
- TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing TIFF header");
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error writing TIFF header");
return (0);
}
return (1);
@@ -1217,7 +1382,8 @@ TIFFLinkDirectory(TIFF* tif)
if (!SeekOK(tif, nextdir) ||
!ReadOK(tif, &dircount, sizeof (dircount))) {
- TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory count");
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error fetching directory count");
return (0);
}
if (tif->tif_flags & TIFF_SWAB)
@@ -1225,7 +1391,8 @@ TIFFLinkDirectory(TIFF* tif)
(void) TIFFSeekFile(tif,
dircount * sizeof (TIFFDirEntry), SEEK_CUR);
if (!ReadOK(tif, &nextdir, sizeof (nextdir))) {
- TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory link");
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error fetching directory link");
return (0);
}
if (tif->tif_flags & TIFF_SWAB)
@@ -1234,7 +1401,8 @@ TIFFLinkDirectory(TIFF* tif)
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))) {
- TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link");
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error writing directory link");
return (0);
}
return (1);