recorte de fonts con PIL

Esta imagen fue creada con PIL. ¿Ves cómo se cortan las g y las y en esta imagen? ¿Cómo puedo prevenir esto?

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

El código que creó esta imagen es bastante sencillo (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() 

Lo probé con algunas fonts diferentes, y siempre se recorta. Sorprendente; y, el “clipping de fuente PIL” de Googleing devuelve muy pocos resultados útiles … Estoy usando python 2.6.4 y PIL 1.1.6 en Ubuntu 9.10

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

    Tu código reescrito en 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() 

    Aquí hay una respuesta tardía para esta pregunta anterior.

    El problema parece ser que PIL y Pillow recortarán los bordes del texto renderizado. Esto se muestra con mayor frecuencia en los caracteres anchos y los defensores finales (como ‘y’s). Esto también puede aparecer en la parte superior de algunas fonts. Esto ha sido un problema durante al menos diez años. Ocurre independientemente del tamaño de la imagen en la que se llama a text() . El conflicto parece elegir el rectángulo delimitador como “font.size * number_chars” en lugar de “todo lo que necesito renderizar” y esto ocurre en la stack ( _imagingft.c ). Arreglar esto causa otros problemas, como alinear el texto representado letra por letra.

    Algunas soluciones incluyen:

    • Añade un espacio al final de tu cadena. im.text(xy, my_text + ' ', ...)
    • Para problemas de altura, obtenga el ancho de su texto ( font.getsize() ), haga una segunda presentación del texto más un buen ascendente y descendente, corte el texto representado en la primera anchura reportada y la segunda altura real.
    • Utilice una biblioteca diferente, como AggDraw o pyvips .

    A esto se hace referencia en varias preguntas sobre el recorte de fonts con PIL , PIL corta la parte superior de las letras , representa correctamente el texto con una fuente dada en Python y detecta con precisión sus límites . Estas preguntas hacen referencia al mismo problema subyacente pero no son duplicados

    El “error” todavía existe en 2012, con Ubuntu 11.10. Fontsize 11, 12, 13 y 15 recortan el subrayado 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() 

    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") ( documentación ).

    En una secuencia de comandos de generación de imágenes que realicé, primero encontré la altura máxima de una línea de texto, llamando al mismo valor de font.getsize("Åj") (Si solo necesita US-ASCII, puede encontrar la altura de "Aj" lugar). Luego calculé la altura de la imagen requerida y las desviaciones de línea, incluidos los márgenes y el interlineado.

    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 por separado frente a un comentario, espero). He probado muchas ubicaciones de palabras y esto se ha realizado de manera consistente.

    Cuando se dibuja un texto sin llegar a la altura completa de la fuente, se puede producir un recorte. Como señaló gnud, al usar caracteres como “Aj” (yo uso “Fj”) se evita este error.

    Cada vez que se coloca una palabra:

    1) Haz un draw.textsize (texto, fuente = fuente) con tu palabra deseada. Almacenar la altura / anchura.

    2) Agregue ‘Fj’ (espacioFJ) al final de la palabra, vuelva a hacer el tamaño del texto y guárdelo en la tercera altura / anchura.

    4) Dibujará el texto real con la palabra del elemento 2 (con la ‘Fj’ al final). Tener este addendum evitará que la fuente se recorte.

    4) Antes de realizar el dibujo del texto real, recorte la imagen donde aterrizará el ‘Fj’ (se requiere crop.load () para evitar una copia perezosa). Luego dibuje el texto y vuelva a pasar la imagen recortada sobre el ‘Fj’.

    Este proceso evita el recorte, parece tener un rendimiento razonable y produce el texto completo, sin recortar. A continuación se muestra una copia / pegado de una sección del código Python que uso para esto. Ejemplo parcial, pero ojalá agregue alguna idea.

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