-
Notifications
You must be signed in to change notification settings - Fork 45
/
collage_maker.py
118 lines (103 loc) · 4.12 KB
/
collage_maker.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# -*- coding: utf-8 -*-
"""
Collage maker - tool to create picture collages
Author: Delimitry
"""
import argparse
import os
import random
from PIL import Image
def make_collage(images, filename, width, init_height):
"""
Make a collage image with a width equal to `width` from `images` and save to `filename`.
"""
if not images:
print('No images for collage found!')
return False
margin_size = 2
# run until a suitable arrangement of images is found
while True:
# copy images to images_list
images_list = images[:]
coefs_lines = []
images_line = []
x = 0
while images_list:
# get first image and resize to `init_height`
img_path = images_list.pop(0)
img = Image.open(img_path)
img.thumbnail((width, init_height))
# when `x` will go beyond the `width`, start the next line
if x > width:
coefs_lines.append((float(x) / width, images_line))
images_line = []
x = 0
x += img.size[0] + margin_size
images_line.append(img_path)
# finally add the last line with images
coefs_lines.append((float(x) / width, images_line))
# compact the lines, by reducing the `init_height`, if any with one or less images
if len(coefs_lines) <= 1:
break
if any(map(lambda c: len(c[1]) <= 1, coefs_lines)):
# reduce `init_height`
init_height -= 10
else:
break
# get output height
out_height = 0
for coef, imgs_line in coefs_lines:
if imgs_line:
out_height += int(init_height / coef) + margin_size
if not out_height:
print('Height of collage could not be 0!')
return False
collage_image = Image.new('RGB', (width, int(out_height)), (35, 35, 35))
# put images to the collage
y = 0
for coef, imgs_line in coefs_lines:
if imgs_line:
x = 0
for img_path in imgs_line:
img = Image.open(img_path)
# if need to enlarge an image - use `resize`, otherwise use `thumbnail`, it's faster
k = (init_height / coef) / img.size[1]
if k > 1:
img = img.resize((int(img.size[0] * k), int(img.size[1] * k)), Image.LANCZOS)
else:
img.thumbnail((int(width / coef), int(init_height / coef)), Image.LANCZOS)
if collage_image:
collage_image.paste(img, (int(x), int(y)))
x += img.size[0] + margin_size
y += int(init_height / coef) + margin_size
collage_image.save(filename)
return True
def main():
# prepare argument parser
parse = argparse.ArgumentParser(description='Photo collage maker')
parse.add_argument('-f', '--folder', dest='folder', help='folder with images (*.jpg, *.jpeg, *.png)', default='.')
parse.add_argument('-o', '--output', dest='output', help='output collage image filename', default='collage.png')
parse.add_argument('-w', '--width', dest='width', type=int, help='resulting collage image width')
parse.add_argument('-i', '--init_height', dest='init_height', type=int, help='initial height for resize the images')
parse.add_argument('-s', '--shuffle', action='store_true', dest='shuffle', help='enable images shuffle')
args = parse.parse_args()
if not args.width or not args.init_height:
parse.print_help()
exit(1)
# get images
files = [os.path.join(args.folder, fn) for fn in os.listdir(args.folder)]
images = [fn for fn in files if os.path.splitext(fn)[1].lower() in ('.jpg', '.jpeg', '.png')]
if not images:
print('No images for making collage! Please select other directory with images!')
exit(1)
# shuffle images if needed
if args.shuffle:
random.shuffle(images)
print('Making collage...')
res = make_collage(images, args.output, args.width, args.init_height)
if not res:
print('Failed to create collage!')
exit(1)
print('Collage is ready!')
if __name__ == '__main__':
main()