Dima Lituiev
Dima Lituiev

Reputation: 13136

Loading image from a remote server in pyglet or PIL / python

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?

Upvotes: 1

Views: 1913

Answers (2)

Jay
Jay

Reputation: 61

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.

Upvotes: 0

Torxed
Torxed

Reputation: 23500

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)

Upvotes: 1

Related Questions