2006.09.27 10:01 "[Tiff] help", by Robert Scheck

2006.10.16 19:35 "Re: [Tiff] Handling Of SubIFD in Libtiff Ver 3.8.3", by Sebastian Boehmer

Hi folks,

Anurag Singh schrieb:
>
> In your code, you are setting TIFFTAG_PRIVATE_OFFSET for SubIFD

> offset. Is there any use of it??. we can get the offset of any subIFD > with this tag only TIFFTAG_SUBIFD.

The tag TIFFTAG_PRIVAT_OFFSET is fictitious. You can define other tag numbers as tags.

You define your tag with:
static const TIFFFieldInfo tiffIFDOffset[] = {
       { TIFFTAG_PRIVATE_OFFSET, 1,1, TIFF_LONG, FIELD_CUSTOM,
               TRUE, FALSE, "IMTEK ATR2 IFD" }
};

The tifftag number must be bigger than 32768.

The structure of the example above is:

*typedef*       *struct* {
        ttag_t  field_tag;              //* field's tag *//
        short   field_readcount;        //* read count/TIFF_VARIABLE/TIFF_SPP *//
        short   field_writecount;       //* write count/TIFF_VARIABLE *//
        TIFFDataType field_type;        //* type of associated data *//
        unsigned short field_bit;       //* bit in fieldsset bit vector *//
        unsigned char field_oktochange; //* if true, can change while writing *//
        unsigned char field_passcount;  //* if true, pass dir count on set *//
        char    *field_name;            //* ASCII name *//

} TIFFFieldInfo;

> how do we deal with the image which have 2 oe more SubIFDs. hmmm? You are right, that is a case I forgot to implement.

In General:

You use for every single private/sub IFD a structure like above.

>From the definition of TIFF 6.0 is in every directory the number of tiff tags in the directory.

When you create several directories, you could read perhaps each directory with TIFFReadPrivateDirectoryWithInfo(...).

For the support of writing more than one directory seperatly I will take a look on the code in the next week.

>
> what i earlier used to do generally we use

> TIFFSetSubDirectory(input_tiff,subifdoffset) function to read SubIFD, > i think this should also be modified.

Yes could be I will take a look.

>

> One important question, wht is the flow of reading and writing when > a image have one aur more subIFD's.

Every directory lays one after another in the tiff file. See the adobe TIFF 6.0 specification for the format.

An interface for this doesn't exist in the moment - I think so.

>
> i am writing over here wht i have done with my code, please do
> correction if any
>
> 1) Read main IFD ( for example IFD 0)
> 2) Get offset of subIFD if any
> 3) read subIFD by using TIFFReadPrivateDirectory(TIFF* tif, toff_t
> diroff)

It looks right. Additionally, you have to collect the variables with TIFFGetField (and perhaps write variables with TIFFSetField).

>
> if we have more than one subIFD then all the entries goes in

> tif->tif_privateFieldInfo. And at the time of writing we are not able > diffrenciate which entris belongs to which subIFD.

>

Yes it will be possible with a new Interface function: TIFFWritePrivateDirectoryWithFieldInfo.

Perhaps we schould omit the actual unnecessary TIFFWritePrivateDirectory and TIFFReadPrivateDirectory or?

> am i right?? So we have to read n write one by one subIFD ( act my aim > is just reading n writing any tiff image)

>

> and wht about the offsets of subIFD, we have to finally set all the > offset of subIFD before writing main IFD or libtiff will take care of it. Yes this is also a littel problem. :-) The libtiff didn't care about it at the moment.

--
Greetings, Sebastian
>
> please suggest me.
>
> Thanks
> Anurag Singh
>
>
>
>
>
>
>
>
>
>

> On 10/11/06, *Sebastian Boehmer* <sebastian.boehmer@web.de > <mailto:sebastian.boehmer@web.de>> wrote:

This Problem could be solved with the patch in the bugzilla report 1320
http://bugzilla.remotesensing.org/show_bug.cgi?id=1320

It add the following interface for private sub IFD support:
extern void TIFFMergePrivateFieldInfo(TIFF*, const TIFFFieldInfo[],unsigned int);

extern  const TIFFFieldInfo* TIFFFindPrivateFieldInfo(TIFF*,  ttag_t, TIFFDataType);
extern  const TIFFFieldInfo* TIFFPrivateFieldWithTag(TIFF*, ttag_t);

