2010-06-17 80 views
7

HTTP響應返回圖像我有一個生成開羅ImageSurface代碼,我揭露它,像這樣:如何與CherryPy的

def preview(...): 
    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) 
    ... 
    cherrypy.response.headers['Content-Type'] = "image/png" 
    return surface.get_data() 
preview.exposed = True 

這不起作用(瀏覽器報告,圖像有錯誤)。

我測試了surface.write_to_png('test.png')的作品,但我不確定將數據轉儲到什麼位置以返回它。我在猜測一些類似文件的對象?根據the pycairo documentationget_data()返回一個緩衝區。我也試過現在:

tempf = os.tmpfile() 
surface.write_to_png(tempf) 
return tempf 

而且,是它更好地創建和存儲持有這一形象(就像我試圖做的),或者將其寫入到磁盤的臨時文件,並從那裏爲它服務?我只需要一次圖像,然後就可以丟棄。

+0

'write_to_png_stream'如何? http://cairographics.org/documentation/cairomm/reference/classCairo_1_1Surface.html#b3eca5bc13abe27f470fdf08134269bb – 2010-06-17 18:18:10

+0

pycairo似乎並未公開該方法... http://cairographics.org/documentation/pycairo/2/reference/surfaces。 html#class-imagesurface-surface – colinmarc 2010-06-17 18:23:52

回答

15

添加這些進口:

from cherrypy.lib import file_generator 
import StringIO 

,然後是這樣的:

def index(self): 
    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) 
    cherrypy.response.headers['Content-Type'] = "image/png" 

    buffer = StringIO.StringIO() 
    surface.write_to_png(buffer) 
    buffer.seek(0) 

    return file_generator(buffer) 

Additionaly,如果你服務獨立文件(即它不是網頁的一部分),你不希望它被渲染到瀏覽器中,而是作爲一個文件處理保存在磁盤上,那麼你需要一個更多頭:

cherrypy.response.headers['Content-Disposition'] = 'attachment; filename="file.png"' 

此外,爲更好在內存中創建並保持 此圖像(像我試圖 做的),或者它寫入到磁盤一個臨時文件 並從那裏提供服務?我只需要 需要一次圖像,那麼它可以被 丟棄。

如果你想要做的唯一的事情是爲這個文件瀏覽器沒有理由在服務器上的磁盤上創建它。恰恰相反 - 請記住,訪問硬盤會帶來性能損失。

+0

工程太棒了!對於賞金,你能向我解釋爲什麼? – colinmarc 2010-06-21 04:57:32

+0

很好的答案,zifot - 我認爲關鍵是使用「write_to_png」將原始數據轉換爲PNG格式。只是使用surface.get_data()將不起作用,因爲它不是內部存儲爲PNG數據(它是ARGB_32)。 – 2010-06-21 05:01:44

+0

@Marc Novakowski - 謝謝。你是對的,ImageSurface以這裏描述的格式之一在內存中保存數據:http://cairographics.org/manual/cairo-image-surface.html#cairo-format-t。輸出文件的格式是一個不同的故事。 – zifot 2010-06-21 17:01:48

0

你試過return str(surface.get_data())

+0

剛剛嘗試過,沒有工作。 – colinmarc 2010-06-18 01:07:21

0

嘗試此 '在內存中的文件' 的方式

return StringIO.StringIO(surface.get_data()) 
+0

仍然沒有運氣... – colinmarc 2010-06-18 15:04:12

1

由於不瞭解surface.get_data()的工作原因,您失敗了。 你試圖返回MIME類型image/pngsurface.get_data()返回 平原位圖圖像(不是用頭一個WIDNOWS位圖文件.BMP),這 是從「虛擬屏幕」(表面)

像這種普通的圖像轉儲:

 
0000010000 
0000101000 
0001000100 
0010000010 
0001000100 
0000101000 
0000010000