Python and 16 bit Tiff

How to convert and save 16-bit single-channel TIF in Python?

I can load a 16 and 32-bit image without problems and see that the 32-bit image is mode F and the 16-bit image is mode I;16S :

 import Image i32 = Image.open('32.tif') i16 = Image.open('16.tif') i32 # <TiffImagePlugin.TiffImageFile image mode=F size=2000x1600 at 0x1098E5518> i16 # <TiffImagePlugin.TiffImageFile image mode=I;16S size=2000x1600 at 0x1098B6DD0> 

But I am having problems working with a 16-bit image. If I want to save as PNG, I cannot do this directly:

 i32.save('foo.png') # IOError: cannot write mode F as PNG i16.save('foo.png') # ValueError: unrecognized mode 

If I convert a 32-bit image, I can save it:

 i32.convert('L').save('foo.png') 

But the same command will not work with a 16-bit image:

 i16.convert('L').save('foo.png') # ValueError: unrecognized mode 
+11
python 16-bit tiff
Aug 30 '11 at 17:35
source share
4 answers

To convert lossless from a 16-bit grayscale TIFF to PNG, use PythonMagick :

 from PythonMagick import Image Image('pinei_2002300_1525_modis_ch02.tif').write("foo.png") 
+6
Aug 30 '11 at 8:01 a.m.
source share

I came across this thread trying to save 16-bit TIFF images with PIL / numpy.

Versions: python 2.7.1 - numpy 1.6.1 - PIL 1.1.7

Here is a quick test I wrote. uint16 numpy array → converted to string → converted to a PIL image of type 'I; 16 '→ saved as 16-bit TIFF.

Opening an image in ImageJ shows the right horizontal gradient chart, and the image type is "Bits per pixel: 16 (unsigned)"

 import Image import numpy data = numpy.zeros((1024,1024),numpy.uint16) h,w = data.shape for i in range(h): data[i,:] = numpy.arange(w) im = Image.fromstring('I;16',(w,h),data.tostring()) im.save('test_16bit.tif') 

edit: Starting with version 1.1.7, PIL does not support writing compressed files, but pylibtiff does (lzw compression). Thus, the test code becomes (tested with pylibtiff 0.3):

 import Image import numpy from libtiff import TIFFimage data = numpy.zeros((1024,1024),numpy.uint16) h,w = data.shape for i in range(w): data[:,i] = numpy.arange(h) tiff = TIFFimage(data, description='') tiff.write_file('test_16bit.tif', compression='lzw') #flush the file to disk: del tiff 

Please note: the test code has changed to create a vertical gradient, otherwise compression is not achieved (see warning: pylibtiff currently supports reading and writing images that are stored using TIFF bands).

+8
Jan 27 '12 at 10:09
source share

It looks like you came across a PIL error or an invalid corner case.

Here's a workaround:

 i16.mode = 'I' i16.point(lambda i:i*(1./256)).convert('L').save('foo.png') 
+5
Aug 30 '11 at 19:09
source share

Convert ImageJ TIFF to JPEG with PIL 4.1+

 im = numpy.array(Image.open('my.tiff')) image = Image.fromarray(im / numpy.amax(im) * 255) image.save('my.jpg') 
0
Apr 18 '17 at 20:25
source share



All Articles