extern  int TIFFSetPrivateField(TIFF*, ttag_t, ...);
extern  int TIFFVSetPrivateField(TIFF*, ttag_t, va_list);
extern  int TIFFGetPrivateField(TIFF*, ttag_t, ...);
extern  int TIFFVGetPrivateField(TIFF*, ttag_t, va_list);
extern  int TIFFWritePrivateDirectory(TIFF*, toff_t*);
extern  int TIFFReadPrivateDirectory(TIFF*, toff_t);
extern  int TIFFReadPrivateDirectoryWithFieldInfo(TIFF*, toff_t,  const TIFFFieldInfo[], size_t);

In the attachment is an example Interface for the ATR private tags.
The code below comes from this files.
greets, Sebastian

Here is a draft of an example:

Use the code for custom tags from
http://www.remotesensing.org/libtiff/addingtags.html
The essenctial changes are marked with //!!!

 File: private_tags.h
---

>     #include < tiffio.h>

#include <tiff.h>

#define    TIFFTAG_PRIVATE_OFFSET       0xB10A  // !!!

//!!!

/* TIFF_IFD is actual not correct implemented in libtiff. */

        //{ TIFFTAG_PRIVATE_OFFSET, 1,1, TIFF_IFD,      FIELD_CUSTOM,

        //      TRUE, FALSE, "IMTEK ATR2 IFD" }
        /* BUG: libtiff 06-09-26: TIFF_IFD didn't work correct  date:06-09-26 */

        { TIFFTAG_PRIVATE_OFFSET, 1,1, TIFF_LONG, FIELD_CUSTOM,
                TRUE, FALSE, "IMTEK ATR2 IFD" }
};

    static const TIFFFieldInfo xtiffFieldInfo[] = {

/* XXX Insert Your tags here */

    { TIFFTAG_GEOPIXELSCALE,    -1,-1, TIFF_DOUBLE,     FIELD_CUSTOM,

      TRUE,     TRUE,   "GeoPixelScale" },
    { TIFFTAG_GEOTRANSMATRIX,   -1,-1, TIFF_DOUBLE,     FIELD_CUSTOM,
      TRUE,     TRUE,   "GeoTransformationMatrix" },
    { TIFFTAG_GEOTIEPOINTS,     -1,-1, TIFF_DOUBLE,     FIELD_CUSTOM,
      TRUE,     TRUE,   "GeoTiePoints" },
    { TIFFTAG_GEOKEYDIRECTORY, -1,-1, TIFF_SHORT,       FIELD_CUSTOM,
      TRUE,     TRUE,   "GeoKeyDirectory" },
    { TIFFTAG_GEODOUBLEPARAMS,  -1,-1, TIFF_DOUBLE,     FIELD_CUSTOM,
      TRUE,     TRUE,   "GeoDoubleParams" },

    { TIFFTAG_GEOASCIIPARAMS,   -1,-1, TIFF_ASCII,      FIELD_CUSTOM,

      TRUE,     FALSE,  "GeoASCIIParams" }

};

#define N(a)    (sizeof (a) / sizeof (a[0]))

static TIFFExtendProc _ParentExtender = NULL;

static
void _XTIFFInitialize(void)
{
    static int first_time=1;

if (! first_time) return; /* Been there. Done that. */
first_time = 0;

    /* Grab the inherited method and install */
    _ParentExtender = TIFFSetTagExtender(_XTIFFDefaultDirectory);
}

static void

_XTIFFDefaultDirectory(TIFF *tif)
{
    /* Install the extended Tag field info */

    TIFFMergeFieldInfo(tif, tiffIFDOffset,  N(tiffIFDOffset));                   // !!!
    TIFFMergePrivateFieldInfo(tif, xtiffFieldInfo,  N(xtiffFieldInfo));          // !!!

    /* Since an XTIFF client module may have overridden
     * the default directory method, we call it now to
     * allow it to set up the rest of its own methods.
     */

    if (_ParentExtender)
        (*_ParentExtender)(tif);
}

---

File: application.cc
---
#include <tiffio.h> // the libtiff

int main()
{

char filename[] = "test.tiff";
unsinged int length=100, width=100;
uint16 bps=8, spp=1;
unsigned char* imageBuffer = new unsigned char[2*length*width];

_XTIFFInitialize();
TIFF* image;
if (( image = TIFFOpen(filename,"w")) == NULL) {
        printf("Could not open %s for \n",filename);
        return -1;
}

        /*
        * Write the Image
        */
        // Check that it is of a type that we support

if(TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, bps) == 0){ printf("Couldn't write the bits per sample. It is not possible to write the image."); TIFFClose(image);

        return -1;
}

