Text automatisiert in Bilder einfügen mit Python
Da ich für diesen Blog einige Beiträge vorab schreibe und diese entsprechend plane, hatte ich immer wieder das Problem, dass ich Bilder „manuell“ bearbeiten musste. Durch die manuelle Bearbeitung der Titelbilder war auch teilweise keine Linie vorhanden, um damit den Wiedererkennungswert zu gewährleisten.
Zusätzlich dazu brauchte ich auch immer ein Bildbearbeitungsprogramm, wofür ich aber auch nicht mehr bereit war zu bezahlen, da ich wirklich nur Grundfunktionen nutze, wie z.B. eine neue Ebene mit Text zu erstellen.
Warum das ganze?
Da ich mich durch andere Projekte (Internet-Speed- / Bandbreiten-Messung mit Python oder Automatische Firmware-Updates für Microcontroller mit Gitlab und PlatformIO) bereits etwas mit Python beschäftigt habe, lag die Überlegung nahe, die Bearbeitung gänzlich zu automatisieren. Dadurch bekomme ich zum Einen eine einheitliche Linie in die Titelbilder (selbe Schriftart, Position, Aufmachung) und muss mich auch nur noch um das nötigste kümmern, nämlich nur noch das Aussuchen des Bildes.
Der Code
Der Code ist recht einfach und verständlich. Für die Bearbeitung der Bilder nutze ich die Python-Library „PIL„, womit man recht elegant einfache (auch bis hin zu komplizierten) Bearbeitungen durchführen kann. Diese muss natürlich vorab installiert werden mit pip install pil
bzw. gemäß der Doku.
Den Code habe ich weitestgehend dokumentiert, wo es nötig war. Ansonsten ist er recht selbsterklärend. Solltest du dennoch Fragen haben, schreib es mir einfach in den Kommentaren!
from PIL import Image, ImageDraw, ImageFont import os import re # settings source_image = "images/pexels-photo-442573.jpeg" txt = "Text automatisiert in Bilder"+os.linesep+"einfügen mit Python" txt_color = "white" fontsize = 1 fontfile = "font/LuckiestGuy.ttf" border = True border_color = "black" border_size = 5 output_dir = "output" text_alignment = "center" # portion of image width you want text width to be img_fraction = 1 # line_height = 0 line_width = 0 # generating images image = Image.open(source_image).convert('RGBA') image_with_text = Image.new('RGBA', image.size, (255,255,255,0)) draw = ImageDraw.Draw(image_with_text) # initial position of the text font_pos_x = 0 font_pos_y = 0 # getting font font = ImageFont.truetype("arial.ttf", fontsize) # caluclate position of text (centered) image_width = image.size[0] image_height = image.size[1] print("Image height: "+str(image_height)) print("Image width: "+str(image_width)) # getting the perfect size of the fraction of teh text to fit in the image while (font.getsize(txt)[0] < img_fraction*image.size[0]): fontsize += 1 font = ImageFont.truetype(fontfile, fontsize) # check if there is a new line terminator if txt.find(os.linesep) >= 0: print("New line found. Checking longest line width") lines = txt.split(os.linesep) for line in lines: # find the longest line if(font.getsize(line)[0] > line_width): line_width = font.getsize(line)[0] line_height += font.getsize(line)[1] else: line_width = font.getsize(txt)[0] line_height = font.getsize(txt)[1] # calculating text position font_pos_x = (image_width - line_width) / 2 font_pos_y = (image_height - line_height) / 2 # optionally de-increment to be sure it is less than criteria fontsize -= 1 font = ImageFont.truetype(fontfile, fontsize) print("Final font size: ",fontsize) # applying border if needed if(border): print("Applying border ",fontsize) draw.text((font_pos_x-border_size, font_pos_y-border_size), txt, font=font, fill=border_color, align=text_alignment) draw.text((font_pos_x+border_size, font_pos_y-border_size), txt, font=font, fill=border_color, align=text_alignment) draw.text((font_pos_x-border_size, font_pos_y+border_size), txt, font=font, fill=border_color, align=text_alignment) draw.text((font_pos_x+border_size, font_pos_y+border_size), txt, font=font, fill=border_color, align=text_alignment) # draw text to image draw.text((font_pos_x, font_pos_y), txt, font=font, fill=txt_color, align=text_alignment) # put the text on the image # overlay text layer with the picture out = Image.alpha_composite(image, image_with_text) # show image out.show() # save image file_name = re.sub(r"[^a-zA-Z0-9 | ]*","", txt).replace(" ", "_")+'.png' out.save(os.path.join(output_dir, file_name)) # save it
Den gesamten Code bzw. das Projekt findest du in meinem GitHub: