Skip to content

Instantly share code, notes, and snippets.

@rueycheng
Last active February 12, 2023 14:47
Show Gist options
  • Save rueycheng/56389ff807a9732f9978e661ca3ff556 to your computer and use it in GitHub Desktop.
Save rueycheng/56389ff807a9732f9978e661ca3ff556 to your computer and use it in GitHub Desktop.
Fit multiple 35mm x 45mm passport photos into a 4x6-sized printable format
import argparse
import math
from PIL import Image, ImageDraw
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-o', dest='output_file', required=True, help='output file')
parser.add_argument('input_files', metavar='FILE', nargs='+')
args = parser.parse_args()
def snap(x):
return int(math.ceil(x))
# Load input files and resize all images
img = [Image.open(fname) for fname in args.input_files]
for i in range(1, len(img)):
img[i] = img[i].resize(img[0].size)
# Allocate slots
if len(img) in (1, 2, 4, 8):
rep = int(8 / len(img))
slot = []
for obj in img:
slot.extend([obj] * rep)
else:
print('Can only process 1, 2, or 4 input files')
return
# Assuming input is 35mm x 45mm, target (4x6) will be 101.6mm x 152.4mm in landscape
print('Image size:', img[0].size)
width, height = img[0].size
ppmm = width / 35
new_width, new_height = snap(height / 45 * 152.4), snap(width / 35 * 101.6)
# New image in landscape
new_img = Image.new('RGB', (new_width, new_height), color='white')
print('Target size:', new_img.size)
offset = snap(ppmm)
margin_left = (new_width - 4 * (width + 2*offset)) / 2
margin_top = (new_height - 2 * (height + 2*offset)) / 2
new_draw = ImageDraw.Draw(new_img)
for i in range(4):
for j in range(2):
x = snap(margin_left + offset + i * (width + 2*offset))
y = snap(margin_top + offset + j * (height + 2*offset))
new_img.paste(slot[i+4*j], (x, y))
new_draw.line((x-offset, y-offset, x+width+offset, y-offset), fill='#333333')
new_draw.line((x+width+offset, y-offset, x+width+offset, y+height+offset), fill='#333333')
new_draw.line((x-offset, y+height+offset, x+width+offset, y+height+offset), fill='#333333')
new_draw.line((x-offset, y-offset, x-offset, y+height+offset), fill='#333333')
new_img.save(args.output_file)
print(f'Output saved to {args.output_file}')
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment