在Python/Web.Py中使用PIL正确提供动态图像的方法

0 投票
1 回答
3755 浏览
提问于 2025-04-17 16:21

我需要让一个Python文件表现得像一张图片。也就是说,这个Python文件的路径会被用在网页的标签里。这个Python文件会用PIL动态生成一张图片(不需要先保存到文件)。

我使用的是Python 2.7、Web.Py和PIL,开发环境是32位的Windows XP,使用WAMPSS网页服务器,并且用的是最新的Chrome浏览器。

我觉得我快要成功了

下面是我这个Python图片文件的简化示例:

#!/home/bin/python
# #############################################################################
import web, sys
from PIL import Image, ImageDraw, ImageFont
# #############################################################################
class debug:
    def GET(self):
        # drawing with PIL (Python Image Library)
        # create a new 256x256 pixel image surface (default is black bg)
        img = Image.new("RGB", (256, 256))
        # set up the new image surface for drawing
        draw = ImageDraw.Draw (img)
        # REMOVED - Image manipulation
        # Output the image to the browser
        sys.stdout.write('Status: 200 OK\r\n')
        sys.stdout.write('Content-type: image/png\r\n')
        sys.stdout.write('\r\n')
        img.save(sys.stdout, "PNG")
# #############################################################################
urls = ( '/debug.py', 'debug' )
app = web.application(urls, globals())
if __name__ == "__main__":
    app.run()
# #############################################################################

现在,这个是可以工作的……有点。

如果我直接在浏览器中查看这个文件(在本地的AMPSS服务器上),它会显示出图片。但是,相比于一个类似的1k PNG图片,它的显示/加载时间要长很多(超过5秒)。而且Chrome控制台显示它失败了(尽管我能看到图片)。

我觉得浏览器期待的东西和我发送的不同?

真正的问题出现在我在JQuery和OnLoad事件中使用这个图片时。事情变得……奇怪……用更好的词形容都不太容易。我似乎遇到了一些事件(不是我设置的)在图片加载并显示后几秒钟又把它清除了。

Chrome控制台显示在获取图片时GET请求失败(尽管图片确实显示出来了,至少在某些JS让它消失之前!)

有趣的是,这个问题在最新的Firefox中似乎不存在。在最新的Opera中加载时间被夸大了,但JS没有让图片出现问题。在IE8中也是一样。

更让人困惑的是,我有两台Windows XP(32位)的开发机器。JS的问题在其中一台上没有出现。而且Chrome控制台没有列出任何错误!

我在网上放了一个这个图片文件的演示:链接,还有我正在开发的使用这个文件的页面:链接。如果你在白色的图片占位符上点击,Jquery/JS会激活。

我不知道这在你的环境中是否能工作。我只是为了完整性而链接这些。

你有什么想法我可能遗漏了什么吗?

1 个回答

2

在web.py中,你需要返回要发送给浏览器的内容。同时,可以使用 web.header 来设置HTTP头信息。

将图片保存到 StringIO 中,然后返回它的内容:

import StringIO

# in GET(self):
web.header('Content-type', 'image/png')
buf = StringIO.StringIO()
img.save(buf, "PNG")
contents = buf.getvalue()
return contents

撰写回答