- 2016.09.19 18:47 "Re: [Tiff] Accuracy of TIFF Field metadata (COLORMAP)", by
-
2016.11.14 22:49 "Re: [Tiff] Right way to make a multi-resolution pyramid", by Kemp Watson
-
2016.11.14 18:16 "[Tiff] Right way to make a multi-resolution pyramid", by Kemp Watson
- 2016.11.14 18:40 "Re: [Tiff] Right way to make a multi-resolution pyramid", by Kemp Watson
- 2016.11.14 18:55 "Re: [Tiff] Right way to make a multi-resolution pyramid", by Dmitry Fedorov
-
2016.11.14 18:16 "[Tiff] Right way to make a multi-resolution pyramid", by Kemp Watson
2016.09.19 16:29 "[Tiff] Accuracy of TIFF Field metadata (COLORMAP)", by
I recently discovered a problem on Windows where I was getting a strange runtime error ("Run-Time Check Failure #2 -S") which turns out was due to stack corruption. This was due to calling TIFFGetField with the wrong parameters, and that was because the field metadata in tif_dirinfo.c was wrong. Here's the broken bit:
{ TIFFTAG_COLORMAP, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_OTHER,
TIFF_SETGET_UNDEFINED, FIELD_COLORMAP, 1, 0, "ColorMap", NULL },
It's the "-1, -1," values which map to TIFF_VARIABLE. It should be -2 which is TIFF_SPP. At least, that's my understanding (which could be wrong).
I wrote a set of type-safe generic tag processing functions in C++ which make use of the metadata and expect it to be correct. The logic is essentially this for the three-array variant:
int readcount = TIFFFieldReadCount(field);
typename T::value_type::value_type *valueptr0, *valueptr1,
*valueptr2; // type of array of array of values
uint32_t count;
if (readcount == TIFF_SPP)
{
uint16_t spp;
ifd->getRawField(TIFFTAG_SAMPLESPERPIXEL, &spp);
ifd->getRawField(tag, &valueptr0, &valueptr1, &valueptr2);
count = static_cast<uint32_t>(spp);
}
else if (readcount == TIFF_VARIABLE)
{
uint16_t n;
ifd->getRawField(tag, &n, &valueptr0, &valueptr1,
&valueptr2);
count = static_cast<uint32_t>(n);
}
else if (readcount == TIFF_VARIABLE2)
{
ifd->getRawField(tag, &count, &valueptr0, &valueptr1,
&valueptr2);
}
else
{
if (!limit)
ifd->getRawField(tag, &valueptr0, &valueptr1,
&valueptr2);
else
ifd->getRawField(tag, &valueptr0);
count = static_cast<uint32_t>(readcount);
}
// copy valueptr[0-2] + count into destination array(s)
Note: it's using wrappers around libtiff, but getRawField is essentially TIFFGetField with added locking for thread safety. (https://github.com/ome/ome-files-cpp/blob/develop/lib/ome/files/tiff/Field.cpp#L522 is the actual code and https://github.com/ome/ome-files-cpp/blob/develop/lib/ome/files/in/OMETIFFReader.cpp#L817 is an example of its use)
Since I'm hitting the TIFF_VARIABLE case, I'm clearly calling TIFFGetField with the wrong arguments and this ends up trashing the stack (since we're storing a 64-bit pointer in a 16-bit type).
Assuming I'm not totally wrong in my understanding, the wider question here is this: is the field metadata generally usable? Or does it need a proper audit of every field to ensure the types are correct in every case? Would it help to use the VARIABLE/VARIABLE2/SPP values in place of negative values?
Regards,
Roger
--
Dr Roger Leigh -- Open Microscopy Environment
Wellcome Trust Centre for Gene Regulation and Expression, School of Life Sciences, University of Dundee, Dow Street, Dundee DD1 5EH Scotland UK Tel: (01382) 386364