Kerning with Python Imaging Library(PIL)

I was working on a problem that requires excellent precision pixel by pixel, so I needed to have the ability to manipulate text in more ways than what PIL provides. Especially with regard to kerning. There is a feature that allows you to disable kerning, but not control the amount which is obviously incomplete.

This problem was made more challenging because of bugs in PIL that relate to accurately measuring the size of text. There are many posts about this problem but the most useful information is a Stack Overflow post here, 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.

My code is for my own use but if someone is having similar issues, I’m sure that it can easily be adapted for your own needs.

My key functions are:

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)

It gives a nice output below. However, it’s not entirely precise. The number of pixels between letters will vary slightly with different fonts. I have not found a way to standardize this, so I’ve just accepted the fact when I enter a value for kerning into my GUI, it is just a scalar relative to the font, not the number of pixels

-David Van Anda

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: