2003.11.21 03:17 "[Tiff] Reading Tiff Image files", by Sridhar Duggireddy

2003.11.21 05:34 "[Tiff] Reading Tiff Image files", by Ross Finlayson

I have a doubt. What does StripOffsets mean? Where is it used? When I searched in the net I found that it is the only field to find the image data.? In my program I'm doing like this to get the image data...Can you please tell me whether I'm doing correct or not?

You don't have to worry about the strip offsets. The strip offsets, when you get them into a unit32* called uint32av with TIFFGetField(tif, TIFFTAG_STRIPOFFSETS, &uint32av), would contain the contents of the Strip Offsets field, then the Strip Byte Counts field contains the extent of each strips data from the corresponding offset, each array has as many elements as there are stripes in the image.

When you call TIFFReadEncodedStrip, the function uses the strip offset and strip byte count for that strip to get the raw, compressed data from the strip. Then, it uncompresses the data into the buffer that you have passed to the TIFFReadEncodedStrip, as you illustrate in your sample program.

The TIFFReadEncodedStrip and TIFFReadRawStrip functions handle the strip offsets and byte counts for you. If you had some reason to access them separately, you can with TIFFGetField, but you shouldn't set them with TIFFSetField, they are determined by TIFFWriteEncodedStrip.

.................. Sample output from tiffdump()......

sample.tif:
Magic: 0x4949 <little-endian> Version: 0x2a
Directory 0: offset 8 (0x8) next 0 (0)
OldSubFileType (255) SHORT (3) 1 <1>
ImageWidth (256) SHORT (3) 1 <4733>
ImageLength (257) SHORT (3) 1 <4733>
BitsPerSample (258) SHORT (3) 1 <8>
Photometric (262) SHORT (3) 1 <1>
StripOffsets (273) LONG (4) 1 <265>
ImageDescription (270) ASCII (2) 155 <[30..46140] PGA-HCL-ast ...>
GrayResponseUnit (290) SHORT (3) 1 <2>

............. Sample Code...............

#include "tiffio.h"
#include <stdio.h>
int main()
{
        TIFF* tif = TIFFOpen("sample.tif","r");
        if(tif)
        {
                uint32 imagelength;
                uint32 w,h;
                int t;
                tstrip_t strips;
                unsigned char *buf;
                FILE *fp;
                fp = fopen("out.txt","w");
                TIFFGetField(tif,TIFFTAG_IMAGELENGTH,&imagelength);
                TIFFGetField(tif,TIFFTAG_IMAGEWIDTH,&w);
                printf("WIDTH = %ld,HEIGHT = %ld\n",w,imagelength);
                strips = TIFFNumberOfStrips(tif);
                printf("Number of strips = %ld\n",strips);
               printf("Strip Size = %ld\n",TIFFStripSize(tif));
                buf = (unsigned char *)(_TIFFmalloc(TIFFStripSize(tif)));
                // Get the image data...
              for(strips=0;strips < TIFFNumberOfStrips(tif);strips++)
                {
                        TIFFReadEncodedStrip(tif,strips,buf,(tsize_t)-1);
                        for(int x = 0; x < TIFFStripSize(tif); x++)
                                fprintf(fp,"%d ",buf[x]);
                        fprintf(fp,"\n");
                }
                _TIFFfree(buf);
                TIFFClose(tif);
        }
}

Here's my suggestion, add another variable and instead of having the strips variable be both the count of strips and later the incrementor, have a separate incrementor and only call TIFFNumberOfStrips once, eg adding tstrip_t i=0; to the variable list and have the for loop be "for(i=0;i<strips;i++)", and changing the TIFFReadEncodedStrip function to use i instead of strips.

Here's another example of storing the result, when you call TIFFStripSize, that function returns the size of a buffer that can hold the contents of each strip. Store that size in a variable and then reuse instead of calling TIFFStripSize, which calculates the strip size from the sample type and dimensions of the strip.

tsize_t strip_size=0;
strip_size=TIFFStripSize(tif);

Then replace the calls to TIFFStripSize(tif) with the variable strip_size.

You might want to check the return value of the TIFFReadEncodedStrip function. It returns (tsize_t)-1 if there was an error. Otherwise, it returns the amount read into the buffer. This won't always be the same as strip_size, but it should be, except for the last strip. This is where if there are, for example, 16 rows per strip, and, the image length is not a multiple of 16, the last strip will only have x/16'ths of the data read, for x between 1 and 15, x is image_length % rows_per_strip.

Instead of using the -1 argument to TIFFReadEncodedStrip for the amount to read, you could replace that with strip_size. Because you already know the value, it might help the function from having to calculate it itself. Also, in some weird case where it would otherwise read more than strip_size, it would stop.

Ross F.