2009-12-19 6 views
5

Cette image a été créée avec PIL. Voyez comment les g et les y sont coupés dans cette image? Comment puis-je empêcher cela?découpage de polices avec PIL

http://img109.imageshack.us/img109/8874/screenshotep.png

Le code qui a créé cette image est assez simple (en abrégé):

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() 

Je l'ai essayé avec quelques polices différentes, et il obtient toujours coupé. Surprenant, y, googleing « coupure de police PIL » retourne très quelques coups utiles ... J'utilise python 2.6.4 et 1.1.6 PIL sur Ubuntu 9.10

+0

Mieux nous dire les polices que vous avez essayées, et sur quelle plateforme vous vous trouvez. Je viens d'essayer ici sur Win7 avec consola.ttf et ne pas obtenir l'écrasement d'arrière-plan que vous voyez. –

+0

Malheureusement, je n'ai pas VeraSe.ttf ici, et vous n'avez pas encore indiqué sur quelle plateforme vous vous trouvez. Je soupçonne Linux, pas Windows, et que c'est un problème spécifique à la plate-forme que vous rencontrez. –

+0

Cela se passe aussi pour moi avec georgia.ttf (partie du paquet msttcorefonts) en utilisant PIL 1.1.7 sur Python 2.6 dans Ubuntu 9.10. Il semble que ce soit un problème avec PIL où n'importe quel tampon rendu temporairement n'est pas assez élevé. –

Répondre

0

Ma suggestion est, avant de créer l'objet d'image, à obtenir la taille requise pour le texte. Ceci est effectué en utilisant font.getsize("text") (documentation).

Dans un script de génération d'image que j'ai fait, j'ai trouvé la hauteur maximale d'une ligne de texte, en appelant le equvalient de font.getsize("Åj") (Si vous avez seulement besoin US-ASCII, vous pouvez trouver la hauteur de "Aj" à la place). Ensuite, j'ai calculé la hauteur d'image et les décalages de ligne requis, y compris les marges et l'interlignage.

+0

J'ai déjà essayé quelque chose comme ça. Si la hauteur de la ligne ne suffit pas, PIL chevauchera simplement le texte au lieu de l'écrêter ... – priestc

1

Je ne pouvais pas résoudre ce problème pour certaines polices en utilisant les approches mentionnées jusqu'à présent, donc j'ai fini à l'aide aggdraw en remplacement transparent pour les méthodes de drawig texte de PIL.

Votre code réécrite à aggdraw ressemblerait à ceci:

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() 
+0

Fonctionne! Aggdraw nécessitait cependant des correctifs sous Windows - aggdraw.cxx pour le crash (http://comments.gmane.org/gmane.comp.python.image/1959) et setup.py pour construire avec Freetype2 (en a obtenu un de gnuwin32). – ogurets

0

Le "bug" existe toujours en 2012, avec Ubuntu 11.10. La police de caractères 11, 12, 13 et 15 découpe complètement le trait de soulignement.

#!/usr/bin/env python 
""" demonstrates clipping of descenders for certain font sizes """ 
import Image, ImageDraw, ImageFont 
fontPath = "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf" 
im = Image.new('L', (256, 256)) 
ys=15 
for i in range(10,21): 
    fh = ImageFont.truetype(fontPath, i) 
    sometext="%dgt_}" % (i) 
    ImageDraw.Draw(im).text((10, ys),sometext , 254, fh) 
    ys+=i+5 
im.show() 
+1

Voir ci-dessous pour une alternative en utilisant aggdraw ... –

0

Voici une bidouille qui fonctionne bien pour moi. C'est une variante de la réponse de gnud. (Assez différent pour mériter une réponse séparée par rapport à un commentaire que j'espère.) J'ai testé beaucoup de placements de mots et cela a toujours fonctionné.

Lorsqu'un texte est dessiné sans atteindre la hauteur totale de la police, un écrêtage peut se produire. Comme l'a noté gnud, en utilisant des caractères tels que "Aj" (j'utilise "Fj"), vous évitez ce bug.

Chaque fois qu'un mot est placé:

1) Faites un draw.textsize (texte, police = police) avec votre mot désiré. Stocker la hauteur/largeur.

2) Ajouter 'Fj' (spaceFJ) à la fin du mot, et refaire la taille et mémoriser la troisième hauteur/largeur.

4) Vous ferez le tirage de texte avec le mot de l'article 2 (avec le 'Fj' à la fin). Avoir cet addendum maintiendra la police d'être coupée.

4) Avant de dessiner le texte, rognez l'image où le 'Fj' atterrira (crop.load() est requis pour éviter une copie paresseuse). Dessinez ensuite le texte et passez l'image recadrée sur le 'Fj'.

Ce processus évite l'écrêtage, semble raisonnablement performant et génère le texte complet non découpé. Voici un copier/coller d'une section de code Python que j'utilise pour cela. Exemple partiel, mais j'espère que cela ajoute un peu de perspicacité.

# note: xpos & ypos were previous set = coordinates for text draw 
    #  the hard-coded addition of 4 to c_x likely will vary by font 
    #  (I only use one font in this process, so kludged it.) 
    width, height = draw.textsize(word, font=font) 
    word2 = word + ' Fj' 
    width2, height2 = draw.textsize(word2, font=font) 
    # crop to overwrite ' Fj' with previous image bits 
    c_w = width2 - width 
    c_h = height2 
    c_x = xpos + width + 4 
    c_y = ypos 
    box = (c_x, c_y, c_x + c_w, c_y + c_h) 
    region = img.crop(box) 
    region.load() 
    draw.text((xpos, ypos), word2, (0,0,0), font=font) 
    img.paste(region, box)