Wie würde ich Text bei Verwendung von PIL mittig ausrichten (und mittig vertikal ausrichten)?
python
python-imaging-library
Phillip B. Oldham
quelle
quelle
draw.textsize(msg, font=myFont)
folgt einzuschließen : Andernfalls wird sie nicht richtig zentriertHier ist ein Beispielcode, der Textwrap verwendet, um eine lange Zeile in Teile zu teilen, und dann die
textsize
Methode verwendet, um die Positionen zu berechnen.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')
quelle
width
Zeichen zählt, während PIL-Bilder in Pixel messen. Ich habe eine Version des oben genannten verwendet, aber vor der for-Schleife, die die Zeilen schreibt, eine while-Schleife hinzugefügt. Zuerst habe ich eine beliebig hohe Zeichenanzahl festgelegt, um zu beginnen, dann habe ich Textwrap verwendet, um die Linien zu brechen, und dann habe ich .textsize verwendet, um die Pixelbreite der ersten Ausgabe in der Textwrap-Ergebnisliste zu messen. Wenn es passt, fahren Sie fort, andernfalls verringern Sie meine Zeichenanzahl und messen Sie erneut, bis die Linien zum Bild passen.Man muss beachten, dass die
Draw.textsize
Methode ungenau ist. Ich habe mit Bildern mit niedrigen Pixeln gearbeitet, und nach einigen Tests stellte sich heraus, dasstextsize
jedes Zeichen 6 Pixel breit ist, während ein ZeichenI
max. 2 Pixel und aW
dauert min. 8 Pixel (in meinem Fall). Und so war es, abhängig von meinem Text, überhaupt nicht zentriert. Ich denke, "6" war ein Durchschnitt. Wenn Sie also mit langen Texten und großen Bildern arbeiten, sollte es immer noch in Ordnung sein.Wenn Sie jedoch eine echte Genauigkeit wünschen, verwenden Sie besser die
getsize
Methode des Schriftobjekts, das Sie verwenden möchten :arial = ImageFont.truetype("arial.ttf", 9) w,h = arial.getsize(msg) draw.text(((W-w)/2,(H-h)/2), msg, font=arial, fill="black")
Wie in Edilios Link verwendet.
quelle
getsize
akzeptiert nicht-lateinische Zeichen wie € oder deutsche Umlaute.textsize
nicht. ThumbsUp :-)Die PIL-Dokumente für ImageDraw.text sind ein guter Anfang, aber beantworten Sie Ihre Frage nicht.
Im Folgenden finden Sie ein Beispiel für das Zentrieren des Texts in einem beliebigen Begrenzungsrahmen im Gegensatz zur Bildmitte. Der Begrenzungsrahmen ist definiert als:
(x1, y1)
= obere linke Ecke und(x2, y2)
= untere rechte Ecke.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')
Die Ausgabe zeigt den vertikal und horizontal zentrierten Text im Begrenzungsrahmen .
Ob Sie eine ein- oder mehrzeilige Nachricht haben, spielt keine Rolle mehr, da PIL den
align='center'
Parameter integriert hat. Dies gilt jedoch nur für mehrzeiligen Text . Wenn die Nachricht eine einzelne Zeile ist, muss sie manuell zentriert werden. Wenn die Nachricht mehrzeilig ist,align='center'
erledigt sie die Arbeit für Sie in nachfolgenden Zeilen, aber Sie müssen den Textblock trotzdem manuell zentrieren. Beide Fälle werden im obigen Code sofort gelöst.quelle
Verwenden Sie die
textsize
Methode (siehe Dokumente ), um die Abmessungen Ihres Textobjekts zu ermitteln, bevor Sie es tatsächlich zeichnen. Zeichnen Sie es dann beginnend an den entsprechenden Koordinaten.quelle