ImageFont的getsize()不返回正确的文本大小?
我使用以下两种方法来生成 .ttf 字体文件的文字预览图像。
PIL 方法:
def make_preview(text, fontfile, imagefile, fontsize=30):
try:
font = ImageFont.truetype(fontfile, fontsize)
text_width, text_height = font.getsize(text)
img = Image.new('RGBA', (text_width, text_height))
draw = ImageDraw.Draw(img)
draw.text((0, 0), text, font=font, fill=(0, 0, 0))
return True
except:
return False
ImageMagick 方法:
def make_preview(text, fontfile, imagefile, fontsize=30):
p = subprocess.Popen(['convert', '-font', fontfile, '-background',
'transparent', '-gravity', 'center', '-pointsize', str(fontsize),
'-trim', '+repage', 'label:%s' % text, image_file])
return p==0
这两种方法大部分情况下都能正确生成预览图像,但在一些少见的情况下(不到2%),font.getsize(text) 就无法获取正确的文字大小,导致文字超出了预设的画布范围。ImageMagick 也有同样的问题。
示例字体和预览:
HANFORD.TTF http://download.appfile.com/HANFORD.png
NEWTOW.TTF http://download.appfile.com/NEWTOW.png
MILF.TTF http://download.appfile.com/MILF.png
SWANSE.TTF http://download.appfile.com/SWANSE.png
我查看了 ImageMagick 的文档,发现了这个问题的解释,链接在这里:http://www.imagemagick.org/Usage/text/#overflow。
有没有办法检测到这种文字溢出,并将文字绘制到我们预期的画布上呢?
3 个回答
我之前在用PHP和ImageMagick的时候也遇到过类似的问题。
最后,我是通过在一个非常大的画布上绘制文字,然后使用trim/auto-crop功能来裁剪掉多余的空白区域来解决的。
如果我理解你的预览功能没错的话,它其实已经在做这个了:只需要去掉宽度和高度的设置就可以了。
这不是一个编程解决方案,但我在重现你的问题时发现,只有你的字体有问题(像Arial这样的其他字体就没问题),所以我修复了你的字体文件(通过调整上升和下降的度量)。你可以在这里下载。
关于Hanford Script字体,抱歉,它并不完美,虽然高度看起来还行,但左边的部分没有显示出来,这让我有点困惑。
更新:关于Hanford字体,这里有个变通办法,可以在文本中加一些额外的空格,比如" Handford Script",然后在图像中裁剪掉多余的空白,像这样使用img=img.crop(img.getbbox())
。
这里是变通办法的示例 http://img64.imageshack.us/img64/1903/hanfordfontworkaround.jpg
更新2:我需要在Image.New中加上color=(255,255,255)才能在白色背景上显示黑色文字。
img = Image.new('RGBA', (text_width, text_height),color=(255,255,255))
在这种情况下,只需要告诉ImageMagick使用更大的画布尺寸,并设置固定的字体大小,这样它就能在指定的点大小下绘制文本,同时保持文本的完整性。
def make_preview(text, fontfile, imagefile, fontsize=30):
p = subprocess.call(['convert', '-font', fontfile, '-background',
'transparent', '-gravity', 'center', '-size', '1500x300',
'-pointsize', str(fontsize), '-trim', '+repage', 'label:%s' % text, image_file])
return p==0
如果你想把文本放进指定的画布里,而不是使用固定的点大小,你可能需要在创建完输出图像后调整图像的大小。
PIL在处理一些特殊字体时效果不太好,无论你指定什么点大小来加载字体,它总是会把文本溢出到输出图像之外。