You need to log in before you can comment on or make changes to this bug.
I am trying to use libtiff to create a TIFF file that contains two IFDs, one for the primary image and one for a small thumbnail image. I'd like the order of data in the TIFF file to be IFD0, IFD1, thumbnail image, primary image -- that would be most consistent with other image creation software, e.g. Photoshop. Surely this should be possible with libtiff. The attached C code is a pretty minimal demonstration of the problem. If run with no arguments, it results in two warnings _TIFFVGetField: thumb.tif: Invalid tag "Predictor" (not supported by codec). _TIFFVGetField: thumb.tif: Invalid tag "Predictor" (not supported by codec). and then crashes with thumb.c:68: failed assertion `TIFFSetDirectory(tif, 1)' Abort trap and if I examine the partially-written output file with exiftool, it shows that IFD1 was written directly on top of IFD0 - this is not what I wanted and probably explains the Predictor messages. The man page for TIFFCheckpointDirectory is sketchy, as is much of libtiff's documentation. There is no discussion of how TIFFWriteDirectory or TIFFCheckpointDirectory increment the current directory index, although examination of the source code makes that clear, making it a challenge for anyone trying to write multiple IFDs with any control over the order of data in the file. And I don't find any example uses of TIFFCheckpointDirectory in the tools/ or contrib/ dirs, so consequently I am only able to guess that I'm using TIFFCheckpointDirectory and TIFFSetDirectory properly. Either there's a bug in TIFFCheckpointDirectory or I am using that function incorrectly. Which is it? I'm on Mac OS 10.5.8 and linking with libtiff 4.0.3. thumb.c: --- /* Write a test picture to a TIFF file, with thumbnail and EXIF, using libtiff. * * Run "thumb -nocheckpoint" to write data in the order: * primary image, IFD0, thumbnail image, IFD1. * and most software (e.g. Mac Finder, exiftool) does not find IFD1, it seems. * With no args, this program uses TIFFCheckpointDirectory to write in the order I'd prefer: * IFD0, IFD1, thumbnail image, primary image. * But running it this way causes IFD1 to overwrite IFD0 * and gives an assert on the first call to TIFFSetDirectory. * * Paul Heckbert, 2012/11/15 */ #include <assert.h> #include <string.h> #include <tiffio.h> static void write_image(TIFF *tif, int nx, int ny) { uint8 *buf = _TIFFmalloc(nx*3); int x, y; assert(buf); /* picture has horizontal ramp in red, vertical ramp in green */ for (y=0; y<ny; y++) { uint8 *p = buf; for (x=0; x<nx; x++) { *p++ = x*255/(nx-1); /* r */ *p++ = y*255/(ny-1); /* g */ *p++ = 0; /* b */ } assert(TIFFWriteScanline(tif, buf, y, 0) != -1); } _TIFFfree(buf); } static void set_tags(TIFF *tif, int nx, int ny, int compression) { assert(TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, nx)); assert(TIFFSetField(tif, TIFFTAG_IMAGELENGTH, ny)); assert(TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8)); assert(TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)); assert(TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, ny)); /* one strip */ printf("set_tags %d %d %d\n", nx, ny, compression); assert(TIFFSetField(tif, TIFFTAG_COMPRESSION, compression)); if (compression == COMPRESSION_LZW) assert(TIFFSetField(tif, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL)); assert(TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT)); assert(TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)); assert(TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3)); } int main(int argc, char **argv) { int px = 640, py = 480; /* primary image size */ int tx = 160, ty = 120; /* thumbnail image size */ char *filename = "thumb.tif"; int checkpoint = argc!=2 || strcmp(argv[1], "-nocheckpoint"); TIFF *tif = TIFFOpen(filename, "w"); assert(tif); if (checkpoint) { set_tags(tif, px, py, COMPRESSION_LZW); /* write IFD0 (preliminary version) and create an empty IFD1 */ assert(TIFFCheckpointDirectory(tif)); set_tags(tif, tx, ty, COMPRESSION_NONE); /* write IFD1 (preliminary version) and create an empty IFD2 */ assert(TIFFCheckpointDirectory(tif)); /* set current dir to IFD1 */ assert(TIFFSetDirectory(tif, 1)); /* write pixels of thumbnail */ write_image(tif, tx, ty); /* write IFD1 */ assert(TIFFWriteDirectory(tif)); /* set current dir to IFD0 */ assert(TIFFSetDirectory(tif, 0)); /* write pixels of primary image */ write_image(tif, px, py); } else { set_tags(tif, px, py, COMPRESSION_LZW); /* write pixels of primary image */ write_image(tif, px, py); /* write IFD0 */ assert(TIFFWriteDirectory(tif)); set_tags(tif, tx, ty, COMPRESSION_NONE); /* write pixels of thumbnail */ write_image(tif, tx, ty); } /* causes TIFFWriteDirectory to be called */ TIFFClose(tif); return 0; } --- Makefile --- DEP = ../../../dependencies TIFF = $(DEP)/tiff-4.0.3/build COPTS = -g -Wall -Werror TIFFDYLIB = $(TIFF)/lib/libtiff.dylib thumb: thumb.o $(TIFFDYLIB) gcc $(COPTS) -o $@ $^ $(TIFFDYLIB) .c.o: gcc -c $(COPTS) -I$(TIFF)/include $< ---
I see that bug 2135, comment 5 also finds problems with TIFFCheckpointDirectory, but that code is not trying to create two IFDs, so it's not quite the same situation.
Bugzilla is no longer used for tracking libtiff issues. Remaining open tickets, such as this one, have been migrated to the libtiff GitLab instance at https://gitlab.com/libtiff/libtiff/issues . The migrated tickets have their summary prefixed with [BZ#XXXX] where XXXX is the initial Bugzilla issue number.