2005.10.26 16:34 "[Tiff] Fixed TIFFUnlinkDirectory()", by Шебеко Евгений

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