tutorial pil para library for python python-imaging-library

python - para - Centrar/alinear el texto medio con PIL?



pillow python tutorial (6)

¿Cómo centraría-alinearía (y alinearía verticalmente-medio) el texto cuando use PIL?


Aquí hay un código de ejemplo que usa textwrap para dividir una larga línea en partes, y luego usa el método de textsize para calcular las posiciones.

from PIL import Image, ImageDraw, ImageFont import textwrap astr = ''''''The rain in Spain falls mainly on the plains.'''''' para = textwrap.wrap(astr, width=15) MAX_W, MAX_H = 200, 200 im = Image.new(''RGB'', (MAX_W, MAX_H), (0, 0, 0, 0)) draw = ImageDraw.Draw(im) font = ImageFont.truetype( ''/usr/share/fonts/truetype/msttcorefonts/Arial.ttf'', 18) current_h, pad = 50, 10 for line in para: w, h = draw.textsize(line, font=font) draw.text(((MAX_W - w) / 2, current_h), line, font=font) current_h += h + pad im.save(''test.png'')


Los documentos PIL para ImageDraw.text son un buen lugar para comenzar, pero no responden a su pregunta.

A continuación se muestra un ejemplo de cómo centrar el texto en un cuadro delimitador arbitrario, en oposición al centro de una imagen. El cuadro delimitador se define como: (x1, y1) = esquina superior izquierda y (x2, y2) = esquina inferior derecha.

from PIL import Image, ImageDraw, ImageFont # Create blank rectangle to write on image = Image.new(''RGB'', (300, 300), (63, 63, 63, 0)) draw = ImageDraw.Draw(image) message = ''Stuck in/nthe middle/nwith you'' bounding_box = [20, 30, 110, 160] x1, y1, x2, y2 = bounding_box # For easy reading font = ImageFont.truetype(''Consolas.ttf'', size=12) # Calculate the width and height of the text to be drawn, given font size w, h = draw.textsize(message, font=font) # Calculate the mid points and offset by the upper left corner of the bounding box x = (x2 - x1 - w)/2 + x1 y = (y2 - y1 - h)/2 + y1 # Write the text to the image, where (x,y) is the top left corner of the text draw.text((x, y), message, align=''center'', font=font) # Draw the bounding box to show that this works draw.rectangle([x1, y1, x2, y2]) image.show() image.save(''text_center_multiline.png'')

La salida muestra el texto centrado vertical y horizontalmente en el cuadro delimitador .

Ya sea que tenga un mensaje único o multilínea ya no importa, ya que PIL incorporó el parámetro align=''center'' . Sin embargo, es solo para texto de líneas múltiples . Si el mensaje es una sola línea, debe estar centrado manualmente. Si el mensaje es de líneas múltiples, align=''center'' hace el trabajo por usted en las líneas subsiguientes, pero aún tiene que centrar manualmente el bloque de texto. Ambos casos se resuelven a la vez en el código anterior.


Puede encontrar una implementación de esto en http://tools.jedutils.com/tools/center-text-image

Puede usar esa página para crear la imagen allí mismo en lugar de implementarla usted mismo, pero el código utilizado también se incluye en la página.


Se debe tener en cuenta que el método Draw.textsize no es exacto. Estaba trabajando con imágenes de bajo nivel de píxeles, y después de algunas pruebas, resultó que Textize considera que cada personaje tiene 6 píxeles de ancho, mientras que una "I" toma un valor máximo. 2 píxeles y una "W" lleva min. 8 píxeles (en mi caso). Y así, dependiendo de mi texto, estaba o no centrado en absoluto. Sin embargo, supongo que "6" era un promedio, por lo que si está trabajando con textos largos e imágenes grandes, todavía debería estar bien.

Pero ahora, si quieres una precisión real, mejor utilizas el método getsize del objeto fuente que vas a usar:

arial = ImageFont.truetype("arial.ttf", 9) w,h = arial.getsize(msg) draw.text(((W-w)/2,(H-h)/2), msg, font=arial, fill="black")

Como se usa en el enlace de Edilio.


Utilice el método de tamaño de texto (consulte los documentos ) para descubrir las dimensiones de su objeto de texto antes de dibujarlo. Luego, dibuja comenzando en las coordenadas apropiadas.


Use el método Draw.textsize para calcular el tamaño del texto y recalcular la posición en consecuencia.

Aquí hay un ejemplo:

from PIL import Image, ImageDraw W, H = (300,200) msg = "hello" im = Image.new("RGBA",(W,H),"yellow") draw = ImageDraw.Draw(im) w, h = draw.textsize(msg) draw.text(((W-w)/2,(H-h)/2), msg, fill="black") im.save("hello.png", "PNG")

y el resultado:

Si el tamaño de su fuente es diferente, incluya la fuente de esta manera:

myFont = ImageFont.truetype("my-font.ttf", 16) draw.textsize(msg, font=myFont)