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

是否可以检测到此类文本溢出并按照我们的预期绘制文本以适合画布?


问题答案:

在这种情况下,只需指定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绘制异国字体的效果不佳,无论您指定加载字体的点大小如何,PIL总是在输出图像之外溢出文本。