DEV Community

Seerat Awan
Seerat Awan

Posted on

Automating Fonts Previews with Python and Pillow

Selecting fonts from lists is a pain when you cant visualize how they'll look. Thats why I wrote a Python script using Pillow to auto-generate font previews.

# we're importing the needed libraries
import json
import requests
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
import os

# open fonts.json file to load fonts
with open('fonts.json') as f:
    fonts = json.load(f)

# set directory for font previews
outdir = './font_previews'

# creates previews directory if it doesn't exist
os.makedirs(outdir, exist_ok=True)

# for each font in the fonts list, it will attempt the following:
for idx, font in enumerate(fonts):

    try:
        # downloads the font file from the URL provided in the font list
        response = requests.get(font['url'])

        # create a bytesIO object with downloaded font. This object behaves like a file object.
        font_file = BytesIO(response.content)

        # if the response from the server is not successful (status code 200),
        # it will print a message and will skip the rest of the loop for the current font
        if response.status_code != 200:
            print(f"Skipping font {font['postscript_name']} due to unsuccessful download from {font['url']}.")
            continue

        # creates a new image with white background
        img = Image.new('RGB', (500, 200), color='white')

        # we can now do drawing operations on this opened image
        draw = ImageDraw.Draw(img)

        # loads the downloaded font file to be later used on the image
        loadfont = ImageFont.truetype(font_file, 36)

        # calculates size in pixels of the font family string
        left, upper, right, lower = draw.textbbox((0, 0), font['family'], font=loadfont)
        w, h = right - left, lower - upper

        # calculates the center position in the image for our string to be placed
        text_pos = ((img.width - w) / 2, (img.height - h) / 2)

        # places the text (the font family string) at the calculated position
        draw.text(text_pos, font['family'], fill='black', font=loadfont)

        # sets the output filename
        outfile = os.path.join(outdir, font['postscript_name'] + '.png')

        # and saves the image in a PNG format
        img.save(outfile)

        # notifies by printing
        print(f"Saved {outfile}")

    except Exception as e:
        # handles exceptions during font handling, notifies about the error.
        print(f"An error occurred with font {font['postscript_name']}: {e}")

Enter fullscreen mode Exit fullscreen mode

Read the full article here: https://www.seeratawan.me/blog/generating-font-previews-with-python-pillow-for-enhanced-ux/

Top comments (0)