2012.11.24 00:09 "[Tiff] help writing thumbnails to TIFF file?", by Paul Heckbert

2012.11.24 00:09 "[Tiff] help writing thumbnails to TIFF file?", by Paul Heckbert

I reported this (with subject TIFFCheckpointDirectory not working when
writing two IFDs) a week ago at bugzilla
(http://bugzilla.maptools.org/show_bug.cgi?id=2417) but have not heard a
reply, so I'll try here.

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.

/* Write a test picture to a TIFF file, with thumbnail and EXIF, using

* 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;

/* 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);


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_ROWSPERSTRIP, ny)); /* one strip */ printf("set_tags %d %d %d\n", nx, ny, compression); assert(TIFFSetField(tif, TIFFTAG_COMPRESSION, compression)); if (compression == COMPRESSION_LZW)


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");

if (checkpoint) {
  set_tags(tif, px, py, COMPRESSION_LZW);
  /* write IFD0 (preliminary version) and create an empty IFD1 */
  set_tags(tif, tx, ty, COMPRESSION_NONE);
  /* write IFD1 (preliminary version) and create an empty IFD2 */
  /* set current dir to IFD1 */
  assert(TIFFSetDirectory(tif, 1));
  /* write pixels of thumbnail */
  write_image(tif, tx, ty);
  /* write IFD1 */
  /* 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 */
  set_tags(tif, tx, ty, COMPRESSION_NONE);
  /* write pixels of thumbnail */
  write_image(tif, tx, ty);

 /* causes TIFFWriteDirectory to be called */
 return 0;
DEP = ../../../dependencies
TIFF = $(DEP)/tiff-4.0.3/build
COPTS = -g -Wall -Werror

TIFF_DYLIB = $(TIFF)/lib/libtiff.dylib

thumb: thumb.o $(TIFF_DYLIB)
 gcc $(COPTS) -o $@ $^ $(TIFF_DYLIB)

 gcc -c $(COPTS) -I$(TIFF)/include $<
View this message in context: http://old.nabble.com/help-writing-thumbnails-to-TIFF-file--tp34716184p34716184.html
Sent from the Tiff / LibTiff mailing list archive at Nabble.com.