How do I display a PIL Image object in a template?

14,954

Solution 1

For a limited set of browsers, you can base64 encode the image and use inline images. See Embedding Base64 Images.

A solution that works for all browsers is an image tag referencing a view that returns the image.

[update]

All I want is for the user to submit the original image, and then be prompted by another form to input a caption for the image (with the resized image to the left of the caption field). Then when the user hits "submit" the image and the caption get saved in a model instance.

Well... When you use <img src="foo">, foo is always retrieved by a GET perhaps that is why it is not working - request.FILES will not be available in a GET request. If you open firebug or the chrome debug toolbar, in the network tab, you will see the POST request with the uploaded image and after that a GET request to fetch the image.

You have to save the image somewhere between both steps.

how else could i save it? I would love for it to be temporary. Do you think there's a really easy way to do this, or should I go look into those options?

Popular choices are redis and memcached. You can think of them as giant shared python dict with an expire date. If the images are small, like an avatar, you can also save the image data in a session variable.

Solution 2

Yes and no.

Yes, you can put the images as raw Base64 data. Here's a little script you can use to test this:

import Image
import base64
import StringIO
output = StringIO.StringIO()
im = Image.open("test.png") # Your image here!
im.save(output, format='PNG')
output.seek(0)
output_s = output.read()
b64 = base64.b64encode(output_s)
open("test.html","w+").write('<img src="data:image/png;base64,{0}"/>'.format(b64))

However, this is a really bad idea. With multiple thumbnails, your single HTML page might be 10MB+.

What you really should be doing is using a separate Django view to return images from PIL objects as PNG files, and then referencing that view in the img href attributes on your page.

Solution 3

You can embed base64 encoded images into an tag. So you could convert PIL image to base64 and then display it.

from PIL import Image
import StringIO

x = Image.new('RGB',(400,400))
output = StringIO.StringIO()
x.save(output, "PNG")
contents = output.getvalue().encode("base64")
output.close()
contents = contents.split('\n')[0]

Then show with:

 <img src="data:image/png;base64,' + contents + ' />

Look to an example output.

Share:
14,954
sgarza62
Author by

sgarza62

Updated on July 04, 2022

Comments

  • sgarza62
    sgarza62 almost 2 years

    If a user uploads an image, and I resize it using PIL, I get a PIL Image object.

    How do I display a PIL Image file in a template, before it has been saved to the database? Can it even be passed in as an image and rendered?

  • sgarza62
    sgarza62 over 11 years
    How would I reference a view from an image tag?
  • Paulo Scardine
    Paulo Scardine over 11 years
    <img src="/url/to/my/image-returning/view/perhaps/with/1/or/2/par‌​ameters/" alt="the same url from urls.py, got it?">
  • sgarza62
    sgarza62 over 11 years
    Thank you for you help so far, I apologize for the delay...I've been trying to get this to work with my code. I was able to save the Image to the HttpResponse object (thanks!), but I'm having trouble getting it to work from the image tag in the template. Maybe I'm not passing a certain parameter in the url, I'm not sure.
  • Yerke
    Yerke about 8 years
    This worked for me after I removed this line: contents = contents.split('\n')[0]