This image was created with PIL. See how the g's and the y's are cut off in this image? How can I prevent this?
http://img109.imageshack.us/img109/8874/screenshotep.png
The code that created this image is pretty straight forward (abbreviated):
import Image, ImageDraw, ImageFont
im = Image.new("RGBA", (200, 200), 'white')
draw = ImageDraw.Draw(im)
font = ImageFont.truetype("VeraSe.ttf", 12)
draw.text(
(1, 1),
" %s: " % "ggjyfFwe__",
font=font,
fill='black'
)
draw.text(
(1, 30),
" %s" % 15,
font=font,
fill='black'
)
im.show()
I tried it with a few different fonts, and it always gets clipped. Surprising;y, googleing "PIL font clipping" returns very few useful hits... I'm using python 2.6.4 and PIL 1.1.6 on Ubuntu 9.10
Here's a late answer for this older question.
The problem appears to be that PIL and Pillow will clip the edges of rendered text. This most often shows on trailing wide characters and decenders (like 'y's). This can also appear on the top of some fonts. This has been a problem for at least ten years. It happens regardless of the size of the image on which text()
is called. The conflict appears to choosing the bounding rectangle as "font.size * number_chars" instead of "whatever I actually need to render" and this occurs deep in the stack (_imagingft.c
). Fixing this causes other problems, like lining up text rendered letter by letter.
Some solutions include:
im.text(xy, my_text + ' ', ...)
font.getsize()
), second render the text plus a good ascender and descender, chop the rendered text to the first reported width and the second actual height.This is referenced in various questions fonts clipping with PIL, PIL cuts off top of letters, Properly render text with a given font in Python and accurately detect its boundaries. These questions reference the same underlying issue but are not duplicates
I couldn't solve this problem for some fonts using the approaches mentioned so far, so I ended up using aggdraw as a transparent replacement for PIL's text drawig methods.
Your code rewritten to aggdraw would look like:
import Image
import aggdraw
im = Image.new("RGBA", (200, 200), 'white')
draw = aggdraw.Draw(im)
# note that the color is specified in the font constructor in aggdraw
font = aggdraw.Font((0,0,0), "VeraSe.ttf", size=12, opacity=255)
draw.text((1, 1), " %s: " % "ggjyfFwe__", font) # no color here
draw.text((1, 30), " %s" % 15, font)
draw.flush() # don't forget this to update the underlying PIL image!
im.show()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With