2004.04.04 17:22 "Re: [Tiff] 16 bit gray scale images and tiff", by Andrey Kiselev
On Fri, Apr 02, 2004 at 09:05:31AM -0500, Wendel Dean Renner wrote:
The TIFF 6.0 Specification, on page 22, says "Allowable values for Baseline TIFF grayscale images are 4 and 8, allowing either 16 or 256 distinct shades of gray." Maybe the problem here is the word "Baseline". I don't know what that means.
Well, page 11 of the specification says: "Baseline TIFF is the core of TIFF, the essentials that all mainstream TIFF developers should support in their products." TIFF files can contain a lot of extra info used in complex applications, but simple baseline files should be read by any TIFF-aware applications, even by simple ones.
Where in that document is 16 bits per sample allowed?
Look at the BitsPerSample tag description at the page 29.
In any event I posted a message last week because I could not understand how film scanners could be writing 16 bit gray scale images
> in TIFF format (for x-ray film which is black and white)
I have attached a simple application to write 16-bit TIFF. Search mailing list archives, I have posted sample code to read TIFF images recently.
I want to thank the two people who replied to me. To read a 16 bit gray scale I was told to call
TIFFReadScanline in the TIFF library, and that works. For each pixel the first byte was the most significant byte.
Do I assume that all images are of this byte order?
No. The byte order is specified in TIFF header and you will get the properly swapped bytes from the library.
Another question, is there such a thing as an RGB image with 16 bits per sample (and so 3 samples per pixel)?
Yes, and such images are widely used.
What happens when a 14 bit scanner writes out a color image? Are they truncated to 8 bits per color?
That depends on how the scanner sofware writes image. I believe it should be written in form of 16-bit files.
I notice in the TIFF library that TIFFGetR, TIFFGetB and TIFFGetG assume RGB is 3 bytes, blue the most significant byte, and so byte order is also assumed besides the size of each sample.
Don't use TIFFGetR/G/B functions. They are part of the TIFFRGBAImage interface which is designed for simple viewers and not suitable for your needs.
Lastly, I have a 16 bit TIFF gray scale image file written by Adobe PhotoShop that someone sent me, that TIFFOpen bombs on every time (I mean the program crashes upon calling TIFFOpen passing in the file name as an argument). Yet the image displays OK if I use some other image viewing software. But I have yet another 16 bit gray scale image from PhotoShop.that gets past TIFFOpen and I can read and display the image. I am using a Windows libtiff that I down loaded (I can't remember if it was from your site or someplace else). (I also run under Linux and have not tried it there yet.)
Please, try the latest libtiff package (3.6.1). If you still get an error I shall try to fix the bug (but I shall need a sample image to work).
Andrey V. Kiselev
Home phone: +7 812 5274898 ICQ# 26871517
#define XSIZE 256
#define YSIZE 256
int main (int argc, char **argv)
uint32 image_width, image_height;
float xres, yres;
uint16 spp, bpp, photo, res_unit;
int i, j;
uint16 array[XSIZE * YSIZE];
for (j = 0; j < YSIZE; j++)
for(i = 0; i < XSIZE; i++)
array[j * XSIZE + i] = i * j;
out = TIFFOpen("out.tif", "w");
fprintf (stderr, "Can't open %s for writing\n", argv);
image_width = XSIZE;
image_height = YSIZE;
spp = 1; /* Samples per pixel */
bpp = 16; /* Bits per sample */
photo = PHOTOMETRIC_MINISBLACK;
TIFFSetField(out, TIFFTAG_IMAGEWIDTH, image_width / spp);
TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, bpp);
TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, spp);
TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photo);
TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_BOTLEFT);
/* It is good to set resolutions too (but it is not nesessary) */
xres = yres = 100;
res_unit = RESUNIT_INCH;
TIFFSetField(out, TIFFTAG_XRESOLUTION, xres);
TIFFSetField(out, TIFFTAG_YRESOLUTION, yres);
TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, res_unit);
for (j = 0; j < image_height; j++)
TIFFWriteScanline(out, &array[j * image_width], j, 0);