From 9a9813f68425fdcbc3c481b425c4d1aa4124e3ec Mon Sep 17 00:00:00 2001 From: cgohlke Date: Fri, 9 Dec 2011 13:37:45 -0800 Subject: [PATCH 1/8] Don't flip PIL image --- lib/matplotlib/image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index 9b7076795e72..85e6919d55e7 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -1261,7 +1261,7 @@ def pil_to_array( pilImage ): """ def toarray(im): 'return a 1D array of floats' - x_str = im.tostring('raw',im.mode,0,-1) + x_str = im.tostring('raw', im.mode) x = np.fromstring(x_str,np.uint8) return x From b1a0a1a192ed02701a512c5588617a4e826426e8 Mon Sep 17 00:00:00 2001 From: cgohlke Date: Fri, 9 Dec 2011 14:00:21 -0800 Subject: [PATCH 2/8] Fix conversion of PIL 16 bit grayscale images to 8 bit --- lib/matplotlib/image.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index 85e6919d55e7..270648e410dd 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -5,6 +5,7 @@ """ from __future__ import division import os, warnings +import math import numpy as np from numpy import ma @@ -1259,10 +1260,10 @@ def pil_to_array( pilImage ): grayscale images, the return array is MxN. For RGB images, the return value is MxNx3. For RGBA images the return value is MxNx4 """ - def toarray(im): - 'return a 1D array of floats' + def toarray(im, dtype=np.uint8): + 'return a 1D array of dtype' x_str = im.tostring('raw', im.mode) - x = np.fromstring(x_str,np.uint8) + x = np.fromstring(x_str, dtype) return x if pilImage.mode in ('RGBA', 'RGBX'): @@ -1279,7 +1280,21 @@ def toarray(im): x = toarray(im) x.shape = im.size[1], im.size[0], 3 return x - + elif pilImage.mode.startswith('I;16'): + # return MxN luminance array + # Normalize with the highest bit depth detected in image + # to minimize loss of dynamic range. + im = pilImage + if im.mode.endswith('B'): + x = toarray(im, '>u2') + else: + x = toarray(im, ' 255: + x >>= int(math.ceil(math.log(xmax, 2))) - 8 + x = x.astype(np.uint8) + x.shape = im.size[1], im.size[0] + return x else: # try to convert to an rgba image try: im = pilImage.convert('RGBA') From 98d706b7eefa3fe5281ff3c61eb000451c571b50 Mon Sep 17 00:00:00 2001 From: cgohlke Date: Fri, 9 Dec 2011 14:11:14 -0800 Subject: [PATCH 3/8] Add detection of file extension for file-like objects --- lib/matplotlib/image.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index 270648e410dd..4c9b8da9da5f 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -1190,6 +1190,9 @@ def pilread(): if cbook.is_string_like(fname): basename, ext = os.path.splitext(fname) ext = ext.lower()[1:] + elif hasattr(fname, 'name'): + basename, ext = os.path.splitext(fname.name) + ext = ext.lower()[1:] else: ext = 'png' else: From 8408cb3163d0cf5a59c4a1ce8f2f0376a7de73bd Mon Sep 17 00:00:00 2001 From: cgohlke Date: Fri, 9 Dec 2011 20:39:22 -0800 Subject: [PATCH 4/8] Allow pil_to_array to return arrays with dtypes other than uint8 --- lib/matplotlib/image.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index 4c9b8da9da5f..4038b71e7e82 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -1259,7 +1259,7 @@ def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None, def pil_to_array( pilImage ): """ - load a PIL image and return it as a numpy array of uint8. For + load a PIL image and return it as a numpy array. For grayscale images, the return array is MxN. For RGB images, the return value is MxNx3. For RGBA images the return value is MxNx4 """ @@ -1284,18 +1284,12 @@ def toarray(im, dtype=np.uint8): x.shape = im.size[1], im.size[0], 3 return x elif pilImage.mode.startswith('I;16'): - # return MxN luminance array - # Normalize with the highest bit depth detected in image - # to minimize loss of dynamic range. + # return MxN luminance array of uint16 im = pilImage if im.mode.endswith('B'): x = toarray(im, '>u2') else: x = toarray(im, ' 255: - x >>= int(math.ceil(math.log(xmax, 2))) - 8 - x = x.astype(np.uint8) x.shape = im.size[1], im.size[0] return x else: # try to convert to an rgba image From e87bc08f79fed28b70151d1d47d476590dbdcf7b Mon Sep 17 00:00:00 2001 From: cgohlke Date: Fri, 9 Dec 2011 20:42:18 -0800 Subject: [PATCH 5/8] No more need to flip PIL images in imshow --- examples/pylab_examples/image_demo3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/pylab_examples/image_demo3.py b/examples/pylab_examples/image_demo3.py index ba1c7011ae8f..fd27a20380cc 100644 --- a/examples/pylab_examples/image_demo3.py +++ b/examples/pylab_examples/image_demo3.py @@ -15,7 +15,7 @@ figure(figsize=figsize) ax = axes([0,0,1,1], frameon=False) ax.set_axis_off() -im = imshow(lena, origin='lower') +im = imshow(lena) show() From 463a3b59b9acc4706514de147fd176f59bcf7a31 Mon Sep 17 00:00:00 2001 From: cgohlke Date: Fri, 9 Dec 2011 21:28:54 -0800 Subject: [PATCH 6/8] Return native byte order uint16 --- lib/matplotlib/image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index 4038b71e7e82..d2d61549709a 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -1291,7 +1291,7 @@ def toarray(im, dtype=np.uint8): else: x = toarray(im, ' Date: Fri, 9 Dec 2011 21:40:10 -0800 Subject: [PATCH 7/8] Test reading uint16 grayscale image with PIL --- lib/matplotlib/tests/test_image.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/matplotlib/tests/test_image.py b/lib/matplotlib/tests/test_image.py index 2c9db8a23e17..88e09be3c70d 100644 --- a/lib/matplotlib/tests/test_image.py +++ b/lib/matplotlib/tests/test_image.py @@ -75,6 +75,11 @@ def test_image_python_io(): buffer.seek(0) plt.imread(buffer) +def test_imread_pil_uint16(): + img = plt.imread(os.path.join(os.path.dirname(__file__), + 'baseline_images/test_image/uint16.tif')) + assert (img.dtype == np.uint16) + # def test_image_unicode_io(): # fig = plt.figure() # ax = fig.add_subplot(111) From 64d3264ab9f8192012ba2a5c26b5d176c9da685f Mon Sep 17 00:00:00 2001 From: Christoph Gohlke Date: Sun, 11 Dec 2011 19:45:17 -0800 Subject: [PATCH 8/8] Add uint16 image --- .../tests/baseline_images/test_image/uint16.tif | Bin 0 -> 8302 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 lib/matplotlib/tests/baseline_images/test_image/uint16.tif diff --git a/lib/matplotlib/tests/baseline_images/test_image/uint16.tif b/lib/matplotlib/tests/baseline_images/test_image/uint16.tif new file mode 100644 index 0000000000000000000000000000000000000000..78b8ea4cca16b35d4a060a82d8f10ec8974019f2 GIT binary patch literal 8302 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 EAE~H(S^xk5 literal 0 HcmV?d00001