I covered the basics in one of my articles on Video generation with Python, and today I want to write about different ways to assemble text on the image so it does not look too bland.
1 – Arrange \n
To write a long text that has to be on multiple lines, you need to arrange the lines. To do that you need to set a maximum_length of the current_line, then iterate the array of the words of the text and accumulate each until current_length of current_line reaches the maximum_length.
- Iterate the words of the split text
- Arrange the words in lines until the length of the line reaches the maximum length of the line
So the code for that is pretty simple:
current_length = []
current_line = []
result = []
words = text.split()
for word in words:
word_length, word_height = Imagedraw.Draw(you_img).textsize(word, font)
if sum(current_length + [word_length]) >= maximum_length:
# new line
result.append(current_line)
current_line = [word]
current_length = [word_length]
else:
# add to the old line
current_line.append(word)
current_length.append(word_length)
# and then in case we have a trailing line
if current_line: result.append(current_line)
result = "\n".join([" ".join(x) for x in result)]
2 – Positions
Now each text has its formula to calculate the position on the list. It depends on the length of each text (after you arrange the \n’s) and the amount_of_texts. The general formula is:

The new variable here is text_proportions – this you need to derive from the lengths of the texts and the proportion between this values of all the texts. It depends heavily on the resolution of the picture. So far I failed to get a definite formula so for a limited amout of the most populat resolution I just hardcoded the value.
Now let’s apply this knowledge
and assemble text on the frame!
Here are two lines – in German and Russian (this is basically a “phrase in foreign language and its translation” frame).
Option 1: One under another (+ different style)


Option 2: Just one line in the center (+ different style + with a transparent background)

To style the text I would recommend these options:
- Font size
- Font color
- Font style – here I used italic, but I did not arrange it with PIL – I used an italic version of the font. It’s much easier and more versatile.

You can also add a background – it adds up to the structure of the frame, makes it easier to read.
To do that I make a white_<image_name>.jpg version of the background once and use it instead of the original background when necessary. The code for adding this transparent layer is fairly simple. Make a class of the background:
class Background():
def __init__(self, filename):
self.file = filename
self.file_white = Background.background_name_to_white(filename)
print(self.file_white)
if not Path(self.file_white).exists():
self.make_transparent_rect()
@classmethod
def background_name_to_white(cls, backgr):
return os.path.join("/".join(backgr.split("/")[:-1]), f'white_{backgr.split("/")[-1]}')
def make_transparent_rect(self):
# background, new_place
img = Image.open(self.file).convert("RGBA")
strip_width, strip_height = img.size
rec_width = strip_width * 0.93
rec_height = strip_height * 0.93
overlay = Image.new('RGBA', img.size, TINT_COLOR + (0,))
draw = ImageDraw.Draw(overlay) # Create a context for drawing things on it.
draw.rectangle(((strip_width * 0.07, strip_height * 0.07), (rec_width, rec_height)),
fill=TINT_COLOR + (OPACITY,))
# Alpha composite these two images together to obtain the desired result_1.
print(img.mode)
print(overlay.mode)
img = Image.alpha_composite(img, overlay)
img = img.convert("RGB") # Remove alpha for saving in jpg format.
img.save(self.file_white)
# img.show()
return

There are many other options, these are what I use in my work.
super!!!
LikeLike