Skip to content

Instantly share code, notes, and snippets.

@markusfisch markusfisch/
Last active Jan 2, 2020

What would you like to do?
Make a collage in shape of 2019 of your best shots of the year

Year In Pictures

Take your best picture of this year, put them into a folder and run this script:


You'll get a collage in shape of 2019 where the digits are made from your pictures:



You'll need to have Pillow:

$ pip3 install Pillow

Fix EXIF Orientation

Digital cameras often store pictures in camera orientation and just save a possibly deviating orientation with it. When the picture is displayed, it is rotated accordingly (see EXIF for details).

Pillow doesn't evaluate that EXIF orientation out of the box but provides an additional function for this: ImageOps.exif_transpose(). Unfortunately, this function failed quite often for me.

So, to fix this, I used Image Magick's mogrify to rotate the pictures into their intended orientation:

$ mogrify -auto-orient IMAGE_FILES...
#!/usr/bin/env python3
from PIL import Image, ImageOps
from random import shuffle
import os
import sys
def year_in_pictures(template, outfile, srcdir='.'):
images = []
for f in os.listdir(srcdir):
if f.endswith('.jpg'):
images.append(os.path.join(srcdir, f))
if len(images) < 1:
sys.stderr.write('error: no JPG images found in %s\n' % (srcdir, ))
lines = template.split('\n')
width = len(max(lines))
height = len(lines)
cellSize = 320
width *= cellSize
height *= cellSize
canvas ='RGB', (width, height))
i = 0
y = 0
x = 0
for line in lines:
for ch in line:
if ch == 'X':
im = ImageOps.exif_transpose(
images[i % len(images)]
i += 1
(w, h) = im.size
scale = max(cellSize / w, cellSize / h)
w = round(w * scale)
h = round(h * scale)
im = im.resize((w, h), resample=Image.BICUBIC).crop(
(0, 0, cellSize, cellSize)
canvas.paste(im, (x, y))
x += cellSize
x = 0
y += cellSize, quality=95)
template = """
year_in_pictures(template, '2019.jpg', * sys.argv[1:])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.