Last active
August 21, 2016 04:48
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ''' | |
| 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