From cd8c3da8ec1b80ac327eba41fdb6cf2fa52cc3d9 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Thu, 18 Oct 2012 21:51:21 -0400 Subject: [PATCH 1/6] ENH: Allow imread to read URLs --- skimage/io/_io.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/skimage/io/_io.py b/skimage/io/_io.py index eea7e509..e400f6b3 100644 --- a/skimage/io/_io.py +++ b/skimage/io/_io.py @@ -1,6 +1,9 @@ __all__ = ['Image', 'imread', 'imread_collection', 'imsave', 'imshow', 'show', 'push', 'pop'] +import re +import urllib2 +import tempfile from io import BytesIO import numpy as np @@ -12,6 +15,14 @@ from skimage.color import rgb2grey # Shared image queue _image_stack = [] +URL_REGEX = re.compile(r'http://|https://|ftp://') + + +def is_url(filename): + """Return True if string is an http or ftp path.""" + return (isinstance(filename, basestring) and + URL_REGEX.match(filename) is not None) + class Image(np.ndarray): """Class representing Image data. @@ -88,7 +99,7 @@ def imread(fname, as_grey=False, plugin=None, flatten=None, Parameters ---------- fname : string - Image file name, e.g. ``test.jpg``. + Image file name, e.g. ``test.jpg`` or URL. as_grey : bool If True, convert color images to grey-scale (32-bit floats). Images that are already in grey-scale format are not converted. @@ -117,7 +128,15 @@ def imread(fname, as_grey=False, plugin=None, flatten=None, if flatten is not None: as_grey = flatten - img = call_plugin('imread', fname, plugin=plugin, **plugin_args) + if is_url(fname): + with tempfile.NamedTemporaryFile() as f: + u = urllib2.urlopen(fname) + f.write(u.read()) + f.seek(0) + # Note: the temporary file must be used inside the with-block. + img = call_plugin('imread', f.name, plugin=plugin, **plugin_args) + else: + img = call_plugin('imread', fname, plugin=plugin, **plugin_args) if as_grey and getattr(img, 'ndim', 0) >= 3: img = rgb2grey(img) From e5130180526d6eb79b5af56ef859c7ea6fa7f567 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Thu, 18 Oct 2012 22:07:18 -0400 Subject: [PATCH 2/6] Fix handling of temporary file. Opening an already-opened file was unsafe. Close the file, then manually delete it. --- skimage/io/_io.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/skimage/io/_io.py b/skimage/io/_io.py index e400f6b3..bf75cf76 100644 --- a/skimage/io/_io.py +++ b/skimage/io/_io.py @@ -1,6 +1,7 @@ __all__ = ['Image', 'imread', 'imread_collection', 'imsave', 'imshow', 'show', 'push', 'pop'] +import os import re import urllib2 import tempfile @@ -129,12 +130,12 @@ def imread(fname, as_grey=False, plugin=None, flatten=None, as_grey = flatten if is_url(fname): - with tempfile.NamedTemporaryFile() as f: + with tempfile.NamedTemporaryFile(delete=False) as f: u = urllib2.urlopen(fname) f.write(u.read()) - f.seek(0) - # Note: the temporary file must be used inside the with-block. + f.close() img = call_plugin('imread', f.name, plugin=plugin, **plugin_args) + os.remove(f.name) else: img = call_plugin('imread', fname, plugin=plugin, **plugin_args) From 9f7a376e4dcf19886c6f7f9cea806ffafc8bf36d Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Fri, 19 Oct 2012 15:21:31 -0400 Subject: [PATCH 3/6] ENH: Add test and support for reading file URLs --- skimage/io/_io.py | 2 +- skimage/io/tests/test_io.py | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/skimage/io/_io.py b/skimage/io/_io.py index bf75cf76..6986cc0f 100644 --- a/skimage/io/_io.py +++ b/skimage/io/_io.py @@ -16,7 +16,7 @@ from skimage.color import rgb2grey # Shared image queue _image_stack = [] -URL_REGEX = re.compile(r'http://|https://|ftp://') +URL_REGEX = re.compile(r'http://|https://|ftp://|file://') def is_url(filename): diff --git a/skimage/io/tests/test_io.py b/skimage/io/tests/test_io.py index 72f8496a..b29994c5 100644 --- a/skimage/io/tests/test_io.py +++ b/skimage/io/tests/test_io.py @@ -2,6 +2,7 @@ from numpy.testing import * import numpy as np import skimage.io as io +from skimage import data_dir def test_stack_basic(): @@ -15,5 +16,12 @@ def test_stack_basic(): def test_stack_non_array(): io.push([[1, 2, 3]]) + +def test_imread_url(): + image_url = 'file://%s/camera.png' % data_dir + image = io.imread(image_url) + assert image.shape == (512, 512) + + if __name__ == "__main__": run_module_suite() From c451aa0d4b0b07559fc0a3ea07e6a45a467cbc3e Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Fri, 19 Oct 2012 17:52:10 -0400 Subject: [PATCH 4/6] STY: Fix confusing use of context-manager. --- skimage/io/_io.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/skimage/io/_io.py b/skimage/io/_io.py index 6986cc0f..2a177076 100644 --- a/skimage/io/_io.py +++ b/skimage/io/_io.py @@ -133,9 +133,8 @@ def imread(fname, as_grey=False, plugin=None, flatten=None, with tempfile.NamedTemporaryFile(delete=False) as f: u = urllib2.urlopen(fname) f.write(u.read()) - f.close() - img = call_plugin('imread', f.name, plugin=plugin, **plugin_args) - os.remove(f.name) + img = call_plugin('imread', f.name, plugin=plugin, **plugin_args) + os.remove(f.name) else: img = call_plugin('imread', fname, plugin=plugin, **plugin_args) From a6d4b6e7fabc835c978d956e7fd38ef8ba1a03df Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Wed, 12 Dec 2012 11:06:15 -0500 Subject: [PATCH 5/6] BUG: Fix file separators for windows --- skimage/io/_io.py | 2 +- skimage/io/tests/test_io.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/skimage/io/_io.py b/skimage/io/_io.py index 2a177076..f8f395bd 100644 --- a/skimage/io/_io.py +++ b/skimage/io/_io.py @@ -16,7 +16,7 @@ from skimage.color import rgb2grey # Shared image queue _image_stack = [] -URL_REGEX = re.compile(r'http://|https://|ftp://|file://') +URL_REGEX = re.compile(r'http://|https://|ftp://|file://|file:\\') def is_url(filename): diff --git a/skimage/io/tests/test_io.py b/skimage/io/tests/test_io.py index b29994c5..aa48ac1a 100644 --- a/skimage/io/tests/test_io.py +++ b/skimage/io/tests/test_io.py @@ -1,3 +1,5 @@ +import os + from numpy.testing import * import numpy as np @@ -18,7 +20,7 @@ def test_stack_non_array(): def test_imread_url(): - image_url = 'file://%s/camera.png' % data_dir + image_url = 'file:{0}{0}{1}{0}camera.png'.format(os.path.sep, data_dir) image = io.imread(image_url) assert image.shape == (512, 512) From abc1d2095f18f6c7ff129f3b8bf9eae2d7a6239a Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Thu, 13 Dec 2012 13:39:32 -0500 Subject: [PATCH 6/6] BUG: Fix file URI in test (2nd attempt) --- skimage/io/tests/test_io.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/skimage/io/tests/test_io.py b/skimage/io/tests/test_io.py index aa48ac1a..484784ee 100644 --- a/skimage/io/tests/test_io.py +++ b/skimage/io/tests/test_io.py @@ -20,7 +20,10 @@ def test_stack_non_array(): def test_imread_url(): - image_url = 'file:{0}{0}{1}{0}camera.png'.format(os.path.sep, data_dir) + # tweak data path so that file URI works on both unix and windows. + data_path = data_dir.lstrip(os.path.sep) + data_path = data_path.replace(os.path.sep, '/') + image_url = 'file:///{0}/camera.png'.format(data_path) image = io.imread(image_url) assert image.shape == (512, 512)