Spaces:
Runtime error
Runtime error
File size: 5,033 Bytes
c19ca42 |
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 119 120 121 122 123 124 125 126 127 128 129 |
#!/usr/bin/env python
"""
Create image grid
"""
import os
import argparse
import math
import logging
from pathlib import Path
import filetype
from PIL import Image, ImageDraw, ImageFont
from util import log
params = None
def wrap(text: str, font: ImageFont.ImageFont, length: int):
lines = ['']
for word in text.split():
line = f'{lines[-1]} {word}'.strip()
if font.getlength(line) <= length:
lines[-1] = line
else:
lines.append(word)
return '\n'.join(lines)
def grid(images, labels = None, width = 0, height = 0, border = 0, square = False, horizontal = False, vertical = False): # pylint: disable=redefined-outer-name
if horizontal:
rows = 1
elif vertical:
rows = len(images)
elif square:
rows = round(math.sqrt(len(images)))
else:
rows = math.floor(math.sqrt(len(images)))
cols = math.ceil(len(images) / rows)
size = [0, 0]
if width == 0:
w = max([i.size[0] for i in images])
size[0] = cols * w + cols * border
else:
size[0] = width
w = round(width / cols)
if height == 0:
h = max([i.size[1] for i in images])
size[1] = rows * h + rows * border
else:
size[1] = height
h = round(height / rows)
size = tuple(size)
image = Image.new('RGB', size = size, color = 'black') # pylint: disable=redefined-outer-name
font = ImageFont.truetype('DejaVuSansMono', round(w / 40))
for i, img in enumerate(images): # pylint: disable=redefined-outer-name
x = (i % cols * w) + (i % cols * border)
y = (i // cols * h) + (i // cols * border)
img.thumbnail((w, h), Image.Resampling.HAMMING)
image.paste(img, box=(x + int(border / 2), y + int(border / 2)))
if labels is not None and len(images) == len(labels):
ctx = ImageDraw.Draw(image)
label = wrap(labels[i], font, w)
ctx.text((x + 1 + round(w / 200), y + 1 + round(w / 200)), label, font = font, fill = (0, 0, 0))
ctx.text((x, y), label, font = font, fill = (255, 255, 255))
log.info({ 'grid': { 'images': len(images), 'rows': rows, 'cols': cols, 'cell': [w, h] } })
return image
if __name__ == '__main__':
log.info({ 'create grid' })
parser = argparse.ArgumentParser(description='image grid utility')
parser.add_argument("--square", default = False, action='store_true', help = "create square grid")
parser.add_argument("--horizontal", default = False, action='store_true', help = "create horizontal grid")
parser.add_argument("--vertical", default = False, action='store_true', help = "create vertical grid")
parser.add_argument("--width", type = int, default = 0, required = False, help = "fixed grid width")
parser.add_argument("--height", type = int, default = 0, required = False, help = "fixed grid height")
parser.add_argument("--border", type = int, default = 0, required = False, help = "image border")
parser.add_argument('--nolabels', default = False, action='store_true', help = "do not print image labels")
parser.add_argument('--debug', default = False, action='store_true', help = "print extra debug information")
parser.add_argument('output', type = str)
parser.add_argument('input', type = str, nargs = '*')
params = parser.parse_args()
output = params.output if params.output.lower().endswith('.jpg') else params.output + '.jpg'
if params.debug:
log.setLevel(logging.DEBUG)
log.debug({ 'debug': True })
log.debug({ 'args': params.__dict__ })
images = []
labels = []
for f in params.input:
path = Path(f)
if path.is_dir():
files = [os.path.join(f, file) for file in os.listdir(f) if os.path.isfile(os.path.join(f, file))]
elif path.is_file():
files = [f]
else:
log.warning({ 'grid not a valid file/folder', f})
continue
files.sort()
for file in files:
if not filetype.is_image(file):
continue
if file.lower().endswith('.heic'):
from pi_heif import register_heif_opener
register_heif_opener()
log.debug(file)
img = Image.open(file)
# img.verify()
images.append(img)
fp = Path(file)
if not params.nolabels:
labels.append(fp.stem)
# log.info({ 'folder': path.parent, 'labels': labels })
if len(images) > 0:
image = grid(
images = images,
labels = labels,
width = params.width,
height = params.height,
border = params.border,
square = params.square,
horizontal = params.horizontal,
vertical = params.vertical)
image.save(output, 'JPEG', optimize = True, quality = 60)
log.info({ 'grid': { 'file': output, 'size': list(image.size) } })
else:
log.info({ 'grid': 'nothing to do' })
|