2009-07-10 11 views
7

Estoy usando matplotlib en una aplicación django y me gustaría devolver directamente la imagen renderizada. Hasta ahora puedo ir a plt.savefig(...), luego devolver la ubicación de la imagen.Devolución de la imagen Matplotlib como cadena

Lo que quiero hacer es:

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

¿Alguna idea?

Respuesta

16

HttpResponse objeto de Django es compatible con la API de tipo fichero y se puede pasar un objeto de archivo de savefig.

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

Por lo tanto, puede devolver la imagen directamente en el HttpResponse.

+0

Hay algunas otras sugerencias que parecen funcionar, pero DEFINITIVAMENTE esta parece ser la más fácil de usar. ¡Solo tengo que agregar alrededor de 2 o 3 líneas de código! Thank-You – DarwinSurvivor

0

Duck Typing emplear y pasar un objeto de su cuenta, en el encubrimiento del objeto de archivo

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

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

puede utilizar mi_archivo = StringIO.StringIO() en lugar de código real y devolver datos en Reponse por ejemplo,

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

Esto funcionaría bastante bien, pero como mencionó wierob, HttpResponse ya admite el acceso a archivos (cosa que no me di cuenta). Entonces puede saltarse la creación de su propia clase. Cualquiera que esté haciendo algo similar fuera de django, esto definitivamente parece una buena idea. – DarwinSurvivor

+0

en realidad no estoy creando mi propia clase que era solo una posibilidad, como dije el usuario StringIO, y sí, usar respose object es lo mejor. –

6

¿qué hay de 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 
+0

Hmm, esto funcionaría para otros sistemas, pero no creo que django maneje muy bien la impresión directa ya que usa objetos HttpResponse para todas sus comunicaciones salientes. – DarwinSurvivor

+0

@darwinsuvivor, de acuerdo con usted, solo quiero mostrar que guardar en un objeto cStringIO.StringIO() es lo mismo que guardar en el archivo PNG. después de eso, no hay necesidad de usar imprimir aquí. Parece que la respuesta de @ wierob es completamente adecuada para nuestra situación actual. – sunqiang

2

Hay una receta en el Matplotlib Cookbook que hace exactamente esto. En su núcleo, se ve así:

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 

Ponlo en tu archivo de visitas, apunta tu URL hacia él, y estarás en funcionamiento.

Editar: Como se señaló, esta es una versión simplificada de una receta en el libro de cocina. Sin embargo, parece que hay una diferencia entre llamar a print_png y savefig, al menos en la prueba inicial que hice. Llamando fig.savefig(response, format='png') dio una imagen que era más grande y tenía un fondo blanco, mientras que el original canvas.print_png(response) dio una imagen ligeramente más pequeña con un fondo gris. Por lo tanto, reemplazaría las últimas líneas de arriba con:

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

Aún necesita tener el lienzo instanciado.

+0

¿Hay alguna diferencia (velocidad, eficiencia, etc.) entre usar canvase.print_png y simplemente hacer save_fig() en HttpResponse? – DarwinSurvivor

+0

Tendría que medir la diferencia de velocidad, pero hay una diferencia en la presentación como se indica en la edición. Esto tampoco depende de las funciones de envoltorio pylab/pyplot, que me gusta para este tipo de aplicación. –

Cuestiones relacionadas