From 5f769cb4bf5c7644132921ebb01be9b7e84040df Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 24 Sep 2014 16:34:50 -0500 Subject: [PATCH] Fix handling of non-uint8 images for PIL imsave. Fix handling of non-uint8 imags for PIL imsave. Update build requirements and documentation Reorganized dependencies in DEPENDS.txt. Fix install_requires string formatting Use img_as_ubyte instead of the previous hack Add to the docstring notes. Add to docstring notes Fix errant changes Add support for tif floating point and 16bit files Handle case where format_str is None Add note about 2D TIFF file support Add handling for uint16 and integer types. --- skimage/io/_plugins/pil_plugin.py | 49 +++++++++++++++++++------------ 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/skimage/io/_plugins/pil_plugin.py b/skimage/io/_plugins/pil_plugin.py index f45084ce..413647e1 100644 --- a/skimage/io/_plugins/pil_plugin.py +++ b/skimage/io/_plugins/pil_plugin.py @@ -11,7 +11,7 @@ except ImportError: "http://pypi.python.org/pypi/PIL/) " "for further instructions.") -from skimage.util import img_as_ubyte +from skimage.util import img_as_ubyte, img_as_uint, img_as_int, img_as_float from six import string_types @@ -109,29 +109,37 @@ def ndarray_to_pil(arr, format_str=None): if arr.shape[2] not in (3, 4): raise ValueError("Invalid number of channels in image array.") - # Image is floating point, assume in [0, 1] - if np.issubdtype(arr.dtype, float): - arr = arr * 255 + if not format_str is None and format_str in ('tiff', 'tif'): + # open with pylibtiff + pass - arr = arr.astype(np.uint8) + if arr.ndim == 3: + arr = img_as_ubyte(arr) + mode_base = mode = {3: 'RGB', 4: 'RGBA'}[arr.shape[2]] - if arr.ndim == 2: - mode = 'L' + elif arr.dtype.kind == 'f': + arr = img_as_uint(arr) + mode = 'I;16' + mode_base = 'I' - elif arr.shape[2] in (3, 4): - mode = {3: 'RGB', 4: 'RGBA'}[arr.shape[2]] - - # Force all integers to bytes + elif arr.max() < 256 and arr.min() >= 0: arr = arr.astype(np.uint8) + mode = 'L' + mode_base = 'L' - try: - img = Image.frombytes(mode, (arr.shape[1], arr.shape[0]), - arr.tostring()) - except AttributeError: - img = Image.fromstring(mode, (arr.shape[1], arr.shape[0]), - arr.tostring()) + elif arr.max() < 2**16 and arr.min() >= 0: + arr = arr.astype(np.uint16) + mode = 'I;16' + mode_base = 'I' - return img + else: + arr = img_as_int(arr) + mode = 'I' + mode_base = 'I' + + im = Image.new(mode_base, arr.T.shape) + im.fromstring(arr.tostring(), 'raw', mode) + return im def imsave(fname, arr, format_str=None): @@ -151,7 +159,10 @@ def imsave(fname, arr, format_str=None): Notes ----- - Currently, only 8-bit precision is supported. + Currently, only 8-bit precision is supported for PNG and JPEG. + Images that are not uint8 type will be converted using + `skimage.img_as_ubyte`. + 2D TIFF Files also support unit16 and float32 type images. """ # default to PNG if file-like object