So recently I’ve been wanting to create a years worth of images with quotes from famous people and then schedule them on various social media for a few different pet projects of mine. Please note that I’m not at all a professional developer, so experienced developers, please brace yourselves.
This post will provide a working example of a very simple, yet powerful enough Python image batch script using Pillow, that iterate through stock images, and combine them with famous quotes and authors from CSV files.
At the end of this tutorial, you can generate hundreds or thousands of unique images with added quotes and their respective authors. I also add support for embedding custom graphics and or optional text for company logos or websites, so you can further customize to your needs.
And last but not least I show off the opacity function for overlays, separating the quote texts from the backgrounds.
What you will end up with, could be something like this.
I might update the code later with an added transparent image overlay containing a few swirls and lines to give the image a bit more panache, but the main purpose is to show you how to generate images in batch, not give a lesson in design.
As of writing, there are some issues with the functionality of the code, such as some text being incorrectly padded like this:
Another quite big issue is the fact that the first line is set to simply just use a fixed width, meaning that for quotes particularly, oftentimes it just looks wrong, such as this one:
As I’m not using this script for anything, I doubt I’ll get around to updating it, but I mention it as I hope someone might comment with a quick solution.
It should also be noted that I by no means encourage you to just use this code as I am neither a professional developer, nor am I read up on any theory regarding best practices. (Read: the code is
most likely horrible)
So, first we need an installation of Python, I use the lastest version. So create a folder named after you liking, this folder will contain the entire script, including folders for images and CSV files.
Create your main script, name it whatever you like, I will just refer to this as:
import PIL import csv import textwrap from PIL import ImageFont from PIL import Image from PIL import ImageDraw
First few lines are importing and assigning the libraries we need, namely Pillow, csv and textwrap. If you are new to Python and the above lines are throwing an error, look into package managers, and install the needed modules.
The way I have structured things in this script are as follows:
The authors and quotes are split up for my own benefit, as I originally wrote this script for movie quotes where I needed to link various data from 2 separate files. I’ve left it like this, since it might provide some additional functionality that would otherwise be left out. Feel free to change it.
The folder called /in/, are simply containing a list of JPG’s that I’ve downloaded from various CC0 image archive sites, such as Pexels and Pixabay.
The folder called /out/ are used to store the newly generated images.
I then run a simple windows .bat file thats simply located inside the /in/ folder to rename all files to my liking. This way I could even match up quote #4 with image #4 if I wished to.
@echo off ren *.jpeg *.jpg setlocal EnableDelayedExpansion set i=0 for %%a in (*.jpg) do ( ren "%%a" "!i!.new" set /a i+=1 ) ren *.new *.jpg
As you can see, both CSV files are simply separated by line breaks.
This is the first time I write a tutorial that covers more than a few lines of code, so I hope you can bear with my bad commenting, and even worse quality of code and formatting. Below is the full script.
#BIMP - Batch Image Manipulating with Python """ Author; Mark Pedersen @makerspender License: CC BY 2.0 https://creativecommons.org/licenses/by/2.0/ """ #load required libraries import PIL import csv import textwrap from PIL import ImageFont from PIL import Image from PIL import ImageDraw #create lists to store quotes and authors in lines = [line.rstrip() for line in open('quotes.csv')] authors = [author.rstrip() for author in open('authors.csv')] #start the for loop for idx, val in enumerate(lines): #echo each quote and author print(idx, val) #create main quote value para = textwrap.wrap(val, width=40) #set image dimensions MAX_W, MAX_H = 1920, 1280 #set image location imageFile = "D:\imgapp\in\%s.jpg" %idx #assign im to pillow and open the image im = Image.open(imageFile).convert('RGBA') #resize the image to our chosen proportions and use antialiasing im = im.resize((1920, 1280), Image.ANTIALIAS) #create new layer for adding opacity poly = Image.new('RGBA', (1920,1280)) polydraw = ImageDraw.Draw(poly) #fill the image with black and 165/255 opacity polydraw.rectangle([(0,0),(1920,1280)], fill=(0,0,0,165), outline=None) #paste in the layer on top of the image im im.paste(poly,mask=poly) #command to start merging layers draw = ImageDraw.Draw(im) #setting up fonts font = ImageFont.truetype("C:\Windows\Fonts\ArchivoBlack-Regular.ttf",80) authorfont = ImageFont.truetype("C:\Windows\Fonts\Roboto-BlackItalic.ttf",60) linkfont = ImageFont.truetype("C:\Windows\Fonts\Roboto-Black.ttf",24) #setting up padding and positioning for quote text current_h, pad = 300, 50 #for loop breaking up each quote into lines not exceeding the width of the image dimensions 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 #setting up padding and positioning for author text current_h2, pad2 = 900, 80 currentauthor = authors[idx] w, h = draw.textsize(currentauthor, font=authorfont) draw.text(((MAX_W - w) / 2, (current_h + 100)), currentauthor, font=authorfont) current_h2 += h + pad2 #setting up padding and positining for optional text current_h3, pad3 = 1200, 30 sitelink = "Batch Image Manipulating with Python" w, h = draw.textsize(sitelink, font=linkfont) draw.text(((MAX_W - w) / 2, current_h3), sitelink, font=linkfont) current_h3 += h + pad3 #loading optional logo and converting to RGBA for transparency support logo = Image.open('logo.png').convert('RGBA') logo_w, logo_h = logo.size im.paste(logo, (50,1150), logo) #saving the image to our chosen location im.save("D:\imgapp\out\image_%d.jpg" %idx)
I’ve used the official pillow documentation extensively, and while I had an idea that there would be plenty of tutorials out there offering a quick and better solution than the one I came up with, I couldn’t find any complete package.
So while the above code is neither pretty nor optimal, it works for the intended purpose, and hopefully can serve as inspiration or a bootstrap for your own projects.
Please let me know in the comments whether I’ve made a giant error, if you have updates, fixes or wishes for new features.