Skip to content

Instantly share code, notes, and snippets.

@tjibbevanderlaan
Last active March 29, 2023 19:39
Show Gist options
  • Save tjibbevanderlaan/00a662f8fc8341d8e3e99314a5cd5fae to your computer and use it in GitHub Desktop.
Save tjibbevanderlaan/00a662f8fc8341d8e3e99314a5cd5fae to your computer and use it in GitHub Desktop.
Create collages of 4 photos each in a 2x2 grid for all photos in current folder where the collage is 100x150mm in size with 300dpi saved as jpg
#!/usr/bin/env python3
import os
import glob
import subprocess
# this script needs imagemagick and can be installed with the following command on MacOS:
# brew install imagemagick
# is_landscape checks whetherimage file is landscape oriented. Returns true or false
def is_landscape(filename):
command = ['identify', '-format', '%[orientation] %[w] %[h]', filename]
output = subprocess.check_output(command)
orientation, width, height = output.decode().split()
return (orientation == 'TopLeft' and int(width) > int(height))
# Creates a 100x150 mm collage photo at 300 dpi and saves it as a jpeg. As parameters,
# 1) 4 photo files in a list and 2) an index of the first photo file must be specified.
# The index is used for the name of the collage file.
def create_collage(input_files, index=0):
# check if all photos are in landscape orientation, if so, create landscape collage
# if not create portrait collage
landscape = all(is_landscape(filename) for filename in input_files)
edge_a = 886 # 150 mm with 300 dpi is 1772 pixels. Divide by 2 to get cell edge length
edge_b = 590 # 100 mm with 300 dpi is 1181 pixels. Divide by 2 to get cell edge length
# Calculate the size of each cell in the collage
cell_width = edge_a if landscape else edge_b
cell_height = edge_b if landscape else edge_a
# Create the command to crop and resize each photo to fit a cell
command_template = "convert {input_file} -auto-orient -resize {width}x{height}^ -gravity center -extent {width}x{height} {output_file}"
# Create a list to store the output file names
output_files = []
# Process each input photo
for i, input_file in enumerate(input_files):
# Create a unique output file name for this cell
output_file = f"collage/tmp/cell{i+1}.jpg"
# Execute the command to crop and resize the photo
command = command_template.format(
input_file=input_file,
width=cell_width,
height=cell_height,
output_file=output_file)
subprocess.run(command, shell=True, check=True)
# Add the output file name to the list
output_files.append(output_file)
# Create the command to assemble the cells into a 2x2 grid
output_filename = 'collage/collage-' + str(index) + '-' + str(index+4) + '.jpg'
command = "montage -tile 2x2 -geometry +0+0 {} {}".format(" ".join(output_files), output_filename)
# Execute the command to assemble the cells
subprocess.run(command, shell=True, check=True)
# Find all jpeg photos in current working directory. This function creates collages for each
# group of four photos. The collages are saved in a 'collage'-folder.
def create_collages():
# Get all .jpeg or .jpg files in the current working directory
jpg_files = glob.glob("*.jpeg") + glob.glob("*.jpg") + glob.glob("*.JPG") + glob.glob("*.JPEG")
# Check if there are any jpeg files found, otherwise stop
if len(jpg_files) <= 0:
return
# Specify the directory and temporary path
directory_path = "./collage"
tmp_directory_path = "./collage/tmp"
# Create the directory if it doesn't already exist
if not os.path.exists(directory_path):
os.makedirs(directory_path)
if not os.path.exists(tmp_directory_path):
os.makedirs(tmp_directory_path)
# Sort the images alphabetically. This make sure that photos are
# grouped in a collage in sequential order
sorted_images = sorted(jpg_files)
# Create groups with 4 photos each. Please note that the current working directory
# must contain a multiple of 4 photos in order for each photo to end up in a collage
for i in range(0, len(sorted_images), 4):
group = sorted_images[i:i+4]
if(len(group) == 4):
print(group)
create_collage(group, i)
if __name__ == "__main__":
create_collages()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment