2003.11.18 10:23 "[Tiff] TIFFGetField COLORMAP memory allocation", by Nathan Becker

2003.11.18 11:28 "[Tiff] TIFFGetField COLORMAP memory allocation", by Ross Finlayson

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.

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.