2007.08.24 21:08 "[Tiff] A few libtiff4 changes", by Frank Warmerdam

2007.08.24 21:08 "[Tiff] A few libtiff4 changes", by Frank Warmerdam

Joris / Andrey,

I made a few changes in libtiff4 to get GDAL overview and multi-directory support working smoothly again. These changes are now all in CVS.

This change just added a runtime check for a check that was only an assertion before. I don't know if it is strictly useful, but it seemed prudent.

Index: tif_dirread.c

=================================================================== RCS file: /cvs/maptools/cvsroot/libtiff/libtiff/tif_dirread.c,v retrieving revision 1.129

diff -r1.129 tif_dirread.c
4504a4505,4511

 >         if( fii == 0xFFFFFFFF )
 >         {
 >             TIFFErrorExt(tif->tif_clientdata, "TIFFFetchNormalTag",
 >                          "No definition found for tag %d",
 >                          dp->tdir_tag);
 >             return 0;
 >         }

This change, in _TIFFMergeFields() handled the case where a field is defined that was already defined. Previously an error was issued and no fields were defined in the call. This change only merges in field definitions for which a definition does not already exist. Duplicates are silently ignored. Without this it seemed that any multi-directory file was resulting in terrible redefinition warnings even just with tiffinfo.

diff -r1.94 tif_dirinfo.c
333,344d332

<       for (i = 0; i < n; i++) {
<               const TIFFField *fip =
<                       TIFFFindField(tif, info[i].field_tag, TIFF_ANY);
<               if (fip) {
<       for (i = 0; i < n; i++) {
<               const TIFFField *fip =
<                       TIFFFindField(tif, info[i].field_tag, TIFF_ANY);
<               if (fip) {
<                       TIFFErrorExt(tif->tif_clientdata, module,
<                       "Field with tag %lu is already registered as \"%s\"",
<                                    (unsigned int) info[i].field_tag,
<                                    fip->field_name);
<                       return 0;
<               }

< }
<
361a350
 >
363,364c352,361
< for (i = 0; i < n; i++)

<               *tp++ = (TIFFField *) (info + i);       /* XXX */

---
 > 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 *) (inf

o+i);
 > tif->tif_nfields++;
 > }
 > }
367c364
< qsort(tif->tif_fields, tif->tif_nfields += n,
---
 > qsort(tif->tif_fields, tif->tif_nfields,

This change is the "real beef" I needed for GDAL. GDAL's overview writer creates directories for several directories for overviews, then goes back and generates the imagery and updates the strip/tile pointers and rewrites the directory. The TIFFWriteDirectory() function was always writing a "zero" next pointer instead of writing an existing valid next pointer back. This change makes it possible to read a directory in the middle of the chain, change something (hopefully not changing the size of the directory!) and then write it back without disrupting the chain.

diff -r1.56 tif_dirwrite.c
784c784
< *(uint32*)n=0;
---

 >               *(uint32*)n = tif->tif_nextdiroff;

814c814
< *(uint64*)n=0;
---

 >               *(uint64*)n = tif->tif_nextdiroff;

With these changes GDAL overview generation seems to work fine, and in fact the full GDAL test suite passes. I am now inclined to migrate libtiff4 into GDAL as it's primary working version.

Best regards,
--
---------------------------------------+--------------------------------------

I set the clouds in motion - turn up   | Frank Warmerdam, warmerdam@pobox.com
light and sound - activate the windows | http://pobox.com/~warmerdam

and watch the world go round - Rush    | President OSGeo, http://osgeo.org