From: libtiff@apexinternetsoftware.com (Finlayson, Ross)
Date: Tue, 18 Nov 2003 03:28:37 -0800
Subject: [Tiff] TIFFGetField COLORMAP memory allocation
In-Reply-To: <Pine.LNX.4.44.0311180219130.32167-100000@metromaster.physics.ucsb.edu>
Message-ID: <200311181116.hAIBGe6l019432@whale2.fsr.net>

On Tuesday, November 18, 2003, at 02:23 AM, Nathan Becker wrote:

> Hi,
>
> I'm trying to read the colormap from an RGB palette tiff file using
>
> something like
>
> ..._TIFFmalloc(red...);
> ...green...
> ...blue...
> TIFFGetField(tiff, TIFFTAG_COLORMAP, &red, &green, &blue);
> ...
> _TIFFfree(red);
>
> After a bunch of seg faults and screwing around I realized that
> TIFFGetField seems to secretly allocate the memory for red, green, and
> blue.  Is this right?  The documentation seems to indicate I'm supposed 
> to
> provide allocated memory to TIFFGetField.  Also, if it does secretly
> allocate memory, then am I supposed to free the red, green, blue arrays?
> It seems like not because doing so gives me a seg fault.
>
> thanks in advance for the help,
>
> Nathan
>
> _______________________________________________
> Tiff mailing list
> Tiff@remotesensing.org
> http://remotesensing.org/mailman/listinfo/tiff
>

Don't allocate memory for the fields or free them.  The color map is 
read into the TIFF structures TIFFDirectory structure when the image is 
opened.  The memory is allocated and released by libtiff.  The 
TIFFGetField function just puts the value of its colormap pointers into 
your variables that are passed by address to the function.

uint16* red;
uint16* green;
uint16* blue;

TIFFGetField(tiff, TIFFTAG_COLORMAP, &red, &green, &blue);

Then each pointer should have 2^bits_per_sample entries.  You should be 
confident that you can index into the red, green, or blue pointers from 
zero to 2^bits_per_sample without an error.  This is so until you change 
the directory of the TIFF or close the TIFF, don't try and read or write 
to the field after changing the TIFF directory.

When you get a field that is a pointer field, like char* or uint16*, 
libtiff has already allocated space for it and put the data the array, 
and will free it when it's done.


Here's my issue with colormap, the indexed tag is a post-6.0 addition to 
the TIFF specification as described in TIFFPM.pdf.  A document that has 
the indexed tag set means that it is a color mapped/ palettized image, 
where it then has Photometric Interpretion of RGB, CMYK, or other.  
Then, the colormap field might contain 4* 2^bits_per_sample instead of 
3* 2^bits_per_sample uint16 entries.  I've not heard of anyone using 
palettized CMYK or other images with more than 3 components but it is 
specified, also the photometric intepretation tag would still be 
misleading.  That could cause problems of the indexed image was loaded 
by libtiff, variously from overreading the data or not being able to get 
the fourth component map.  I think it's not a large issue because I 
think that tag is rarely used.  Yet, I could be wrong.


About the only place you need to allocate your own memory is for 
TIFFReadEncodedStrip or TIFFReadEncodedTile, or TIFFReadRGBAImage, for 
example, putting the image sample data into an array or buffer.  Then, 
if you wanted to realize the palette of the data, then you would 
allocate a large buffer for the image and place in it for each sample 
the values from the colormaps of the index of the sample.  Then, you 
free the image data buffers when you are done with them.  The size of 
the buffer you should allocate for a strip or tile is the result of 
TIFFStripSize or TIFFTileSize, resp.  To contain the entire image, the 
buffer should be at least TIFFStripSize * TIFFNumberOfStrips, or 
calculated for 8 bits per sample by 
image_width*image_height_samples_per_pixel.  One of the arguments to 
TIFFReadEncodedStrip is the maximum size to be read so libtiff doesn't 
overrun your buffer.


Ross F.

