your recognition pil not installed imagedraw python image text python-imaging-library

recognition - python PIL dibuja texto multilínea en la imagen



pillow python (5)

La respuesta aceptada envuelve el texto sin medir la fuente (máximo 40 caracteres, sin importar el tamaño de la fuente y el ancho de la caja), por lo que los resultados son solo aproximados y pueden sobrellenar o llenar poco la casilla.

Aquí hay una biblioteca simple que resuelve el problema correctamente: https://gist.github.com/turicas/1455973

Intento agregar texto en la parte inferior de la imagen y en realidad lo he hecho, pero en caso de que mi texto sea más largo, el ancho de la imagen se corta por ambos lados, para simplificar. Me gustaría que el texto estuviera en varias líneas si es más largo que el ancho de la imagen. Aquí está mi código:

FOREGROUND = (255, 255, 255) WIDTH = 375 HEIGHT = 50 TEXT = ''Chyba najwyższy czas zadać to pytanie na śniadanie /n Chyba najwyższy czas zadać to pytanie na śniadanie'' font_path = ''/Library/Fonts/Arial.ttf'' font = ImageFont.truetype(font_path, 14, encoding=''unic'') text = TEXT.decode(''utf-8'') (width, height) = font.getsize(text) x = Image.open(''media/converty/image.png'') y = ImageOps.expand(x,border=2,fill=''white'') y = ImageOps.expand(y,border=30,fill=''black'') w, h = y.size bg = Image.new(''RGBA'', (w, 1000), "#000000") W, H = bg.size xo, yo = (W-w)/2, (H-h)/2 bg.paste(y, (xo, 0, xo+w, h)) draw = ImageDraw.Draw(bg) draw.text(((w - width)/2, w), text, font=font, fill=FOREGROUND) bg.show() bg.save(''media/converty/test.png'')


Podría usar PIL.ImageDraw.Draw.multiline_text() .

draw.multiline_text((WIDTH, HEIGHT), TEXT, fill=FOREGROUND, font=font)

Incluso establece spacing o align con los mismos nombres de param.


Puede usar textwrap.wrap para dividir el text en una lista de cadenas, cada una con la mayor cantidad de caracteres de width :

import textwrap lines = textwrap.wrap(text, width=40) y_text = h for line in lines: width, height = font.getsize(line) draw.text(((w - width) / 2, y_text), line, font=font, fill=FOREGROUND) y_text += height


Todas las recomendaciones sobre el uso de textwrap no determinan el ancho correcto para fuentes no monoespaciadas (como Arial, que se usa en el código de ejemplo de tema).

Escribí una clase de ayuda simple para ajustar el texto con respecto al tamaño real de las letras de las fuentes:

class TextWrapper(object): """ Helper class to wrap text in lines, based on given text, font and max allowed line width. """ def __init__(self, text, font, max_width): self.text = text self.text_lines = [ '' ''.join([w.strip() for w in l.split('' '') if w]) for l in text.split(''/n'') if l ] self.font = font self.max_width = max_width self.draw = ImageDraw.Draw( Image.new( mode=''RGB'', size=(100, 100) ) ) self.space_width = self.draw.textsize( text='' '', font=self.font )[0] def get_text_width(self, text): return self.draw.textsize( text=text, font=self.font )[0] def wrapped_text(self): wrapped_lines = [] buf = [] buf_width = 0 for line in self.text_lines: for word in line.split('' ''): word_width = self.get_text_width(word) expected_width = word_width if not buf else / buf_width + self.space_width + word_width if expected_width <= self.max_width: # word fits in line buf_width = expected_width buf.append(word) else: # word doesn''t fit in line wrapped_lines.append('' ''.join(buf)) buf = [word] buf_width = word_width if buf: wrapped_lines.append('' ''.join(buf)) buf = [] buf_width = 0 return ''/n''.join(wrapped_lines)

Ejemplo de uso:

wrapper = TextWrapper(text, image_font_intance, 800) wrapped_text = wrapper.wrapped_text()

Probablemente no sea súper rápido, ya que procesa el texto completo palabra por palabra para determinar el ancho de las palabras. Pero para la mayoría de los casos, debería estar bien.


text = textwrap.fill("test ",width=35) self.draw.text((x, y), text, font=font, fill="Black")