Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for HTTP response objects as file-like pointers for Image.open() #1148

Closed
mfitzp opened this issue Mar 26, 2015 · 2 comments
Closed
Milestone

Comments

@mfitzp
Copy link
Contributor

mfitzp commented Mar 26, 2015

Opening this in response to this report on matplotlib. Attempting to open remote image files (passing the urlopen object) fails as the object does not support .seek.

There is example code on this StackOverflow post for how to wrap the opened object into a file-like object supporting .seek using io.BytesIO (replacement for StringIO).

from PIL import Image
import urllib2 as urllib
import io

fd = urllib.urlopen("http://a/b/c")
image_file = io.BytesIO(fd.read())
im = Image.open(image_file)

The relevant bit of PIL code can be inserted as follows in Image.imread (line 2242) immediately before the prefix load:

if isPath(fp):
    filename = fp
    fp = builtins.open(fp, "rb")
else:
    filename = ""

try:
    fp.seek(0)
except (AttributeError, io.UnsupportedOperation):
    fp = io.BytesIO(fp.read())

prefix = fp.read(16)

The general approach that works is checking for AttributeError during .seek(0) and on failure attempting to wrap the object into a io.Bytes object. This will fail if it is not a buffer and we can exit as normal. Using this we can then request files via urls, using both urllib or requests as follows:

Image.open(urllib2.urlopen(url))
Image.open(requests.get(url, stream=True).raw)

It would be nice if requests.get(url).content worked, but that is a raw bytes object with no .read() so would require an alternative handling.

Is this something that would be considered for inclusion in the PIL library? I am happy to put together a PR if it looks reasonable. This depends on the io module as is which adds a 2.6 requirement, but the earlier StringIO is equivalent (there is a wrapper available in six.BytesIO).

@mfitzp mfitzp changed the title Support for Support for HTTP request objects as file-like pointers for Image.open() Mar 26, 2015
@aclark4life
Copy link
Member

I don't see why not. If you send the PR soon it could go in 2.8.0

@mfitzp
Copy link
Contributor Author

mfitzp commented Mar 26, 2015

Great! I've submitted a PR for consideration. This uses io.BytesIO as that is supported from Python 2.6+ according to the docs.

@mfitzp mfitzp changed the title Support for HTTP request objects as file-like pointers for Image.open() Support for HTTP response objects as file-like pointers for Image.open() Mar 26, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants