2005.10.26 14:45 "Re[3]: [Tiff] How can I insert IFD at custom index?", by Шебеко Евгений
I wrote function for this.
When it could be useful.
For example, when you need to insert image in a middle of IFD chain.
You call TIFFCreateDirectory(), then set tag, then call
TIFFChangeDirectoryIndex()
I tested it in different combination of index, seems it work.
/*
* Change the index of current directory in IFD chain
*/
int TIFFChangeDirectoryIndex(TIFF *tif,tdir_t index)
{
static const char module[] = "TIFFInsertDirectory";
toff_t prev_nextdir;
uint16 dircount;
/*
** Check is index inside valid range
*/
if(index>=TIFFNumberOfDirectories(tif))
{
TIFFError(module,"too big index=%d",index);
return 0;
}
/*
** If same index no changes need to do
*/
if(index==TIFFCurrentDirectory(tif))return 1;
/*
** Need flush current directory
*/
TIFFFlush(tif);
/*
** Unlink current entry
*/
/* Is it the first directory in the file? */
if(tif->tif_header.tiff_diroff==tif->tif_diroff)
{
toff_t diroff; tif->tif_header.tiff_diroff=tif->tif_nextdiroff;
diroff=tif->tif_nextdiroff; if(tif->tif_flags&TIFF_SWAB)TIFFSwabLong(&diroff);
TIFFSeekFile(tif,(toff_t)(TIFF_MAGIC_SIZE+TIFF_VERSION_SIZE),SEEK_SET); if(!WriteOK(tif,&diroff,sizeof(diroff)))
{
TIFFError(tif->tif_name, "Error updating TIFF header");
return 0;
}
}
else
{
toff_t nextdir,prev_nextdir_off;
nextdir=tif->tif_header.tiff_diroff;
do
{
if(!SeekOK(tif,nextdir)||!ReadOK(tif, &dircount, sizeof (dircount)))
{
TIFFError(module, "Error fetching directory count");
return 0;
}
if(tif->tif_flags&TIFF_SWAB)TIFFSwabShort(&dircount);
TIFFSeekFile(tif,dircount*sizeof(TIFFDirEntry),SEEK_CUR);
if(!ReadOK(tif,&nextdir,sizeof (nextdir)))
{
TIFFError(module, "Error directory link");fetching
return 0;
}
if (tif->tif_flags & TIFF_SWAB)TIFFSwabLong(&nextdir);
}
while(nextdir!=tif->tif_diroff&&nextdir!=0);
/*
** Coudn't find our directory in a chain
*/
if(nextdir==0)
{
TIFFError(module,"Coudn't find current directory in a chain");
return 0;
}
prev_nextdir_off=TIFFSeekFile(tif,0,SEEK_CUR)-(toff_t)sizeof(nextdir); /* get current offset */
if(!SeekOK(tif,nextdir)||!ReadOK(tif, &dircount, sizeof (dircount)))
{
TIFFError(module, "Error fetching directory count");
return 0;
}
if(tif->tif_flags&TIFF_SWAB)TIFFSwabShort(&dircount);
TIFFSeekFile(tif,dircount*sizeof(TIFFDirEntry),SEEK_CUR); if(!ReadOK(tif,&nextdir,sizeof (nextdir)))
{
TIFFError(module, "Error directory link");fetching
return 0;
}
TIFFSeekFile(tif,prev_nextdir_off,SEEK_SET); if(!WriteOK(tif,&nextdir,sizeof(nextdir) ))
{
TIFFError(module, "Error writing directory link");
return (0);
}
}
/*
** Link directory to other index
*/
if(index==0)
{
toff_t diroff; tif->tif_nextdiroff=tif->tif_header.tiff_diroff; tif->tif_header.tiff_diroff=tif->tif_diroff;
diroff=tif->tif_header.tiff_diroff; if(tif->tif_flags&TIFF_SWAB)TIFFSwabLong(&diroff);
TIFFSeekFile(tif,(toff_t)(TIFF_MAGIC_SIZE+TIFF_VERSION_SIZE),SEEK_SET); if(!WriteOK(tif,&diroff,sizeof(diroff)))
{
TIFFError(tif->tif_name, "Error updating TIFF header");
return 0;
}
}
else
{
toff_t nextdir,prev_nextdir_off;
tdir_t i;
/*
** Find the IFD that should point to our directory
*/
nextdir=tif->tif_header.tiff_diroff;
for(i=0;i<index;i++)
{
if(nextdir==0)
{
TIFFError(tif->tif_name, "Coudn't scan to index=%d",index);
return 0;
}
if(!SeekOK(tif,nextdir)||!ReadOK(tif, &dircount, sizeof (dircount)))
{
TIFFError(module, "Error fetching directory count");
return 0;
}
if(tif->tif_flags&TIFF_SWAB)TIFFSwabShort(&dircount);
TIFFSeekFile(tif,dircount*sizeof(TIFFDirEntry),SEEK_CUR);
prev_nextdir_off=TIFFSeekFile(tif,0,SEEK_CUR);
if(!ReadOK(tif,&nextdir,sizeof (nextdir)))
{
TIFFError(module, "Error
return 0;
}
if (tif->tif_flags & TIFF_SWAB)TIFFSwabLong(&nextdir);
prev_nextdir=nextdir;
}
/*
** Change the pointer in preview IFD to our IFD
*/
nextdir=tif->tif_diroff;
if (tif->tif_flags & TIFF_SWAB)TIFFSwabLong(&nextdir);
TIFFSeekFile(tif,prev_nextdir_off,SEEK_SET); if(!WriteOK(tif,&nextdir,sizeof(nextdir) ))
{
TIFFError(module, "Error writing directory link");
return (0);
}
tif->tif_nextdiroff=prev_nextdir;
}
/*
** Change the pointer in our IFD to old IFD with same index
*/
TIFFSeekFile(tif,tif->tif_diroff,SEEK_SET);
if(!ReadOK(tif, &dircount, sizeof (dircount)))
{
TIFFError(module, "Error fetching directory count");
return 0;
}
TIFFSeekFile(tif,dircount*sizeof(TIFFDirEntry),SEEK_CUR);
prev_nextdir=tif->tif_nextdiroff;
if(tif->tif_flags&TIFF_SWAB)TIFFSwabLong(&prev_nextdir);
if(!WriteOK(tif,&prev_nextdir,sizeof(prev_nextdir) ))
{
TIFFError(module, "Error writing directory link");
return 0;
}
tif->tif_curdir=index;
return 1;
}