· 2 min read

Generating Font Previews with Python and Pillow for Enhanced UX

Using Python and Pillow, I've automated the creation of font previews to simplify selection.

How I automated generating font previews with a Python script using Pillow. It covers the frustrating font picking experience that prompted this solution, how the script downloads and draws fonts into preview images, integrating them to improve UX, and key lessons learned about leveraging Python for automating digital asset generation.

Selecting fonts from lists is tedious when users can’t visualize how text will look. I wrote a Python script using Pillow to auto-generate font previews for easier selection.

In this post, I’ll explain my frustrating experience, the Python automation solution, results, and lessons learned.

The Problematic Font Selection Process

While building a social media post creator web app (Postnitro.ai), I included customizable fonts. Users could choose from 50+ font options.

However, the interface only displayed names in plain text. Users had to:

  1. Pick a font
  2. Apply to their text
  3. Check how it looked
  4. Repeat until satisfied

This frustrating trial-and-error process meant guessing how fonts would appear. Users wasted time visualization was impossible.

I needed to show previews of each font alongside names, so users could see how text would render before selecting.

Automating Previews with Python and Pillow

To solve this, I wrote a Python script using Pillow that loops through available fonts and creates and save the preview images for me.

The script:

  1. Downloads font files from a JSON list of Google Fonts URLs
  2. Checks for errors downloading each font
  3. Uses Pillow to create a simple white background image
  4. Draws the font name on the image in black text
  5. Saves the preview as a PNG file

This allowed me to automatically generate a preview image for every font without tedious manual work.

Here is the json file structure:

[  
   {  
		"family":"Gaegu",  
		"full_name":"Gaegu Light",  
		"postscript_name":"Gaegu-Light",  
		"style":"Gaegu-Light",  
		"url":"https://fonts.gstatic.com/s/gaegu/v10/TuGSUVB6Up9NU57nifw74sdtBk0x.ttf",  
		"category":"handwriting"  
	  },  
	  {  
		"family":"Gaegu",  
		"full_name":"Gaegu Bold",  
		"postscript_name":"Gaegu-Bold",
		"style":"Gaegu-Bold",  
		"url":"https://fonts.gstatic.com/s/gaegu/v10/TuGSUVB6Up9NU573jvw74sdtBk0x.ttf",  
		"category":"handwriting"  
	  },  
	  {  
		"family":"Gaegu",  
		"full_name":"Gaegu Regular",  
		"postscript_name":"Gaegu-Regular",  
		"style":"Gaegu-Regular",  
		"url":"https://fonts.gstatic.com/s/gaegu/v10/TuGfUVB6Up9NU6ZLodgzydtk.ttf",  
		"category":"handwriting"  
	  },  
	  {  
			"family":"Open Sans",  
			"full_name":"Open Sans Light",  
			"postscript_name":"OpenSans-Light",  
			"style":"OpenSans-Light",  
			"url":"https://fonts.gstatic.com/s/opensans/v27/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsiH0C4nY1M2xLER.ttf",  
			"category":"sans-serif"  
	  }
	  // More google fonts here...
  ]

Here is the full script:

# 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}")

This script enabled generating a set of preview images that could be displayed in the font selection interface.

Integrating Previews to Improve UX

With the script generating previews, I could display them in the font selection interface alongside names:

Now users could visualize how text would look in any font before picking one.

This eliminated the frustrating guessing game and improved the overall experience.

Lessons Learned Automating with Python

This project taught me:

  • Python automation simplifies repetitive digital asset creation.
  • Pillow provides an easy way to dynamically draw and save images.
  • For better UX, preview images should accompany font lists.
  • Automated solutions save time compared to manual repetition.
  • Scripts allow instantly updating assets like previews.

Summary

  • Font picking is frustrating when users can’t visualize options.
  • Manually creating previews is time-consuming.
  • Python automation generatively handles preview generation.
  • Pillow draws and saves font previews on the fly.
  • Previews alongside fonts improves selection UX.
Seerat Awan

Tech Enthusiast | Frontend Developer

@seeratawan01

Subscribe to my newsletter to get the latest updates on my blog.

Back to Blog