Skip to main content

Adventures with Pillow Part 1

I am in the middle of building an app and need to put together several promo videos for Twitter and Instagram, and man it is boring. So I thought 'how can I automate this process?', so welcome to this post.

What I am going for is a selection of images, greyscaled flipping through with our logo on the front. So my approach was to use python, pillow and ffmpeg to build something. This could be disastrous.


To start a few pre-flight checks, a variable for the test image and to check for/create a processed folder for the final images to go.

import os, errno
from PIL import Image, ImageFont, ImageDraw
testImage = 'test.png' cwd = os.getcwd()
image_dir = os.path.join(cwd, 'images')
default_dir = os.path.join(cwd, 'processed')try:
    os.makedirs(default_dir)except OSError as e:
    if e.errno != errno.EEXIST:

I am going to build a function that will do all of the processing, but first going to run on one image before looping through all of the one I need. The first process is to resize image. This is just going to social media promo video so I don't want massive images. I do this simply with the thumbnail method. Using will display the image on your OS, on mac will open in preview.

def processImage(imageFile):
    # Resize image    maxsize = (1000, 1000)
    im =

Next I want to crop out the centre to give me a nice square image. The final square image is gonna be 600px x 600px. The crop function will take the top left corner and crop a box of dimension. I have the latter but to get the start location I will have to get the size of the height of the image, divid by 2 and minus 300px, then the same for the width.

def processImage(imageFile):
    # Resize image    ...

    # Crop center of an image out    halfCropArea = 300
    halfWidth = im.size[0] / 2    halfHeight = im.size[1] / 2    startWidth = halfWidth - halfCropArea
    startHeight = halfHeight - halfCropArea
    cropWidth = halfWidth + halfCropArea
    cropHeight = halfHeight + halfCropArea

    cropped = im.crop((startWidth, startHeight, cropWidth, cropHeight))

Next I need to convert to greyscale. will simply use a convert but will look in to filters another time.

def processImage(imageFile):

    # Apply greyscale    greyscale = cropped.convert('LA')
    img = greyscale.convert('RGB')

Finally to add the logo which is set to 144px square. To set in the middle I set (600 -144)/2 = 228 to top left and then 228 + 144 for bottom right.

def processImage(imageFile):

    # Add icon    iconImage ='icon.png')
    img.paste(iconImage, (228, 228, 228 + 144 , 228 + 144))

Now I am gonna save to the new folder and also added an argument to the function for a new filename.

Movie Time

To get all of the images processed, I am gonna look at the folder with all of the images in and then loop through them. These going to be the frames of my video.

def processFolder():
    images = os.listdir(image_dir)
    for count, image in enumerate(images):
        filename = '%04d.png' % count
        imageFile = os.path.join(image_dir, image)
        print filename, imageFile
        processImage(imageFile, filename)


Inside the directory with my script I have put the ffmpeg library and just run the command form the script.

os.system('./ffmpeg -f image2 -r 2 -i ./processed/%04d.jpg -y -an -vf fps=30 -crf 25 -vcodec libx264 ./processed/video.mp4')

And Voila!!!


Popular posts from this blog

Raspberry Pi Download Machine Part 2

Well SSH is BoringI have got my RPi download machine up and running and having success, unfortunately though SSH is annoying and tedious, so I am gonna do something about it. But a disclaimer; this is my first time working with Aria2 in the most part. RPC  Remote Procedure Call is fancy way of saying 'make this thing make that thing do a thing'. So I ran the command to load the config file (and added to my init file) in the last post and ..... BOLLOCKS ALL.
So ran the command again, and need to check the processes (like Task Manager).
pi@raspberrypi:~ $ ps aux | grep aria2c root       524  0.0  0.9  17028  9284 ?        Ss   21:21   0:00 aria2c --conf-path=/home/pi/.aria2/aria2.conf pi        1008  0.0  0.2   4272  1948 pts/0    S+   21:34   0:00 grep --color=auto aria2c
There it is, that little scumbag. But still no dice. In the conf file I stated that the rpc-port to be 6800 so need to check that port. 
A quick note on ports, every service that runs on your computer and needs a …

Adventures in Pillow Part 2

From my last post where I made a slideshow promo video, I realised how powerful Pillow is. I still have a fair bit of automation to do, so another thing I do a lot of is motivational quotes for Twitter (I am aware they are fucking stupid, but they share well)

The breakdown of the components are a background with a filter, the quote, who said it and our logo.
Background and Filter To start off I am going to create a folder called quote and add in an image and just name it background.jpg (sourced from Pixabay). Next I import PIL and open the file.
from PIL import Image import os, errno cwd = os.getcwd() image_dir = os.path.join(cwd, 'quote') def filterImage(imageFile): im = filterImage(os.path.join(image_dir, 'background.jpg'))

Next I need to crop the image. I am going to take the centre portion out of the image to make square. Like so:
So I start off with getting the dimensions of the image with:
I get a tuple of (1920, 1…