2016.10.25 20:02 "[Tiff] problem adding YRESOLUTION and RESOLUTIONUNIT to 16bit grayscale TIFF", by Paul Hemmer

2016.10.27 15:55 "Re: [Tiff] problem adding YRESOLUTION and RESOLUTIONUNIT to 16bit grayscale TIFF", by Paul Hemmer

My colleague helped in tracing the problem to a bug in the libtiff code, and to help any future searchers, I'll post his findings below that solved the problem. I can't seem to tell if anybody actively maintains this library anymore?

The issue is in tif_dirwrite.c, part of libtiff. It exists in libtiff 3.8.0, 3.8.2; and bigtiff 4.1.

The basic issue is how the method to write out a pair of Rationals (WriteRationalPair) handles the directory pointer (dir).

The original code treats 'dir' as a regular pointer, which is incorrect. Simply incrementing the pointer does not point to the next directory entry. There is special method (TDIREntryNext) provided for handling the pointer.

Changing WriteRationalPair to use TDIREntryNext resolved the problem of YResolution not be being written. It also solved an issue found during debug where YPosition was not being correctly written. [Setting YPosition was tested as both the resolution and position are written out by WriteRationalPair .] Furthermore, the correction fixed an invalid free() call that was caught in the debug build.

The changes are highlighted below.

The original code (tif_dirwrite.x, line 67)

#define       WriteRationalPair(type, tag1, v1, tag2, v2) {          \

       TIFFWriteRational((tif), (type), (tag1), (dir), (v1))  \

       TIFFWriteRational((tif), (type), (tag2), (dir)+1, (v2))       \

       (dir)++;                                        \

}

The fixed code (tif_dirwrite.x, line 67)

#define       WriteRationalPair(type, tag1, v1, tag2, v2) {          \

       TIFFWriteRational((tif), (type), (tag1), (dir), (v1))  \

       TDIREntryNext(tif, (dir)); /* go to next entry */ \

       TIFFWriteRational((tif), (type), (tag2), (dir), (v2))  \

}