I\'m using PIL to draw text on an image. How would I wrap a string of text. This is my code:
text = \"Lorem ipsum dolor sit amet, consectetur adipisicing eli
I didn't much like the idea of using yet another module to achieve this; I wanted to make it work with just the utilities in PIL. This works in Python 3.7.
I wrote this function that just wraps text based on pixel width and then checks pixel height too - if there are words it cannot fit, it cuts them off and adds ellipses to show omission (in a way that doesn't break the limits):
from PIL import Image, ImageDraw, ImageFont
def text_wrap(text,font,writing,max_width,max_height):
lines = [[]]
words = text.split()
for word in words:
# try putting this word in last line then measure
lines[-1].append(word)
(w,h) = writing.multiline_textsize('\n'.join([' '.join(line) for line in lines]), font=font)
if w > max_width: # too wide
# take it back out, put it on the next line, then measure again
lines.append([lines[-1].pop()])
(w,h) = writing.multiline_textsize('\n'.join([' '.join(line) for line in lines]), font=font)
if h > max_height: # too high now, cannot fit this word in, so take out - add ellipses
lines.pop()
# try adding ellipses to last word fitting (i.e. without a space)
lines[-1][-1] += '...'
# keep checking that this doesn't make the textbox too wide,
# if so, cycle through previous words until the ellipses can fit
while writing.multiline_textsize('\n'.join([' '.join(line) for line in lines]),font=font)[0] > max_width:
lines[-1].pop()
lines[-1][-1] += '...'
break
return '\n'.join([' '.join(line) for line in lines])
Usage:
bg = Image.open('external/my_background.png')
ws = Image.open('external/my_overlay_with_alpha.png')
writing = ImageDraw.Draw(bg)
title = "My Title"
description = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
title_font = ImageFont.truetype("Arial Black.ttf", size=42)
desc_font = ImageFont.truetype("Arial Narrow Italic.ttf", size=16)
description_wrapped = text_wrap(description,desc_font,writing,160,124)
# write title and description
writing.text((20,5),title,font=title_font)
writing.text((140,120),description_wrapped,font=desc_font)
out = Image.alpha_composite(bg,ws)
out.save('mysubfolder/output.png')
out.show()