What I wanted to do is a function that by given an image width
and height
and text
will fit the text into the image with a perfect font size.
I achieved this by trial-error method. Here's my code:
# -*- coding: utf-8 -*-
from PIL import ImageFont
def get_total_area(width, height):
return width * height
def get_font(name, size):
return ImageFont.truetype(font, size)
def fit(width, height, font, size, text):
font = get_font(font, size)
text_w, text_h = font.getsize(text)
text_area = get_total_area(text_w, text_h)
total_area = get_total_area(width, height)
if total_area>text_area:
action(size)
return True
else:
return size
def action(size):
print("Succes!")
counter = 0
text = """One way of doing it is to pass the text with a default font size of, say 20, to imagettfbbox and retrieve the width from it. You can then calculate how much smaller or bigger the text should be to fit the size you want by calculating a scale factor:"""
size = 60
font = 'my-font.ttf'
while True:
counter += 1
ans = fit(500, 500, font, size, text)
if ans == True:
break
else:
size = ans
size -=1
print("Font_Size: {}".format(size))
print("Repetitions: {} ".format(counter))
In this specific example (from my code above) it takes 16 repetitions and the perfect font size is 45. Now, investigating a little in StackOverflow I found questions regarding the same problem and one This solutions called my attention: https://stackoverflow.com/a/10689312/5106998
So I modified my code as follows:
# -*- coding: utf-8 -*-
from PIL import ImageFont
def get_total_area(width, height):
return width * height
def get_font(name, size):
return ImageFont.truetype(font, size)
def fit(width, height, font, size, text):
font = get_font(font, size)
text_w, text_h = font.getsize(text)
text_area = get_total_area(text_w, text_h)
total_area = get_total_area(width, height)
if total_area>text_area:
action(size)
return True
else:
scale = total_area/text_area
size = int(round(size*scale))
return size
def action(size):
print("Succes!")
counter = 0
text = """One way of doing it is to pass the text with a default font size of, say 20, to imagettfbbox and retrieve the width from it. You can then calculate how much smaller or bigger the text should be to fit the size you want by calculating a scale factor:"""
size = 60
font = 'my-font.ttf'
while True:
counter += 1
ans = fit(500, 500, font, size, text)
if ans == True:
break
else:
size = ans
size -=1
print("Font_Size: {}".format(size))
print("Repetitions: {} ".format(counter))
The second code works but not as expected: It only takes 2 repetitions to conclude that the perfect font size is 34 (We know already that it is actually 45). But obviously this second code, taking into consideration a scale
factor runs a lot faster.
My question is: where is the mistake? Or is this the best approximation that we can get using this method? Do you have any other ideas to tackle down this problem?
I don't want a perfect font size at once, what I want is to reduce the repetitions.