如何在 PIL 中对文本进行紧排

How to kern text in PIL

我正在处理一个需要逐像素精确度的问题,因此我需要能够以比 PIL 提供的方式更多的方式来处理文本。特别是关于字距调整。有一个功能允许您禁用字距调整,但不能控制数量。

由于 PIL 中与准确测量文本大小相关的错误,此问题变得更具挑战性。关于这个问题有很多 post,但最有用的信息是这里的 SO post,How to get the font pixel height using PIL's ImageFont class? and a blog article, How to properly calculate text size in PIL images

我的代码仅供我自己使用,但如果有人遇到类似问题,我相信它可以很容易地根据您自己的需要进行调整。

我的主要职能是:

def get_text_width(text_string, font):
    return font.getmask(text_string).getbbox()[2]


def kern(name, draw_object, y, space, font, fill):
    chars = [char for char in name]

    total_width = 0

    for char in chars:
        width_text = get_text_width(char, font)
        total_width += (width_text + int(space))

    __, height_text = draw_object.textsize(name, font)
    __, offset_y = font.getoffset(name)
    height_text += offset_y

    width_adjuster = 0
    for char in chars:
        width_text = get_text_width(char, font)
        top_left_x = (473 / 2 - total_width / 2) + width_adjuster
        top_left_y = (40 / 2 - height_text / 2) + y
        xy = top_left_x, top_left_y
        width_adjuster += width_text + int(space)
        print(f"char:{char},width_text:{width_text},xy:{xy},width_adjuster:{width_adjuster}")
        draw_object.text(xy, char, font=font, fill=fill)

它在下面给出了一个很好的输出。然而,它并不完全精确。字母之间的像素数会随着字体的不同而略有不同。我还没有找到标准化的方法,所以当我在我的 GUI 中输入字距调整值时,我接受了这个事实,它只是一个相对于字体的标量,而不是像素数