Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ImageFont's getsize() does not get correct text size?

I use the following two methods to to generate text preview image for a .ttf font file

PIL method:

def make_preview(text, fontfile, imagefile, fontsize=30):
    try:
        font = ImageFont.truetype(fontfile, fontsize)
        text_width, text_height = font.getsize(text)
        img = Image.new('RGBA', (text_width, text_height))
        draw = ImageDraw.Draw(img)
        draw.text((0, 0), text, font=font, fill=(0, 0, 0))
        return True
    except:
        return False

ImageMagick method:

def make_preview(text, fontfile, imagefile, fontsize=30):
    p = subprocess.Popen(['convert', '-font', fontfile, '-background',
            'transparent', '-gravity', 'center', '-pointsize', str(fontsize),
            '-trim', '+repage', 'label:%s' % text, image_file])
    return p==0

Both methods create correct preview images most of time but in some rare cases (<2%), the font.getsize(text) just cannot get the correct text size which result in text overflowed provided canvas. ImageMagick has same problem.

Sample fonts and previews:

HANFORD.TTF http://download.appfile.com/HANFORD.png

NEWTOW.TTF http://download.appfile.com/NEWTOW.png

MILF.TTF http://download.appfile.com/MILF.png

SWANSE.TTF http://download.appfile.com/SWANSE.png

I have looked into ImageMagick's documentations and found the explanation of this problem at http://www.imagemagick.org/Usage/text/#overflow.

Is it possible to detect such text overflows and draw text to fit the canvas as we expected?

like image 605
jack Avatar asked Dec 27 '09 07:12

jack


3 Answers

alt text

Not a programming solution, but when I regenerate your problem, its only happens on your fonts (other fonts like Arial is no problem at all), so I have fixed your font files (by changing ascent/decent metrics). you can download here,

And sorry about Hanford Script Font, its not perfect as you see, height seems ok, but left side is not get drawed, its out of my understanding.

UPDATE: Regarding Hanford Font, Here is a work around, pass extra space in text like " Handford Script", and then crop the extra space in image like img=img.crop(img.getbbox())

alt text http://img64.imageshack.us/img64/1903/hanfordfontworkaround.jpg

UPDATE2:I had to pass color=(255,255,255) in Image.New to get Black Text on White background

img = Image.new('RGBA', (text_width, text_height),color=(255,255,255))

alt text

like image 62
YOU Avatar answered Nov 20 '22 03:11

YOU


I had a similar issue once in PHP and ImageMagick.

In the end, I solved this by drawing the text on a very large canvas, and then trimming it using the trim/auto-crop functions that shave extra space off the image.

If I understand your preview function right, it is actually already doing exactly that: It should be enough to just remove the width and height settings.

like image 41
Pekka Avatar answered Nov 20 '22 03:11

Pekka


In this case, just specify ImageMagick to use a larger canvas size with a fixed font size and it will draw text at specified point size while keeping its integrity.

def make_preview(text, fontfile, imagefile, fontsize=30):
    p = subprocess.call(['convert', '-font', fontfile, '-background', 
        'transparent', '-gravity', 'center', '-size', '1500x300',
        '-pointsize', str(fontsize),  '-trim', '+repage', 'label:%s' % text, image_file]) 
    return p==0 

If you need to fit text into specified canvas rather than using a fixed point size, you may need to resize the output image after it's created.

PIL doesn't do this very well drawing exotic fonts, no matter what point size you specify to load a font, it always overflows text outside output image.

like image 1
henry Avatar answered Nov 20 '22 03:11

henry