X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b47c832e5529dc6c632536b4665a005f0a85aec8..c90c34007a72d942f378e46b77e4f4456ac9c5b1:/src/tiff/tif_dirwrite.c diff --git a/src/tiff/tif_dirwrite.c b/src/tiff/tif_dirwrite.c index ed4b0118c0..df120153f2 100644 --- a/src/tiff/tif_dirwrite.c +++ b/src/tiff/tif_dirwrite.c @@ -41,6 +41,7 @@ extern void TIFFCvtNativeToIEEEDouble(TIFF*, uint32, double*); static int TIFFWriteNormalTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*); static void TIFFSetupShortLong(TIFF*, ttag_t, TIFFDirEntry*, uint32); +static void TIFFSetupShort(TIFF*, ttag_t, TIFFDirEntry*, uint16); static int TIFFSetupShortPair(TIFF*, ttag_t, TIFFDirEntry*); static int TIFFWritePerSampleShorts(TIFF*, ttag_t, TIFFDirEntry*); static int TIFFWritePerSampleAnys(TIFF*, TIFFDataType, ttag_t, TIFFDirEntry*); @@ -87,11 +88,11 @@ static int TIFFWriteRational(TIFF*, * handle overwriting a directory with auxiliary * storage that's been changed. */ -int -TIFFWriteDirectory(TIFF* tif) +static int +_TIFFWriteDirectory(TIFF* tif, int done) { uint16 dircount; - uint32 diroff; + toff_t diroff; ttag_t tag; uint32 nfields; tsize_t dirsize; @@ -108,30 +109,34 @@ TIFFWriteDirectory(TIFF* tif) * different characteristics get the right buffers * setup for them. */ - 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); - } + 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); } - (*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_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP); td = &tif->tif_dir; /* @@ -141,8 +146,9 @@ TIFFWriteDirectory(TIFF* tif) */ nfields = 0; for (b = 0; b <= FIELD_LAST; b++) - if (TIFFFieldSet(tif, 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) { @@ -180,12 +186,35 @@ TIFFWriteDirectory(TIFF* tif) } /*XXX*/ for (fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) { const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi]; - if (!FieldSet(fields, fip->field_bit)) - continue; - switch (fip->field_bit) { + + /* + ** 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). @@ -234,6 +263,14 @@ TIFFWriteDirectory(TIFF* tif) 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, @@ -294,7 +331,7 @@ TIFFWriteDirectory(TIFF* tif) */ if (dir->tdir_count > 0) { tif->tif_flags |= TIFF_INSUBIFD; - tif->tif_nsubifd = dir->tdir_count; + tif->tif_nsubifd = (uint16) dir->tdir_count; if (dir->tdir_count > 1) tif->tif_subifdoff = dir->tdir_offset; else @@ -311,8 +348,11 @@ TIFFWriteDirectory(TIFF* tif) break; } dir++; - ResetFieldBit(fields, fip->field_bit); + + if( fip->field_bit != FIELD_CUSTOM ) + ResetFieldBit(fields, fip->field_bit); } + /* * Write directory. */ @@ -350,20 +390,18 @@ TIFFWriteDirectory(TIFF* tif) TIFFError(tif->tif_name, "Error writing directory link"); goto bad; } - TIFFFreeDirectory(tif); - _TIFFfree(data); - tif->tif_flags &= ~TIFF_DIRTYDIRECT; - (*tif->tif_cleanup)(tif); + if (done) { + TIFFFreeDirectory(tif); + tif->tif_flags &= ~TIFF_DIRTYDIRECT; + (*tif->tif_cleanup)(tif); - /* - * Reset directory-related state for subsequent - * directories. - */ - TIFFDefaultDirectory(tif); - tif->tif_diroff = 0; - tif->tif_curoff = 0; - tif->tif_row = (uint32) -1; - tif->tif_curstrip = (tstrip_t) -1; + /* + * Reset directory-related state for subsequent + * directories. + */ + TIFFCreateDirectory(tif); + } + _TIFFfree(data); return (1); bad: _TIFFfree(data); @@ -371,6 +409,30 @@ bad: } #undef WriteRationalPair +int +TIFFWriteDirectory(TIFF* tif) +{ + return _TIFFWriteDirectory(tif, TRUE); +} + +/* + * Similar to TIFFWriteDirectory(), writes the directory out + * but leaves all data structures in memory so that it can be + * written again. This will make a partially written TIFF file + * readable before it is successfully completed/closed. + */ +int +TIFFCheckpointDirectory(TIFF* tif) +{ + int rc; + /* Setup the strips arrays, if they haven't already been. */ + if (tif->tif_dir.td_stripoffset == NULL) + (void) TIFFSetupStrips(tif); + rc = _TIFFWriteDirectory(tif, FALSE); + (void) TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END)); + return rc; +} + /* * Process tags that are not special cased. */ @@ -380,7 +442,7 @@ TIFFWriteNormalTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip) u_short wc = (u_short) fip->field_writecount; uint32 wc2; - dir->tdir_tag = fip->field_tag; + dir->tdir_tag = (uint16) fip->field_tag; dir->tdir_type = (u_short) fip->field_type; dir->tdir_count = wc; #define WRITEF(x,y) x(tif, fip->field_type, fip->field_tag, dir, wc, y) @@ -389,81 +451,123 @@ TIFFWriteNormalTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip) case TIFF_SSHORT: if (wc > 1) { uint16* wp; - if (wc == (u_short) TIFF_VARIABLE) + if (wc == (u_short) TIFF_VARIABLE + || fip->field_passcount) TIFFGetField(tif, fip->field_tag, &wc, &wp); else TIFFGetField(tif, fip->field_tag, &wp); if (!WRITEF(TIFFWriteShortArray, wp)) return (0); } else { - uint16 sv; - TIFFGetField(tif, fip->field_tag, &sv); - dir->tdir_offset = - TIFFInsertData(tif, dir->tdir_type, sv); + if (fip->field_passcount) { + uint16* wp; + TIFFGetField(tif, fip->field_tag, &wc, &wp); + if (!WRITEF(TIFFWriteShortArray, wp)) + return 0; + } else { + uint16 sv; + TIFFGetField(tif, fip->field_tag, &sv); + dir->tdir_offset = + TIFFInsertData(tif, dir->tdir_type, sv); + } } break; case TIFF_LONG: case TIFF_SLONG: + case TIFF_IFD: if (wc > 1) { uint32* lp; - if (wc == (u_short) TIFF_VARIABLE) + if (wc == (u_short) TIFF_VARIABLE + || fip->field_passcount) TIFFGetField(tif, fip->field_tag, &wc, &lp); else TIFFGetField(tif, fip->field_tag, &lp); if (!WRITEF(TIFFWriteLongArray, lp)) return (0); } else { - /* XXX handle LONG->SHORT conversion */ - TIFFGetField(tif, fip->field_tag, &dir->tdir_offset); + if (fip->field_passcount) { + uint32* lp; + TIFFGetField(tif, fip->field_tag, &wc, &lp); + if (!WRITEF(TIFFWriteLongArray, lp)) + return 0; + } else { + /* XXX handle LONG->SHORT conversion */ + TIFFGetField(tif, fip->field_tag, + &dir->tdir_offset); + } } break; case TIFF_RATIONAL: case TIFF_SRATIONAL: if (wc > 1) { float* fp; - if (wc == (u_short) TIFF_VARIABLE) + if (wc == (u_short) TIFF_VARIABLE + || fip->field_passcount) TIFFGetField(tif, fip->field_tag, &wc, &fp); else TIFFGetField(tif, fip->field_tag, &fp); if (!WRITEF(TIFFWriteRationalArray, fp)) return (0); } else { - float fv; - TIFFGetField(tif, fip->field_tag, &fv); - if (!WRITEF(TIFFWriteRationalArray, &fv)) - return (0); + if (fip->field_passcount) { + float* fp; + TIFFGetField(tif, fip->field_tag, &wc, &fp); + if (!WRITEF(TIFFWriteRationalArray, fp)) + return 0; + } else { + float fv; + TIFFGetField(tif, fip->field_tag, &fv); + if (!WRITEF(TIFFWriteRationalArray, &fv)) + return (0); + } } break; case TIFF_FLOAT: if (wc > 1) { float* fp; - if (wc == (u_short) TIFF_VARIABLE) + if (wc == (u_short) TIFF_VARIABLE + || fip->field_passcount) TIFFGetField(tif, fip->field_tag, &wc, &fp); else TIFFGetField(tif, fip->field_tag, &fp); if (!WRITEF(TIFFWriteFloatArray, fp)) return (0); } else { - float fv; - TIFFGetField(tif, fip->field_tag, &fv); - if (!WRITEF(TIFFWriteFloatArray, &fv)) - return (0); + if (fip->field_passcount) { + float* fp; + TIFFGetField(tif, fip->field_tag, &wc, &fp); + if (!WRITEF(TIFFWriteFloatArray, fp)) + return 0; + } else { + float fv; + TIFFGetField(tif, fip->field_tag, &fv); + if (!WRITEF(TIFFWriteFloatArray, &fv)) + return (0); + } } break; case TIFF_DOUBLE: if (wc > 1) { double* dp; - if (wc == (u_short) TIFF_VARIABLE) + if (wc == (u_short) TIFF_VARIABLE + || fip->field_passcount) TIFFGetField(tif, fip->field_tag, &wc, &dp); else TIFFGetField(tif, fip->field_tag, &dp); if (!WRITEF(TIFFWriteDoubleArray, dp)) return (0); } else { - double dv; - TIFFGetField(tif, fip->field_tag, &dv); - if (!WRITEF(TIFFWriteDoubleArray, &dv)) - return (0); + if (fip->field_passcount) { + double* dp; + TIFFGetField(tif, fip->field_tag, &wc, &dp); + if (!WRITEF(TIFFWriteDoubleArray, dp)) + return 0; + } else { + double dv; + TIFFGetField(tif, fip->field_tag, &dv); + if (!WRITEF(TIFFWriteDoubleArray, &dv)) + return (0); + } } break; case TIFF_ASCII: @@ -479,20 +583,32 @@ TIFFWriteNormalTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip) correctness not verified (FW, 99/08) */ case TIFF_BYTE: case TIFF_SBYTE: - if (wc > 1) { - char* cp; - if (wc == (u_short) TIFF_VARIABLE) { - TIFFGetField(tif, fip->field_tag, &wc, &cp); - dir->tdir_count = wc; - } else - TIFFGetField(tif, fip->field_tag, &cp); - if (!TIFFWriteByteArray(tif, dir, cp)) - return (0); + if (wc > 1) { + char* cp; + if (wc == (u_short) TIFF_VARIABLE + || fip->field_passcount) { + TIFFGetField(tif, fip->field_tag, &wc, &cp); + dir->tdir_count = wc; + } else if (wc == (u_short) TIFF_VARIABLE2) { + TIFFGetField(tif, fip->field_tag, &wc2, &cp); + dir->tdir_count = wc2; + } else + TIFFGetField(tif, fip->field_tag, &cp); + if (!TIFFWriteByteArray(tif, dir, cp)) + return (0); } else { - char cv; - TIFFGetField(tif, fip->field_tag, &cv); - if (!TIFFWriteByteArray(tif, dir, &cv)) - return (0); + if (fip->field_passcount) { + char* cp; + TIFFGetField(tif, fip->field_tag, &wc, &cp); + dir->tdir_count = wc; + if (!TIFFWriteByteArray(tif, dir, cp)) + return 0; + } else { + char cv; + TIFFGetField(tif, fip->field_tag, &cv); + if (!TIFFWriteByteArray(tif, dir, &cv)) + return (0); + } } break; @@ -525,7 +641,7 @@ TIFFWriteNormalTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip) static void TIFFSetupShortLong(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint32 v) { - dir->tdir_tag = tag; + dir->tdir_tag = (uint16) tag; dir->tdir_count = 1; if (v > 0xffffL) { dir->tdir_type = (short) TIFF_LONG; @@ -535,6 +651,18 @@ TIFFSetupShortLong(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint32 v) dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v); } } + +/* + * Setup a SHORT directory entry + */ +static void +TIFFSetupShort(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint16 v) +{ + dir->tdir_tag = (uint16) tag; + dir->tdir_count = 1; + dir->tdir_type = (short) TIFF_SHORT; + dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v); +} #undef MakeShortDirent #ifndef TIFFWriteRational @@ -564,8 +692,14 @@ TIFFWritePerSampleShorts(TIFF* tif, ttag_t tag, TIFFDirEntry* dir) uint16* w = buf; int i, status, samples = tif->tif_dir.td_samplesperpixel; - if (samples > NITEMS(buf)) + if (samples > NITEMS(buf)) { w = (uint16*) _TIFFmalloc(samples * sizeof (uint16)); + if (w == NULL) { + TIFFError(tif->tif_name, + "No space to write per-sample shorts"); + return (0); + } + } TIFFGetField(tif, tag, &v); for (i = 0; i < samples; i++) w[i] = v; @@ -589,8 +723,14 @@ TIFFWritePerSampleAnys(TIFF* tif, int i, status; int samples = (int) tif->tif_dir.td_samplesperpixel; - if (samples > NITEMS(buf)) + if (samples > NITEMS(buf)) { w = (double*) _TIFFmalloc(samples * sizeof (double)); + if (w == NULL) { + TIFFError(tif->tif_name, + "No space to write per-sample values"); + return (0); + } + } TIFFGetField(tif, tag, &v); for (i = 0; i < samples; i++) w[i] = v; @@ -625,7 +765,7 @@ TIFFWriteShortTable(TIFF* tif, { uint32 i, off; - dir->tdir_tag = tag; + dir->tdir_tag = (uint16) tag; dir->tdir_type = (short) TIFF_SHORT; /* XXX -- yech, fool TIFFWriteData */ dir->tdir_count = (uint32) (1L<tif_dir.td_bitspersample); @@ -660,7 +800,7 @@ static int TIFFWriteShortArray(TIFF* tif, TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16* v) { - dir->tdir_tag = tag; + dir->tdir_tag = (uint16) tag; dir->tdir_type = (short) type; dir->tdir_count = n; if (n <= 2) { @@ -686,7 +826,7 @@ static int TIFFWriteLongArray(TIFF* tif, TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, uint32* v) { - dir->tdir_tag = tag; + dir->tdir_tag = (uint16) tag; dir->tdir_type = (short) type; dir->tdir_count = n; if (n == 1) { @@ -708,10 +848,15 @@ TIFFWriteRationalArray(TIFF* tif, uint32* t; int status; - dir->tdir_tag = tag; + dir->tdir_tag = (uint16) tag; dir->tdir_type = (short) type; dir->tdir_count = n; t = (uint32*) _TIFFmalloc(2*n * sizeof (uint32)); + if (t == NULL) { + TIFFError(tif->tif_name, + "No space to write RATIONAL array"); + return (0); + } for (i = 0; i < n; i++) { float fv = v[i]; int sign = 1; @@ -731,7 +876,7 @@ TIFFWriteRationalArray(TIFF* tif, while (fv < 1L<<(31-3) && den < 1L<<(31-3)) fv *= 1<<3, den *= 1L<<3; } - t[2*i+0] = sign * (fv + 0.5); + t[2*i+0] = (uint32) (sign * (fv + 0.5)); t[2*i+1] = den; } status = TIFFWriteData(tif, dir, (char *)t); @@ -743,7 +888,7 @@ static int TIFFWriteFloatArray(TIFF* tif, TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, float* v) { - dir->tdir_tag = tag; + dir->tdir_tag = (uint16) tag; dir->tdir_type = (short) type; dir->tdir_count = n; TIFFCvtNativeToIEEEFloat(tif, n, v); @@ -758,7 +903,7 @@ static int TIFFWriteDoubleArray(TIFF* tif, TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, double* v) { - dir->tdir_tag = tag; + dir->tdir_tag = (uint16) tag; dir->tdir_type = (short) type; dir->tdir_count = n; TIFFCvtNativeToIEEEDouble(tif, n, v); @@ -782,14 +927,20 @@ TIFFWriteAnyArray(TIFF* tif, char* w = buf; int i, status = 0; - if (n * tiffDataWidth[type] > sizeof buf) - w = (char*) _TIFFmalloc(n * tiffDataWidth[type]); + if (n * TIFFDataWidth(type) > sizeof buf) { + w = (char*) _TIFFmalloc(n * TIFFDataWidth(type)); + if (w == NULL) { + TIFFError(tif->tif_name, + "No space to write array"); + return (0); + } + } switch (type) { case TIFF_BYTE: { uint8* bp = (uint8*) w; - for (i = 0; i < n; i++) + for (i = 0; i < (int) n; i++) bp[i] = (uint8) v[i]; - dir->tdir_tag = tag; + dir->tdir_tag = (uint16) tag; dir->tdir_type = (short) type; dir->tdir_count = n; if (!TIFFWriteByteArray(tif, dir, (char*) bp)) @@ -798,9 +949,9 @@ TIFFWriteAnyArray(TIFF* tif, break; case TIFF_SBYTE: { int8* bp = (int8*) w; - for (i = 0; i < n; i++) + for (i = 0; i < (int) n; i++) bp[i] = (int8) v[i]; - dir->tdir_tag = tag; + dir->tdir_tag = (uint16) tag; dir->tdir_type = (short) type; dir->tdir_count = n; if (!TIFFWriteByteArray(tif, dir, (char*) bp)) @@ -809,7 +960,7 @@ TIFFWriteAnyArray(TIFF* tif, break; case TIFF_SHORT: { uint16* bp = (uint16*) w; - for (i = 0; i < n; i++) + for (i = 0; i < (int) n; i++) bp[i] = (uint16) v[i]; if (!TIFFWriteShortArray(tif, type, tag, dir, n, (uint16*)bp)) goto out; @@ -817,7 +968,7 @@ TIFFWriteAnyArray(TIFF* tif, break; case TIFF_SSHORT: { int16* bp = (int16*) w; - for (i = 0; i < n; i++) + for (i = 0; i < (int) n; i++) bp[i] = (int16) v[i]; if (!TIFFWriteShortArray(tif, type, tag, dir, n, (uint16*)bp)) goto out; @@ -825,7 +976,7 @@ TIFFWriteAnyArray(TIFF* tif, break; case TIFF_LONG: { uint32* bp = (uint32*) w; - for (i = 0; i < n; i++) + for (i = 0; i < (int) n; i++) bp[i] = (uint32) v[i]; if (!TIFFWriteLongArray(tif, type, tag, dir, n, bp)) goto out; @@ -833,7 +984,7 @@ TIFFWriteAnyArray(TIFF* tif, break; case TIFF_SLONG: { int32* bp = (int32*) w; - for (i = 0; i < n; i++) + for (i = 0; i < (int) n; i++) bp[i] = (int32) v[i]; if (!TIFFWriteLongArray(tif, type, tag, dir, n, (uint32*) bp)) goto out; @@ -841,7 +992,7 @@ TIFFWriteAnyArray(TIFF* tif, break; case TIFF_FLOAT: { float* bp = (float*) w; - for (i = 0; i < n; i++) + for (i = 0; i < (int) n; i++) bp[i] = (float) v[i]; if (!TIFFWriteFloatArray(tif, type, tag, dir, n, bp)) goto out; @@ -931,7 +1082,7 @@ TIFFWriteData(TIFF* tif, TIFFDirEntry* dir, char* cp) } } dir->tdir_offset = tif->tif_dataoff; - cc = dir->tdir_count * tiffDataWidth[dir->tdir_type]; + cc = dir->tdir_count * TIFFDataWidth((TIFFDataType) dir->tdir_type); if (SeekOK(tif, dir->tdir_offset) && WriteOK(tif, cp, cc)) { tif->tif_dataoff += (cc + 1) & ~1; @@ -942,6 +1093,87 @@ TIFFWriteData(TIFF* tif, TIFFDirEntry* dir, char* cp) return (0); } +/* + * Similar to TIFFWriteDirectory(), but if the directory has already + * been written once, it is relocated to the end of the file, in case it + * has changed in size. Note that this will result in the loss of the + * previously used directory space. + */ + +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; + +#if defined(__hpux) && defined(__LP64__) +#define HDROFF(f) ((toff_t)(unsigned long) &(((TIFFHeader*) 0)->f)) +#else +#define HDROFF(f) ((toff_t) &(((TIFFHeader*) 0)->f)) +#endif + TIFFSeekFile(tif, HDROFF(tiff_diroff), 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 ); +} + + /* * Link the current directory into the * directory chain for the file. @@ -950,11 +1182,11 @@ static int TIFFLinkDirectory(TIFF* tif) { static const char module[] = "TIFFLinkDirectory"; - uint32 nextdir; - uint32 diroff; + toff_t nextdir; + toff_t diroff, off; tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1; - diroff = (uint32) tif->tif_diroff; + diroff = tif->tif_diroff; if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong(&diroff); #if SUBIFD_SUPPORT @@ -982,7 +1214,7 @@ TIFFLinkDirectory(TIFF* tif) /* * First directory, overwrite offset in header. */ - tif->tif_header.tiff_diroff = (uint32) tif->tif_diroff; + 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))) { @@ -1014,7 +1246,8 @@ TIFFLinkDirectory(TIFF* tif) if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong(&nextdir); } while (nextdir != 0); - (void) TIFFSeekFile(tif, -(toff_t) sizeof (nextdir), SEEK_CUR); + 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);