Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrap text in PIL

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 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."

image = Image.open("/tmp/background-image.jpg")
draw = ImageDraw.Draw(image)
font = ImageFont.truetype("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf"), 50, encoding='unic')
draw.text((100, 100), text, font=font, fill="#aa0000")
image.save("/tmp/image.jpg")
like image 981
Neil Avatar asked Nov 24 '11 12:11

Neil


People also ask

How do you wrap text in Python?

wrap(text, width=70, **kwargs): This function wraps the input paragraph such that each line in the paragraph is at most width characters long. The wrap method returns a list of output lines. The returned list is empty if the wrapped output has no content.

How do you wrap text around an image in Python?

Import textwrap standard library and just replace "text" with "textwrap. fill(text)" on your sixth line, and it's done dynamically.

What is the text wrap?

Alternatively referred to as text flow, text wrap is a feature in text editors and word processors. It allows the user's text to be continued to the next line when the side of the page is reached.

How do you wrap text in idle Python?

Put simply, if you type a very long piece of text, it disappears off the side of the page, unlike this comment box where it wraps the text around into many lines. If you use the return key to wrap the text, instead of starting a new line, it runs the program.


3 Answers

You will need to first split the text into lines of the right length, and then draw each line individually.

The second part is easy, but the first part may be quite tricky to do accurately if varible-width fonts are used. If fixed-width fonts are used, or if accuracy doesn't matter that much, then you can just use the textwrap module to split the text into lines of a given character width:

margin = offset = 40 for line in textwrap.wrap(text, width=40):     draw.text((margin, offset), line, font=font, fill="#aa0000")     offset += font.getsize(line)[1] 
like image 148
ekhumoro Avatar answered Oct 18 '22 17:10

ekhumoro


Well, you can do this manually, of course, using the \n every time you want to wrap the text. It isn't the best way if you have different string everytime but gives entire control over the result. But there is also the textwrap module. You can use it this way:

import textwrap texto = "Lorem ipsum dolor sit amet, consectetur adipisicing 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." novo = textwrap.wrap(texto, width=20) print(novo) 

Results:

>>>  ['Lorem ipsum dolor', 'sit amet,', 'consectetur', 'adipisicing 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.', 'Duis aute irure', 'dolor in', 'reprehenderit in', 'voluptate velit esse', 'cillum dolore eu', 'fugiat nulla', 'pariatur. Excepteur', 'sint occaecat', 'cupidatat non', 'proident, sunt in', 'culpa qui officia', 'deserunt mollit anim', 'id est laborum.'] 

Returns a list of terms on the previous string wrapped according to the width you determinated.

like image 27
jonathan.hepp Avatar answered Oct 18 '22 17:10

jonathan.hepp


The accepted solution wraps text basing on the fixed limit of 40 characters per line, not taking into account the box width (in pixels) nor font size. This may easily lead to underfill or overfill.

Here is a better solution - a simple code snippet to wrap text taking into account font-based width measurement: https://gist.github.com/turicas/1455973

like image 33
pryma Avatar answered Oct 18 '22 15:10

pryma