Created
September 23, 2022 18:40
-
-
Save avalonv/3331167eeb548004946eebddc623c85d to your computer and use it in GitHub Desktop.
Python function to wrap and scale text to fit Pillow images
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from PIL import Image, ImageFont, ImageDraw | |
def fit_textbox(length:int, height:int, text:str, fontname:str, fmin=15, fmax=40): | |
# this will dynamically wrap and scale text with a font size that can fill | |
# a given textbox, both length and height wise. manually setting fmin and | |
# fmax is recommended when working with larger batches of text. | |
# returns wrapped text and a ImageFont.FreeTypeFont object | |
def get_wrapped_text(text:str, font:ImageFont.FreeTypeFont, line_length:int): | |
# adapted from Chris Collett https://stackoverflow.com/a/67203353/8225672 | |
lines = [''] | |
for word in text.split(): | |
line = f'{lines[-1]} {word}'.strip() | |
if font.getlength(line) <= line_length: | |
lines[-1] = line | |
else: | |
lines.append(word) | |
return '\n'.join(lines) | |
font = ImageFont.truetype(fontname, fmin) | |
lines = get_wrapped_text(text, font, length) | |
boxheight = image.multiline_textbbox((15,15),lines, font)[-1] | |
for fsize in range(fmin, fmax+1): | |
font = font.font_variant(size=fsize) | |
lines = get_wrapped_text(text, font, length) | |
boxheight = image.multiline_textbbox((15,15),lines, font)[-1] | |
# print(boxheight) | |
if boxheight > height: | |
fsize -= 1 | |
font = font.font_variant(size=fsize) | |
lines = get_wrapped_text(text, font, length) | |
# print(f"FSIZE={fsize}") | |
break | |
return lines, font | |
# example | |
text = "Miracles of artistry were everywhere. Great iron crates with wheels sat silent on steel rails. Beautifully carved works with lights of red, amber, and green dangled over every street. As they moved away from the massive sculptures, they found a great array of smaller ones. Some were covered in glass or brick, but many were composed of materials they had never before encountered. The sheer variety of colors and styles was staggering." | |
v_margin = 15 | |
h_margin = 15 | |
out = Image.new(mode='RGB', size=(600,800), color='white') | |
image = ImageDraw.Draw(out) | |
lines, font = fit_textbox(565, 745, text, 'bookerly.ttf') | |
image.multiline_text((h_margin, v_margin), lines, 'grey', font) | |
out.save("forestofmyth.jpg") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment