AWARE [SYSTEMS] Imaging expertise for the Delphi developer
AWare Systems, Imaging expertise for the Delphi developer, Home TIFF and LibTiff Mailing List Archive

LibTiff Mailing List

TIFF and LibTiff Mailing List Archive
October 2005

Previous Thread
Next Thread

Previous by Thread
Next by Thread

Previous by Date
Next by Date

Contact

The TIFF Mailing List Homepage
This list is run by Frank Warmerdam
Archive maintained by AWare Systems



Valid HTML 4.01!



Thread

2005.10.24 07:20 "How can I insert IFD at custom index?", by Eugene Shebeko
2005.10.24 20:02 "Re: How can I insert IFD at custom index?", by Andrey Kiselev
2005.10.24 20:16 "Re: How can I insert IFD at custom index?", by Andrey Kiselev
2005.10.25 06:53 "Re: How can I insert IFD at custom index?", by Eugene Shebeko
2005.10.26 14:45 "Re: How can I insert IFD at custom index?", by Eugene Shebeko

2005.10.26 14:45 "Re: How can I insert IFD at custom index?", by Eugene Shebeko

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 fetching directory
                    link");
                                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 fetching directory link");
                        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 fetching directory
                    link");
                                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;
}