2010-06-17 7 views
7

मेरे पास एक कोड है जो एक काहिरा ImageSurface उत्पन्न करता है, और मैं इसे इस तरह का खुलासा करता हूं:CherryPy के साथ एक HTTP प्रतिक्रिया में एक छवि कैसे वापस करें

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') काम करता है, लेकिन मुझे यकीन नहीं है कि डेटा को वापस करने के लिए डेटा को डंप करना है। मैं कुछ फाइल जैसी वस्तु का अनुमान लगा रहा हूं? Xzx21 के अनुसार, get_data() एक बफर देता है। मैंने अब भी कोशिश की है:

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

साथ ही, क्या यह छवि स्मृति में बनाने और पकड़ने के लिए बेहतर है (जैसे मैं करने की कोशिश कर रहा हूं) या इसे डिस्क पर एक temp फ़ाइल के रूप में लिखना और वहां से इसकी सेवा करना ? मुझे केवल एक बार छवि की आवश्यकता है, फिर इसे त्याग दिया जा सकता है।

+0

'write_to_png_stream' के बारे में कैसे? http://cairographics.org/documentation/cairomm/reference/classCairo_1_1Surface.html#b3eca5bc13abe27f470fdf08134269bb –

+0

pycairo उस विधि का पर्दाफाश प्रतीत नहीं होता है ... http://cairographics.org/documentation/pycairo/2/reference/surfaces। एचटीएमएल # वर्ग-इमेजर्सफेस-सतह – colinmarc

उत्तर

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

+0

ग्रेट उत्तर, ज़िफोट - मुझे लगता है कि कुंजी "write_to_png" का उपयोग कर रही है जो कच्चे डेटा को पीएनजी प्रारूप में परिवर्तित करती है। बस सतह का उपयोग कर .get_data() काम नहीं करेगा क्योंकि यह आंतरिक रूप से पीएनजी डेटा (यह ARGB_32) के रूप में संग्रहीत नहीं है। –

+0

@Marc Novakowski - धन्यवाद। आप सही हैं, ImageSurface यहां वर्णित प्रारूपों में से एक में स्मृति में डेटा रखता है: http://cairographics.org/manual/cairo-image-surface.html#cairo-format-t। आउटपुट फाइल का प्रारूप एक अलग कहानी है। – zifot

0

क्या आपने return str(surface.get_data()) को आजमाया है?

+0

बस कोशिश की, काम नहीं किया। – colinmarc

0

'स्मृति में फ़ाइल' दृष्टिकोण के लिए यह प्रयास

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

अभी भी कोई भाग्य नहीं ... – colinmarc

1

surface.get_data() के काम को समझने के कारण आप असफल हो रहे हैं। आप माइम-प्रकार वापस जाने के लिए कोशिश कर रहे हैं image/png लेकिन surface.get_data() रिटर्न सादा बिटमैप छवि है जो "आभासी स्क्रीन" (सतह)

इस तरह

से सादे छवि डंप है (हेडर के साथ एक Widnows बिटमैप फ़ाइल .BMP नहीं है):

 
0000010000 
0000101000 
0001000100 
0010000010 
0001000100 
0000101000 
0000010000 
संबंधित मुद्दे