diff --git a/skimage/_shared/testing.py b/skimage/_shared/testing.py index 301d25ec..603cfaaa 100644 --- a/skimage/_shared/testing.py +++ b/skimage/_shared/testing.py @@ -93,8 +93,8 @@ def roundtrip(img, plugin, suffix): if not '.' in suffix: suffix = '.' + suffix temp_file = NamedTemporaryFile(suffix=suffix, delete=False) - temp_file.close() fname = temp_file.name + temp_file.close() io.imsave(fname, img, plugin=plugin) new = io.imread(fname, plugin=plugin) try: @@ -119,7 +119,7 @@ def color_check(plugin, fmt='png'): testing.assert_allclose(img2.astype(np.uint8), r2) img3 = img_as_float(img) - with expected_warnings(['precision loss|unclosed file']): + with expected_warnings(['precision loss']): r3 = roundtrip(img3, plugin, fmt) testing.assert_allclose(r3, img) @@ -131,12 +131,12 @@ def color_check(plugin, fmt='png'): r4 = roundtrip(img4, plugin, fmt) testing.assert_allclose(r4, img4) else: - with expected_warnings(['sign loss|precision loss|unclosed file']): + with expected_warnings(['sign loss|precision loss']): r4 = roundtrip(img4, plugin, fmt) testing.assert_allclose(r4, img_as_ubyte(img4)) img5 = img_as_uint(img) - with expected_warnings(['precision loss|unclosed file']): + with expected_warnings(['precision loss']): r5 = roundtrip(img5, plugin, fmt) testing.assert_allclose(r5, img) @@ -156,14 +156,14 @@ def mono_check(plugin, fmt='png'): testing.assert_allclose(img2.astype(np.uint8), r2) img3 = img_as_float(img) - with expected_warnings(['precision|unclosed file|\A\Z']): + with expected_warnings(['precision|\A\Z']): r3 = roundtrip(img3, plugin, fmt) if r3.dtype.kind == 'f': testing.assert_allclose(img3, r3) else: testing.assert_allclose(r3, img_as_uint(img)) - with expected_warnings(['precision loss|unclosed file']): + with expected_warnings(['precision loss']): img4 = img_as_int(img) if fmt.lower() in (('tif', 'tiff')): img4 -= 100 @@ -171,7 +171,7 @@ def mono_check(plugin, fmt='png'): r4 = roundtrip(img4, plugin, fmt) testing.assert_allclose(r4, img4) else: - with expected_warnings(['precision loss|sign loss|unclosed file']): + with expected_warnings(['precision loss|sign loss']): r4 = roundtrip(img4, plugin, fmt) testing.assert_allclose(r4, img_as_uint(img4)) diff --git a/skimage/io/_plugins/pil_plugin.py b/skimage/io/_plugins/pil_plugin.py index f7c10789..4e830438 100644 --- a/skimage/io/_plugins/pil_plugin.py +++ b/skimage/io/_plugins/pil_plugin.py @@ -5,7 +5,7 @@ from six import string_types from PIL import Image from ...util import img_as_ubyte, img_as_uint -from ...external.tifffile import imread as tif_imread, imsave as tif_imsave +from .tifffile_plugin import imread as tif_imread, imsave as tif_imsave def imread(fname, dtype=None, img_num=None, **kwargs): @@ -13,8 +13,8 @@ def imread(fname, dtype=None, img_num=None, **kwargs): Parameters ---------- - fname : str - File name. + fname : str or file + File name or file-like-object. dtype : numpy dtype object or string specifier Specifies data type of array elements. img_num : int, optional @@ -43,18 +43,12 @@ def imread(fname, dtype=None, img_num=None, **kwargs): if fname.lower().endswith(('.tiff', '.tif')): return tif_imread(fname, **kwargs) - im = Image.open(fname) - try: - # this will raise an IOError if the file is not readable - im.getdata()[0] - except IOError as e: - site = "http://pillow.readthedocs.org/en/latest/installation.html#external-libraries" - pillow_error_message = str(e) - error_message = ('Could not load "%s" \n' - 'Reason: "%s"\n' - 'Please see documentation at: %s') % (fname, pillow_error_message, site) - raise ValueError(error_message) + if isinstance(fname, string_types): + with open(fname, 'rb') as f: + im = Image.open(f) + return pil_to_ndarray(im, dtype=dtype, img_num=img_num) else: + im = Image.open(fname) return pil_to_ndarray(im, dtype=dtype, img_num=img_num) @@ -66,6 +60,17 @@ def pil_to_ndarray(im, dtype=None, img_num=None): Refer to ``imread``. """ + try: + # this will raise an IOError if the file is not readable + im.getdata()[0] + except IOError as e: + site = "http://pillow.readthedocs.org/en/latest/installation.html#external-libraries" + pillow_error_message = str(e) + error_message = ('Could not load "%s" \n' + 'Reason: "%s"\n' + 'Please see documentation at: %s' + % (im.filename, pillow_error_message, site)) + raise ValueError(error_message) frames = [] grayscale = None i = 0 diff --git a/skimage/io/_plugins/tifffile_plugin.py b/skimage/io/_plugins/tifffile_plugin.py index a3a766f1..3ae90449 100644 --- a/skimage/io/_plugins/tifffile_plugin.py +++ b/skimage/io/_plugins/tifffile_plugin.py @@ -1 +1,28 @@ -from ...external.tifffile import imread, imsave +from ...external.tifffile import TiffFile, imsave + + +def imread(fname, dtype=None, **kwargs): + """Load a tiff image from file. + + Parameters + ---------- + fname : str or file + File name or file-like-object. + dtype : numpy dtype object or string specifier + Specifies data type of array elements (Not currently used). + kwargs : keyword pairs, optional + Addition keyword arguments to pass through (see `tifffile`'s `imread` function). + + Notes + ----- + Provided by Christophe Golhke's tifffile.py [1]_, and supports many + advanced image types including multi-page and floating point. + + References + ---------- + .. [1] http://www.lfd.uci.edu/~gohlke/code/tifffile.py + + """ + with open(fname, 'rb') as f: + tif = TiffFile(f) + return tif.asarray(**kwargs) diff --git a/skimage/io/collection.py b/skimage/io/collection.py index bf8c58da..cf57f5f7 100644 --- a/skimage/io/collection.py +++ b/skimage/io/collection.py @@ -199,8 +199,9 @@ class ImageCollection(object): index = [] for fname in self._files: if fname.lower().endswith(('.tiff', '.tif')): - img = TiffFile(fname) - index += [(fname, i) for i in range(len(img.pages))] + with open(fname, 'rb') as f: + img = TiffFile(f) + index += [(fname, i) for i in range(len(img.pages))] else: try: im = Image.open(fname) diff --git a/skimage/io/tests/test_pil.py b/skimage/io/tests/test_pil.py index cc00e19e..935dc6a7 100644 --- a/skimage/io/tests/test_pil.py +++ b/skimage/io/tests/test_pil.py @@ -160,7 +160,7 @@ def test_imsave_filelike(): s = BytesIO() # save to file-like object - with expected_warnings(['precision loss|unclosed file', + with expected_warnings(['precision loss', 'is a low contrast image']): imsave(s, image) @@ -230,9 +230,9 @@ class TestSaveTIF: def roundtrip(self, dtype, x, compress): with temporary_file(suffix='.tif') as fname: if dtype == np.bool: - expected = ['low contrast|unclosed file'] + expected = ['low contrast'] else: - expected = ['unclosed file|\A\Z'] + expected = ['\A\Z'] with expected_warnings(expected): if compress > 0: imsave(fname, x, compress=compress)