5

I've spent a lot of time making my first web application using Python, and I'm using for generating images. After reading a lot, I've managed to implement proper text aligning, wrapping, generating files with many extensions etc.

However, all the text generated by PIL is cut off at the top. Here's a sample.

Example of PIL-generated image with text cut off at the top

It should say ŻÓĆjygpq in a variety of fonts (the font names are on the left).

I've found few posts here: fonts clipping with PIL, but I'd like to avoid using another module (aggdraw); since I've figured out so many things in PIL already I'd like to stick to that.

I've tried many fonts in different sizes, but text is still cut off. I even tried to use PIL fonts, but it still doesn't work. [Also converting OTF to BDF, and to PIL].

This is on Ubuntu. What should I try next?

Charles Merriam
  • 19,908
  • 6
  • 73
  • 83
Matt
  • 53
  • 7
  • Interesting problem, I would be surprised if this can be fixed without going into the C parts of PIL. – mmgp Dec 11 '12 at 17:59
  • Can you include your sample code for printing these texts ? I've patched _imagingft.c and it seems to work for the font I tested. – mmgp Dec 11 '12 at 20:05
  • thanks for the answer. i simplified it a little bit, but the method is the same: ``color_text = 'black' text2 = 'DejaVuSans.ttf' font1 = ImageFont.truetype('/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf', 34) draw.text((20,50), text2, color_text, font=font1)`` it's got nothing fancy in it, just few calculations for wrapping, centering etc. so it's just the basic draw.text delivered by pil. in theory it should work out of the box, especially with those PIL type fonts. – Matt Dec 11 '12 at 21:24

2 Answers2

4

I hope to be wrong on this one, but the only correct fix relies on patching how _imagingft.c renders the text. PIL depends on FreeType for this task, but PIL seems to be miscalculating the positioning. Also, the height in getsize is overestimated (although that doesn't cause problem). For the moment, I've put a patch to handle these issues at: http://pastebin.com/jP2iLkDN (there seems to be a better way to patch the render code).

Here are some examples of the output I get without the patch and with the patch, respectively:

enter image description here     enter image description here

Results using the code present in the linked discussion. On OSX:

enter image description here     enter image description here

On Ubuntu:

enter image description here     enter image description here

Here is the code to generate the top figures:

# -*- encoding: utf8 -*-
import sys
import Image, ImageDraw, ImageFont

im = Image.new("RGBA", (1000, 1000), 'white')
draw = ImageDraw.Draw(im)

start_y = 7
text = u'\u00d1\u00d3yŻ\u00d4Ćgp\u010c\u0137'
for i in xrange(28, 46, 2):
    font = ImageFont.truetype('Junicode-Bold.ttf', i)
    width, height = font.getsize(text)
    draw.rectangle((0, start_y, width, height + start_y), outline='blue')
    draw.text((0, start_y), text, font=font, fill='black')
    start_y += height + 7

im.crop((0, 0, width + 1, start_y + 2)).save(sys.argv[1])

The bottom figures were generated according to code present in the linked topic about PIL cutting off parts of the text.

mmgp
  • 18,901
  • 3
  • 53
  • 80
  • One shortcoming of this patch is that it will cause trouble (vertical alignment trouble) when you write letter by letter instead of the entire text at once. To solve that, the patch needs to further modify PIL so it returns the baseline (a good place seems to be in `getsize`) of the text, and then pass that value when a call to `render` is made. The function `getsize` would also need to return proper offsets in vertical directions, which currently is always 0. – mmgp Dec 21 '12 at 12:59
  • you saved me a lot of time. Thanks! – lqdc Jan 26 '13 at 02:37
1

Not the best solution but I see people have solved this by adding a leading a trailing space to their text.

WSkinner
  • 2,147
  • 1
  • 19
  • 21