I think @KSletmoe has pointed out a key point that the SubIFD tag(330) should be added in IFD0 before you write any subIFD, but there is still a problem.
The definition of SubIFD tag is "Offset to child IFDs". So, if you don't set the offset correctly, tiff parser can not parse the whole tiff correctly.
There are two ways to handle this situation.
First, pre-calculate the size of each IFD/SubIFD, then fill-in to SubIFD tag when you set, instead of setting 0x0.
Or you can write every IFD as normal then go back to IFD0 and add SubIFD tag with final offset that calculated by libtiff. Like following:
//Write down every thing you need in a tiff
// ... IFD0
TIFFWriteDirectory(tif);
// ... IFD1
TIFFWriteDirectory(tif);
// ... IFD2
TIFFWriteDirectory(tif);
//set current Dir as IFD0 in the end
TIFFSetDirectory(tif, 0);
//get next dir offset
sub_offset[1] = TIFFGetNextDirOff(tif, 2);
sub_offset[0] = TIFFGetNextDirOff(tif, 1);
//only for clean next dir offset in IFD0
no_use_offset = TIFFGetNextDirOff(tif, 0);
TIFFSetField(tif, TIFFTAG_SUBIFD, 2, sub_offset);
You may need to add flowing function in tif_dir.c
uint64 TIFFGetNextDirOff(TIFF* tif, uint16 dirn)
{
uint64 nextdir;
uint16 n;
if (!(tif->tif_flags&TIFF_BIGTIFF))
nextdir = tif->tif_header.classic.tiff_diroff;
else
nextdir = tif->tif_header.big.tiff_diroff;
for (n = dirn; n > 0 && nextdir != 0; n--)
if (!TIFFAdvanceDirectory(tif, &nextdir, NULL))
return (0);
/*!!Watchout!! Here will reset the next dir offset to 0*/
tif->tif_nextdiroff = 0;
return nextdir;
}
Thanks for @KSletmoe. Hope this can help someone, and looking forward some much elegant way to do so.