AttributeError: Can't use a Specific Font with Pillow Module to Write on Images in Streamlit Cloud

Hi community!

Hope you’re doing well :slight_smile:

I looked up in this and other forums but couldn’t find a solution for my problem.

I’m creating an app for my company to generate certificates where the user 1) uploads a csv file 2) uploads a certificate template and 3) generates certificates and downloads them.

My app uses Pillow module (version 9.5.0) to write a list of names from the csv file and write in the uploaded certificate template using a specific font.

My problem is that I’m getting an Attribute Error when trying to “write” using Pillow module on the user’s image input. Specifically, when user’s presses the “Generar Certificados” (Create Certificates) button.

This error is unexpected because textsize is a valid attribute in Pillow’s ImageDraw module. Also, the code works well locally, but not when deploying the app in the cloud.

AttributeError: 'ImageDraw' object has no attribute 'textsize'

2024-03-30 00:37:18.000 Uncaught app exception
Traceback (most recent call last):
  File "/home/adminuser/venv/lib/python3.9/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 542, in _run_script
    exec(code, module.__dict__)
  File "/mount/src/creador-certificados/creador_de_certificados/streamlit_nt_app.py", line 85, in <module>
    main()
  File "/mount/src/creador-certificados/creador_de_certificados/streamlit_nt_app.py", line 51, in main
    create_certificate(cleaned_data, cert_template, output_dir)
  File "/mount/src/creador-certificados/creador_de_certificados/main.py", line 55, in create_certificate
    text_width, _ = draw.textsize(name, font=font)

AttributeError: 'ImageDraw' object has no attribute 'textsize'

I think the problem is related to my “Roboto-Medium.hnn” file in the create_certificate function in main.py:

from PIL import Image, ImageDraw, ImageFont
import pandas as pd 
from pathlib import Path
import logging

def clean_data(csv_file):
    df = pd.read_csv(csv_file)

    df = df.rename(columns={
        'Correo electrónico. Por favor, asegurarse de que esté escrito correctamente.': 'mail',
        'APELLIDO/S, NOMBRE/S:': 'nombre_apellido'
    })
    return df

def create_certificate(data, certificate_path: str, output_folder: str):
    logging.basicConfig(filename='certificate_creation.log', level=logging.ERROR)

    print('Creating your certificates...')

    # Extract names from the cleaned data
    names = data['nombre_apellido']

    for name in names:
        # Remove unwanted characters from the name
        name = name.replace('.', '').replace(',', '').replace(':', '').strip()
        name = name.upper()

        text_y_position = 430  # Adjusted position for text
        img = Image.open(certificate_path, mode='r')
        img_width = img.width

        # draw
        draw = ImageDraw.Draw(img)

        # font
        font_size = 110

        if len(name) > 30:
            font_size = font_size / 2
        elif len(name) > 20:
            font_size = font_size * 2 / 3

        # PROBLEM
        font_path = str(Path('data/Roboto-Medium.woff'))
        
        try:
            font = ImageFont.truetype(font_path, int(font_size))
        except Exception as e:
            logging.error(f"Error loading font file: {e}")
            print(f"Error loading font file: {e}")
            continue  # Skip this certificate and continue with the next one

        # text width
        text_width, _ = draw.textsize(name, font=font)

        # draw text for name in orange color
        draw.text(((img_width - text_width) / 2, text_y_position), name, font=font, fill='#de5602')

        # save certificates in a folder
        output_path = f"{output_folder}/{name}.pdf"
        img.save(output_path)
        print(f"Saved certificate for {name} at {output_path}")

Somehow, the app can’t find and use that font.

I tried using Path from pathlib but I still encountering errors when deploying my app in streamlit cloud.

This is the link for my app: https://creador-certificados-nt.streamlit.app/
This is the link of my repository: https://github.com/axcasas/creador-certificados/tree/master

main.py contains the create_certificate function.
streamlit_app is the app I’m deploying to streamlit.

Thank you!