Skip to content

Instantly share code, notes, and snippets.

@yig
Last active August 21, 2016 04:48
Show Gist options
  • Select an option

  • Save yig/57d2ac984ef90aa8ef182b39a9c11fd2 to your computer and use it in GitHub Desktop.

Select an option

Save yig/57d2ac984ef90aa8ef182b39a9c11fd2 to your computer and use it in GitHub Desktop.
A test to determine which high bit-depth image formats are supported by Pillow / PIL / Python Imaging Library.
'''
Author: Yotam Gingold <yotam (strudel) yotamgingold.com>
License: Public Domain [CC0](http://creativecommons.org/publicdomain/zero/1.0/)
'''
from __future__ import print_function, division
from numpy import *
from PIL import Image
def generate_gradient( rows, cols ):
result = zeros( ( rows, cols, 3 ) )
## Red increases along the rows
result[:,:,0] = linspace( 0, 1, rows )[:,newaxis]
## Green increases along the columns
result[:,:,1] = linspace( 0, 1, cols )[newaxis,:]
## Blue decreases along both
result[:,:,2] = dot( 1. - linspace( 0, 1, rows )[:,newaxis], 1. - linspace( 0, 1, cols )[newaxis,:] )
return result
def test_format( data, name, scale_dtype = None ):
num_channels = 1 if len( data.shape ) == 2 else data.shape[2]
print( 'test_format( %s channel image as "%s" ):' % ( num_channels, name ), end = ' ' )
savedata = data
if scale_dtype is not None:
savedata = ( data * iinfo(scale_dtype).max ).astype( scale_dtype )
try:
Image.fromarray( savedata ).save( name )
except:
# print( e )
print( "Failed." )
return
try:
loaded = asarray( Image.open( name ) )
except:
# print( e )
print( "Failed." )
return
print( "Success!" )
print( " ", 'total absolute difference from what was saved:', abs( loaded - savedata ).sum() )
if scale_dtype is None:
print( " ", 'total absolute difference from original:', abs( loaded - data ).sum() )
else:
print( " ", 'total absolute difference from original:', abs( asfarray(loaded)/iinfo(scale_dtype).max - data ).sum() )
if __name__ == '__main__':
## Start with 32-bit floating point data.
z = generate_gradient( 128, 256 ).astype( float32 )
# print( 'data.shape:', z.shape )
# print( 'data.dtype:', z.dtype )
## Try 3-channel images in these formats.
## NOTE: On my machine, only uint8 PNG succeeds.
test_format( z, 'float32.tif' )
test_format( z, 'float32.png' )
test_format( z, 'int32.tif', int32 )
test_format( z, 'uint32.tif', uint32 )
test_format( z, 'int32.png', int32 )
test_format( z, 'uint32.png', uint32 )
test_format( z, 'int16.png', int16 )
test_format( z, 'uint16.png', uint16 )
test_format( z, 'int8.png', int8 )
test_format( z, 'uint8.png', uint8 )
## PIL supports more kinds of single-channel images.
## NOTE: On my machine, only float32 TIFF, int32 TIFF, and uint8 PNG succeeds.
# Don't average, since that looks uniformly grey.
# z = average( z, axis = 2 )
z = z[:,:,2]
test_format( z, 'float32_grey.tif' )
test_format( z, 'float32_grey.png' )
test_format( z, 'int32_grey.tif', int32 )
test_format( z, 'uint32_grey.tif', uint32 )
test_format( z, 'int32_grey.png', int32 )
test_format( z, 'uint32_grey.png', uint32 )
test_format( z, 'int16_grey.png', int16 )
test_format( z, 'uint16_grey.png', uint16 )
test_format( z, 'int8_grey.png', int8 )
test_format( z, 'uint8_grey.png', uint8 )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment