How to send image generated by PIL to browser?

PythonStreamingPython Imaging-LibraryFlaskTemporary Files

Python Problem Overview


I'm using flask for my application. I'd like to send an image (dynamically generated by PIL) to client without saving on disk.

Any idea how to do this ?

Python Solutions


Solution 1 - Python

Here's a version without any temp files and the like (see here):

def serve_pil_image(pil_img):
    img_io = StringIO()
    pil_img.save(img_io, 'JPEG', quality=70)
    img_io.seek(0)
    return send_file(img_io, mimetype='image/jpeg')

To use in your code simply do

@app.route('some/route/')
def serve_img():
    img = Image.new('RGB', ...)
    return serve_pil_image(img)

Solution 2 - Python

Mr. Mr. did an excellent job indeed. I had to use BytesIO() instead of StringIO().

def serve_pil_image(pil_img):
    img_io = BytesIO()
    pil_img.save(img_io, 'JPEG', quality=70)
    img_io.seek(0)
    return send_file(img_io, mimetype='image/jpeg')

Solution 3 - Python

First, you can save the image to a tempfile and remove the local file (if you have one):

from tempfile import NamedTemporaryFile
from shutil import copyfileobj
from os import remove

tempFileObj = NamedTemporaryFile(mode='w+b',suffix='jpg')
pilImage = open('/tmp/myfile.jpg','rb')
copyfileobj(pilImage,tempFileObj)
pilImage.close()
remove('/tmp/myfile.jpg')
tempFileObj.seek(0,0)

Second, set the temp file to the response (as per this stackoverflow question):

from flask import send_file

@app.route('/path')
def view_method():
    response = send_file(tempFileObj, as_attachment=True, attachment_filename='myfile.jpg')
    return response

Solution 4 - Python

It turns out that flask provides a solution (rtm to myself!):

from flask import abort, send_file
try:
    return send_file(image_file)
except:
    abort(404)

Solution 5 - Python

I was also struggling in the same situation. Finally, I have found its solution using a WSGI application, which is an acceptable object for "make_response" as its argument.

from Flask import make_response

@app.route('/some/url/to/photo')
def local_photo():
    print('executing local_photo...')
    with open('test.jpg', 'rb') as image_file:
        def wsgi_app(environ, start_response):
            start_response('200 OK', [('Content-type', 'image/jpeg')])
            return image_file.read()
        return make_response(wsgi_app)

Please replace "opening image" operations with appropriate PIL operations.

Solution 6 - Python

        return send_file(fileName, mimetype='image/png')

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser795243View Question on Stackoverflow
Solution 1 - PythonMr. Mr.View Answer on Stackoverflow
Solution 2 - PythonDan ErezView Answer on Stackoverflow
Solution 3 - PythonAdam MorrisView Answer on Stackoverflow
Solution 4 - PythoncybertoastView Answer on Stackoverflow
Solution 5 - PythoncocoatomoView Answer on Stackoverflow
Solution 6 - PythonGankView Answer on Stackoverflow