10

I am using matplotlib in a django app and would like to directly return the rendered image. So far I can go plt.savefig(...), then return the location of the image.

What I want to do is:

return HttpResponse(plt.renderfig(...), mimetype="image/png")

Any ideas?

0

4 Answers 4

18

Django's HttpResponse object supports file-like API and you can pass a file-object to savefig.

response = HttpResponse(mimetype="image/png")
# create your image as usual, e.g. pylab.plot(...)
pylab.savefig(response, format="png")
return response

Hence, you can return the image directly in the HttpResponse.

Sign up to request clarification or add additional context in comments.

1 Comment

There are a few other suggestions that look like they would work, but this DEFINITELY looks like the easiest for me to use. I only have to add about 2 or 3 lines of code! Thank-You
6

what about cStringIO?

import pylab
import cStringIO
pylab.plot([3,7,2,1])
output = cStringIO.StringIO()
pylab.savefig('test.png', dpi=75)
pylab.savefig(output, dpi=75)
print output.getvalue() == open('test.png', 'rb').read() # True

2 Comments

Hmm, this would work for other systems, but I don't think django would handle direct printing very well since it uses HttpResponse objects for all of its outbound communication.
@darwinsuvivor, agree with u, I just wanna to show that savefig to a cStringIO.StringIO() object is the same as savefig to PNG file. after that, there is no need to use print here. It looks @wierob's answer is completly suited to our present situation.
2

There is a recipe in the Matplotlib Cookbook that does exactly this. At its core, it looks like:

def simple(request):
    from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
    from matplotlib.figure import Figure

    fig=Figure()
    ax=fig.add_subplot(111)
    ax.plot(range(10), range(10), '-')
    canvas=FigureCanvas(fig)
    response=django.http.HttpResponse(content_type='image/png')
    canvas.print_png(response)
    return response

Put that in your views file, point your URL to it, and you're off and running.

Edit: As noted, this is a simplified version of a recipe in the cookbook. However, it looks like there is a difference between calling print_png and savefig, at least in the initial test that I did. Calling fig.savefig(response, format='png') gave an image with that was larger and had a white background, while the original canvas.print_png(response) gave a slightly smaller image with a grey background. So, I would replace the last few lines above with:

    canvas=FigureCanvas(fig)
    response=django.http.HttpResponse(content_type='image/png')
    fig.savefig(response, format='png')
    return response

You still need to have the canvas instantiated, though.

2 Comments

Is there a difference (speed, efficiency, etc) between using canvase.print_png and simply doing a save_fig() on the HttpResponse?
You'd have to measure the difference in speed, but there is a difference in presentation as noted in the edit. This also does not depend on the pylab/pyplot wrapper functions, which I like for this sort of application.
0

Employ ducktyping and pass a object of your own, in disguise of file object

class MyFile(object):
    def __init__(self):
        self._data = ""
    def write(self, data):
        self._data += data

myfile = MyFile()
fig.savefig(myfile)
print myfile._data

you can use myfile = StringIO.StringIO() instead in real code and return data in reponse e.g.

output = StringIO.StringIO()
fig.savefig(output)
contents = output.getvalue()
return HttpResponse(contents , mimetype="image/png")

2 Comments

This would work quite well, but as wierob mentioned, HttpResponse already supports file access (which I didn't realize). So you can skip creating your own class. Anyone doing something similar outside of django, this definitely looks like a good idea.
actually I am not creating my own class that was just a possiblity, as I said user StringIO, and yes using respose object itself is best.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.