web-dev-qa-db-fra.com

Bibliothèque d'imagerie Python - Rendu du texte

J'essaie de rendre du texte en utilisant PIL, mais le résultat qui en résulte est, franchement, de la merde.

Par exemple, voici un texte que j'ai écrit dans Photoshop:

PhotoShop

et ce qui sort de la LIP:

PIL

Comme vous pouvez le constater, les résultats de la LIP sont moins que satisfaisants. Peut-être suis-je juste un peu difficile, mais existe-t-il un moyen de dessiner un texte à l'aide de PIL qui donne des résultats plus proches de mon image de référence?

Voici le code que j'utilise sur Python 2.7 avec PIL 1.1.7

image = Image.new("RGBA", (288,432), (255,255,255))
usr_font = ImageFont.truetype("resources/HelveticaNeueLight.ttf", 25)
d_usr = ImageDraw.Draw(image)
d_usr = d_usr.text((105,280), "Travis L.",(0,0,0), font=usr_font)
38
exiva

Je suis venu avec ma propre solution que je trouve acceptable.

Ce que j’ai fait, c’est de rendre le texte grand, par exemple 3 fois la taille requise, puis de le redimensionner avec antialiasing, ce n’est pas parfait à 100%, mais c’est beaucoup mieux que le texte par défaut, et il n’exige ni cairo ni Pango.

par exemple,

image = Image.new("RGBA", (600,150), (255,255,255))
draw = ImageDraw.Draw(image)
font = ImageFont.truetype("resources/HelveticaNeueLight.ttf", fontsize)

draw.text((10, 0), txt, (0,0,0), font=font)
img_resized = image.resize((188,45), Image.ANTIALIAS)

et vous vous retrouvez avec ce résultat,

final result

ce qui est beaucoup mieux que ce que je devenais avant avec la même police.

57
exiva

Essayez d'utiliser pycairo - les liaisons Python pour la bibliothèque de dessins Cairo - elles sont utiles pour des dessins plus raffinés, avec des lignes anti-aliasées,

La manipulation correcte des polices et de la mise en page est compliquée et nécessite également l'utilisation de Les bibliothèques "pango" et "pangocairo". Bien qu'ils soient conçus pour des travaux de police sérieux (tous les widgets GTK + utilisent pango pour le rendu des polices), La documentation et les exemples disponibles sont extrêmement médiocres.

L'exemple ci-dessous montre les impressions disponibles dans le système et restitue le texte exemple D'une famille de polices passée en paramètre sur la ligne de commande.

# -*- coding: utf-8 -*-
import cairo
import pango
import pangocairo
import sys

surf = cairo.ImageSurface(cairo.FORMAT_ARGB32, 320, 120)
context = cairo.Context(surf)

#draw a background rectangle:
context.rectangle(0,0,320,120)
context.set_source_rgb(1, 1, 1)
context.fill()

#get font families:

font_map = pangocairo.cairo_font_map_get_default()
families = font_map.list_families()

# to see family names:
print [f.get_name() for f in   font_map.list_families()]

#context.set_antialias(cairo.ANTIALIAS_SUBPIXEL)

# Positions drawing Origin so that the text desired top-let corner is at 0,0
context.translate(50,25)

pangocairo_context = pangocairo.CairoContext(context)
pangocairo_context.set_antialias(cairo.ANTIALIAS_SUBPIXEL)

layout = pangocairo_context.create_layout()
fontname = sys.argv[1] if len(sys.argv) >= 2 else "Sans"
font = pango.FontDescription(fontname + " 25")
layout.set_font_description(font)

layout.set_text(u"Travis L.")
context.set_source_rgb(0, 0, 0)
pangocairo_context.update_layout(layout)
pangocairo_context.show_layout(layout)

with open("cairo_text.png", "wb") as image_file:
    surf.write_to_png(image_file)

Rendred image

19
jsbueno

Je n'ai jamais utilisé PIL, mais un rapide examen de la documentation de la méthode Draw indique que PIL fournit un moyen de rendre des graphiques simple. Photoshop permet de rendre les graphiques complexes. Pour obtenir des résultats proches de ceux de Photoshop, vous devez au minimum disposer d'indications sur les polices et d'anti-aliasing. La documentation de PIL ne suggère même pas de telles capacités. Vous voudrez peut-être utiliser un outil externe qui rendrait mieux le rendu du texte sur les images. Par exemple, ImageMagick (vous voudrez utiliser la version 8 bits, qui gère la norme RVB 24 bits standard). Vous trouverez des exemples de dessins de texte ici: http://www.imagemagick.org/Usage/draw/

11
dave-holm

Suggestion: utilisez Wand ou une autre bibliothèque d'imagerie

Voici un exemple avec baguette -

from wand.color import Color
from wand.image import Image
from wand.drawing import Drawing
from wand.compat import nested

with Drawing() as draw:
    with Image(width=1000, height=100, background=Color('lightblue')) as img:
        draw.font_family = 'Indie Flower'
        draw.font_size = 40.0
        draw.Push()
        draw.fill_color = Color('hsl(0%, 0%, 0%)')
        draw.text(0,int(img.height/2 + 20), 'Hello, world!')
        draw.pop()
        draw(img)
        img.save(filename='image.png')

 image that comes out-

2
Aditya Shankar

Vous pouvez également essayer d'écrire la police deux fois, cela augmente la qualité.

image = Image.new("RGBA", (288,432), (255,255,255))
usr_font = ImageFont.truetype("resources/HelveticaNeueLight.ttf", 25)
d_usr = ImageDraw.Draw(image)
d_usr = d_usr.text((105,280), "Travis L.",(0,0,0), font=usr_font)
d_usr = d_usr.text((105,280), "Travis L.",(0,0,0), font=usr_font)
0
sharpshadow