将文本转换为PNG图像(Python)
注意:我把这个问题从App Engine小组转过来,因为那里没有人回答。
在我关于日本的网站上,有一个功能可以让用户获取一张大的PNG图片,用作桌面背景,上面显示用户的名字用日文写的。可是在我把网站完全迁移到App Engine后,我把这个功能去掉了,因为我找不到任何方法通过图像API把文字渲染到PNG上。
换句话说,我想知道怎么在一张已知尺寸的图片上(比如1024x768)输出一个unicode字符串,这样文字就能尽可能大地水平显示,并且垂直居中。请问在App Engine上有办法做到这一点吗?或者有没有其他的外部服务可以推荐给我,能让这个过程更简单一些(除了在自己的服务器上运行ImageMagick)?
4 个回答
虽然有点晚了,但我也在找这个。通过以下方法,我成功地把unicode字符串(这里是天城文)绘制到一张图片上,并保存为'.png'文件:
# -*- coding: utf-8 -*-
import Image, ImageDraw, ImageFont
img = Image.new('L', (16,16), 255)
draw = ImageDraw.Draw(img)
text_to_draw = unicode('क','utf-8')
font = ImageFont.truetype('Path/to/font/file',12)
draw.text((2,2), text_to_draw, font = font)
del draw
img.save('image.png')
附注:我从其他StackOverflow的帖子中得到了帮助。
我在给图片写文字的时候也遇到了同样的问题。问题是,谷歌应用引擎上使用的任何图像库都必须是纯Python的,这就排除了PIL这个库。
PyBMP
PyBMP是一个纯Python的库,可以用来简单地渲染文本。你可以用谷歌的图像库把生成的位图合成到其他图片上。下面有一些示例代码。不过这个库的缺点是缺少一些更好的功能,比如抗锯齿和对字体的精细控制,所以它渲染的文字看起来有点糟糕。而且它可能对unicode的支持也不太好。
# Create the image
text_img = bmp.BitMap(300,35,bmp.Color.WHITE)
# bmpfont_Tw_Cen_MT_30 is a generated file using PyBMP's tool
text_img.setFont(bmpfont_Tw_Cen_MT_30.font_data)
text_img.setPenColor( bmp.Color.BLACK )
text_img.drawText(name, 0, 0)
之后,你可以像处理其他图片一样,使用谷歌的composite
函数在text_img.getBitmap()
上进行操作。
外部图像处理
如果渲染的文字效果不够好(我项目中的效果就不理想),另一种解决方案是设置一个外部服务器,比如使用Rackspace,专门进行图像处理。你可以设置一个HTTP处理程序,使用PIL进行图像处理,然后返回处理后的图片。接下来你可以选择
- 直接把结果上传到你的静态文件托管服务器(比如s3),或者
- 使用应用引擎的urlfetch库获取生成的文字图片,然后在应用引擎中完成剩下的合成工作
虽然不太好看,但能完成任务。
解决方案 #1. 纯 Python 图像库。
你可以尝试把 PyPNG 和你的应用程序打包在一起。PyPNG 是一个纯 Python 库,用于创建 PNG 图像。它依赖于 zlib 模块,而这个模块在 AppEngine 上是可以使用的,所以 PyPNG 应该能在 AppEngine 上正常工作。只需使用 StringIO 对象代替文件,并将 PNG 数据写入这些对象中。
这里有个 PyPNG 的例子,展示如何制作位图 PNG 图像:
import png
from StringIO import StringIO
# bitmap data
s = ['110010010011',
'101011010100',
'110010110101',
'100010010011']
s = map(lambda x: map(int, x), s)
f = StringIO()
w = png.Writer(len(s[0]), len(s), greyscale=True, bitdepth=1)
w.write(f, s)
# binary PNG data
print f.getvalue()
我怀疑性能可能不太理想,但据我所知,生成图像在 GAE 上没有其他更好的方法。
你还需要想办法将文本转换为位图数据。最简单的方法可能就是保存所有符号的位图(基本上就是使用位图字体)。
如果想用 PyPNG 渲染 ASCII 文本,可以看看 texttopng 脚本。
所以,限制条件有:
- 可能比较慢(需要检查)
- 需要解决字形栅格化的问题
解决方案 #2. 外部文本转图像渲染。
Google AppEngine 不提供将文本渲染为栅格图像的工具,但 Google Charts 提供了。通过正确选择参数,轮廓文本 图表可以将简单文本渲染为 PNG 图像。
例如,http://chart.apis.google.com/chart?chst=d_text_outline&chld=000000|32|h|FFFFFF|_|Render text to image|with Google Charts.|Some Unicode too:|Здра́вствуйте|こんにちは|नमस्ते|你好|שלו
生成的结果是:
限制条件有:
- 不能生成超过 300000 像素的图像
- 样式和字体的自定义有限
- 某些 Unicode 字符集不可用
- 只能使用白色背景