Python 图像字体';s getsize()的文本大小不正确?

Python 图像字体';s getsize()的文本大小不正确?,python,fonts,imagemagick,python-imaging-library,Python,Fonts,Imagemagick,Python Imaging Library,我使用以下两种方法为.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_widt

我使用以下两种方法为.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
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
ImageMagick方法:

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
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

这两种方法大多数时候都能创建正确的预览图像,但在一些罕见的情况下(PHP和ImageMagick中也有过类似的问题)

最后,我解决了这个问题,在一个非常大的画布上绘制文本,然后使用一些函数来修剪它,这些函数可以减少图像的额外空间


如果我正确理解您的预览功能,它实际上已经做到了这一点:只需删除宽度和高度设置就足够了。

在这种情况下,只需指定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不能很好地绘制外来字体,无论您指定加载字体的点大小如何,它总是在输出图像外溢出文本。

这不是一个编程解决方案,但当我重新生成你的问题时,它只发生在你的字体上(其他字体如Arial完全没有问题),因此我修复了你的字体文件(通过更改ascent/Delegate度量)。你可以下载

很抱歉汉福德的字体,它并不像你们看到的那个样完美,高度看起来还可以,但左边并没有画出来,这超出了我的理解

更新:关于汉福德字体,这里有一个解决方法,在文本中传递额外的空间,如“汉福德脚本”,然后在图像中裁剪额外的空间,如
img=img.crop(img.getbbox())

更新2:我必须在图像中传递color=(255255)。新功能是在白色背景上获得黑色文本

img = Image.new('RGBA', (text_width, text_height),color=(255,255,255))

@Pekka,你的方法可能适用于IM,但它会产生很大的开销,不仅会修剪,而且会调整修剪后的图像大小以适应指定的画布尺寸。这不适用于PIL。即使我创建了一个更大的画布,它也会绘制上面字体的上半部分。请尝试放置“标签”在修剪和重新分页命令之前使用命令,这应该会起作用。开销太大了,我无能为力。如何修改指定字体的上升/下降度量?是否需要对每种字体进行手动重新计算?由于版权问题,我认为最好保持字体的原样,在较大的画布上绘制文本,然后进行裁剪。但您的方法适用于个人使用。谢谢你们的建议。很正确,但你们为什么要先把它们公开下载呢?我会很快删除我帖子上的下载链接。