问题
I would like to feed images from a remote machine into pyglet (though I am open to other platforms where I can present images and record user's mouse clicks and keystrokes). Currently I am trying to do it using flask
on the remote server and pulling it down with requests
import requests
from PIL import Image
import io
import pyglet
import numpy as np
r = requests.get('http://{}:5000/test/cat2.jpeg'.format(myip),)
This does not work:
im = pyglet.image.load(io.StringIO(r.text))
# Error:
File "/usr/local/lib/python3.4/dist-packages/pyglet/image/__init__.py", line 178, in load
file = open(filename, 'rb')
TypeError: invalid file: <_io.StringIO object at 0x7f6eb572bd38>
This also does not work:
im = Image.open(io.BytesIO(r.text.encode()))
# Error:
Traceback (most recent call last):
File "<ipython-input-68-409ca9b8f6f6>", line 1, in <module>
im = Image.open(io.BytesIO(r.text.encode()))
File "/usr/local/lib/python3.4/dist-packages/PIL/Image.py", line 2274, in open
% (filename if filename else fp))
OSError: cannot identify image file <_io.BytesIO object at 0x7f6eb5a8b6a8>
Is there another way to do it without saving files on disk?
回答1:
The first example isn't working properly because I'm having encoding issues. But this will get you on the way of using manual ImageData
objects to manipulate images:
import pyglet, urllib.request
# == The Web part:
img_url = 'http://hvornum.se/linux.jpg'
web_response = urllib.request.urlopen(img_url)
img_data = web_response.read()
# == Loading the image part:
window = pyglet.window.Window(fullscreen=False, width=700, height=921)
image = pyglet.sprite.Sprite(pyglet.image.ImageData(700, 921, 'RGB', img_data))
# == Stuff to render the image:
@window.event
def on_draw():
window.clear()
image.draw()
window.flip()
@window.event
def on_close():
print("I'm closing now")
pyglet.app.run()
Now to the more convenient, less manual way of doing things would be to use the io.BytesIO
dummy file-handle and toss that into pyglet.image.load()
with the parameter file=dummyFile
like so:
import pyglet, urllib.request
from io import BytesIO
# == The Web part:
img_url = 'http://hvornum.se/linux.jpg'
web_response = urllib.request.urlopen(img_url)
img_data = web_response.read()
dummy_file = BytesIO(img_data)
# == Loading the image part:
window = pyglet.window.Window(fullscreen=False, width=700, height=921)
image = pyglet.sprite.Sprite(pyglet.image.load('noname.jpg', file=dummy_file))
# == Stuff to render the image:
@window.event
def on_draw():
window.clear()
image.draw()
window.flip()
@window.event
def on_close():
print("I'm closing now")
pyglet.app.run()
Works on my end and is rather quick as well.
One last note, try putting images into pyglet.sprite.Sprite
objects, they tend to be quicker, easier to work with and gives you a whole bunch of nifty functions to work with (such as easy positioning, spr.scale
and rotate functions)
回答2:
You can show a remote image by PIL as follows:
import requests
from PIL import Image
from StringIO import StringIO
r = requests.get('http://{}:5000/test/cat2.jpeg', stream=True)
sio = StringIO(r.raw.read())
im = Image.open(sio)
im.show()
Note that the stream=True
option is necessary to create a StringIO
object from the data. Also, not using io.StringIO
but StringIO.StringIO
.
来源:https://stackoverflow.com/questions/44636251/loading-image-from-a-remote-server-in-pyglet-or-pil-python