if(TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, spp) == 0){ printf("Couldn't write number of samples per pixel (last time %i)",spp); TIFFClose(image);

        return -1;
}
if(TIFFSetField(image, TIFFTAG_IMAGEWIDTH, width) == 0){
        printf("Couldn't write the width (last time %i)",width);
        TIFFClose(image);
        return -1;
}

... see attachment

/* write the image data */
if ( bps == 8 ) {
        if ( TIFFWriteEncodedStrip(image, 0, imageBuffer, width * length) == 0 ) {
                printf("Write error: TIFF image writing. \nPerhaps not enought memory?");
                TIFFClose(image);
                return -2;
        }

} else
        if ( TIFFWriteEncodedStrip(image, 0, imageBuffer, width * length * 2) == 0) {
                printf("Write error: TIFF image writing. \nPerhaps not enought memory?");
                TIFFClose(image);
                return -2;
        }

        /*
        * Write the Offset
        */
        // with pseudo value for calculating offset
        if (!TIFFSetField(image, TIFFTAG_PRIVATE_OFFSET, 0 ))

        printf("Couldn't write the offset tag to 0");
if (!TIFFCheckpointDirectory(image))
        printf("Couldn't write the checkpoint");
tiff_ifd_offset = TIFFCurrentDirOffset(image);

if (!TIFFSetField(image, TIFFTAGSPEC_OFFSET_V1, tiff_ifd_offset)) { printf("Couldn't write the offset tag (offset=%d)",TIFFCurrentDirOffset(image));

}
if (!TIFFWriteDirectory(image)) {
        printf("Couldn't write the directory");
        TIFFClose(image);
        return -5;
}

        /*
        * Write the private values
        */
        if (! TIFFSetPrivateField(image, TIFFTAG_GEOPIXELSCALE, 0.3  ) {

        printf("Error at writing private field\n");
        return -2;
}

...

        /*
        * Write the private Sub IFD
        */
        toff_t tiff_ref_offset = 0;
        if (!TIFFWritePrivateCustomDirectory(image,&tiff_ref_offset)) {

        printf("Couldn't write the custom directory\n");
        TIFFClose(image);
        return -8;
}

TIFFClose(image);

/*
 * now we read the file
 */

if ( (image = TIFFOpen(filename,"r")) == NULL ) {
        printf("Could not open %s for reading \n",filename);
        return -3;
}

/*
        * Get the Image
        */
// Check that it is of a type that we support

if((TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bps) == 0) || !((bps == 8) || (bps == 16))){ printf("Either undefined or unsupported number of bits per sample (should be 8 or 16)"); TIFFClose(image);

        return -1;
}

if((TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp) == 0) || (spp != 1)){ printf("Either undefined or unsupported number of samples per pixel (should be 1)"); TIFFClose(image);

        return -1;
}

...

/* read the image */
for (row = 0; row < length; row++)
        if ( TIFFReadScanline(image, &imageBuffer[row*scanLineSize], row, 0) == -1 ) {
                sprintf(error_str,"Read error on input \nscanLineSize=%i row=%i",scanLineSize,row);
                setError(error_str);
                closeFile(image);
                return -1;
        }

...
        /*
         * Read the private subIFD
         */

toff_t tiff_ifd_offset;
// get the offset to the directory

if (! TIFFGetField(image, TIFFTAG_PRIVATE_OFFSET, &tiff_ifd_offset) ) { printf("Couldn't find the private IFD Offset to the ATR tags.");

        return -2;
}
// read directory from offset
if (! TIFFReadPrivateCustomDirectory(image, tiff_ifd_offset) ) {
        printf("Couldn't read the private ATR tags.");
        return -2;
}

        /*
        * Read the private values
        */

float f;

if (TIFFGetPrivateField(image, TIFFTAG_GEOPIXELSCALE, &f) == 0) { printf("Couldn't read the private value geo pixel scale");

        }
...

TIFFClose(image);

        return 0;
}

> <mailto:Tiff@lists.maptools.org>

> ------------------------------------------------------------------------
>
> _______________________________________________
> Tiff mailing list: Tiff@lists.maptools.org
> http://lists.maptools.org/mailman/listinfo/tiff
> http://www.remotesensing.org/libtiff/