2009-12-19 18 views
5

Esta imagen se ha creado con PIL. ¿Ve cómo se cortan las g y las y en esta imagen? ¿Cómo puedo prevenir esto?recorte de fuentes con PIL

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

El código que creó esta imagen es bastante simple (abreviado):

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

he probado con un par de fuentes diferentes, y siempre se recorta. Sorprendente; y, googleing "Recorte de fuentes PIL" devuelve muy pocos hits útiles ... Estoy usando Python 2.6.4 y PIL 1.1.6 en Ubuntu 9.10

+0

Mejor díganos las fuentes específicas que ha probado y la plataforma en la que se encuentra. Acabo de probar aquí en Win7 con consola.ttf y no sobreescribo el fondo que ves. –

+0

Desafortunadamente no tengo VeraSe.ttf aquí, y aún no me has mencionado en qué plataforma estás. Sospecho que Linux, no Windows, y que este es un problema específico de la plataforma que está teniendo. –

+0

Esto también me está sucediendo con georgia.ttf (parte del paquete msttcorefonts) usando PIL 1.1.7 en Python 2.6 en Ubuntu 9.10. Parece que hay un problema con el PIL, donde el búfer al que temporalmente rinde no es lo suficientemente alto. –

Respuesta

0

Mi sugerencia es, antes de crear el objeto de imagen, obtener el tamaño requerido para el texto.

Esto se hace usando font.getsize("text") (documentation).

En una secuencia de comandos de generación de imágenes que hice, me encontré por primera vez la altura máxima de una línea de texto, llamando al equvalient de font.getsize("Åj") (Si sólo necesita US-ASCII, se puede encontrar la altura de "Aj" en su lugar). Luego calculé la altura de imagen requerida y los desplazamientos de línea, incluidos los márgenes y el espaciado de línea.

+0

Ya intenté algo así. Si la altura de la línea no es suficiente, PIL simplemente superpondrá el texto en lugar de recortarlo ... – priestc

1

No pude resolver este problema para algunas fuentes utilizando los enfoques mencionados hasta ahora, así que terminé usando aggdraw como un reemplazo transparente para los métodos de dibujo de texto de PIL.

Su código reescrito para aggdraw se vería así:

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

¡Funciona! Sin embargo, Aggdraw requirió algunos parches en Windows: aggdraw.cxx para el bloqueo (http://comments.gmane.org/gmane.comp.python.image/1959) y setup.py para compilar con Freetype2 (se obtuvo uno de gnuwin32). – ogurets

0

El "error" todavía existe en el año 2012, con Ubuntu 11.10. Fontsize 11, 12, 13 y 15 recortan el guión bajo por completo.

#!/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

Vea a continuación una alternativa usando aggdraw ... –

0

Aquí hay un kludge que funciona bien para mí. Es una variante de la respuesta de gnud. (Lo suficientemente diferente como para merecer una respuesta separada vs. comentario, espero.) He probado muchas ubicaciones de palabras y esto ha funcionado de manera consistente.

Cuando se dibuja un texto sin alcanzar completamente la altura de la fuente, puede producirse un recorte. Como notó gnud, al usar caracteres como "Aj" (yo uso "Fj") evitas este error.

Cada vez que se coloca una palabra:

1) Haz una draw.textsize (texto, fuente = fuente) con su palabra deseada. Almacenar el alto/ancho.

2) Agregue 'Fj' (spaceFJ) al final de la palabra, y vuelva a hacer el tamaño de texto y almacene el tercer alto/ancho.

4) Hará el dibujo de texto real con la palabra del ítem 2 (con el 'Fj' al final). Tener este apéndice evitará que la fuente se recorta.

4) Antes de hacer el dibujo de texto real, recorte la imagen donde aterrizará el 'Fj' (crop.load() es necesario para evitar una copia floja). Luego dibuja el texto y pasa la imagen recortada sobre el 'Fj'.

Este proceso evita el recorte, parece razonablemente efectivo y produce el texto completo, sin recortar. A continuación se muestra una copia/pega de una sección del código de Python que uso para esto. Ejemplo parcial, pero con un poco de suerte, agrega algunas ideas.

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