Let stitch take --grid AxB.

This commit is contained in:
voussoir 2022-04-05 10:48:08 -07:00
parent 9f53f1c514
commit f822d000af
No known key found for this signature in database
GPG key ID: 5F7554F8C26DACCB

View file

@ -17,29 +17,55 @@ def stitch_argparse(args):
patterns = pipeable.input_many(args.image_files, skip_blank=True, strip=True) patterns = pipeable.input_many(args.image_files, skip_blank=True, strip=True)
files = pathclass.glob_many_files(patterns) files = pathclass.glob_many_files(patterns)
images = [PIL.Image.open(file.absolute_path) for file in files] images = [PIL.Image.open(file.absolute_path) for file in files]
if args.vertical:
direction = VERTICAL if args.grid:
(grid_x, grid_y) = [int(part) for part in args.grid.split('x')]
if grid_x * grid_y < len(images):
pipeable.stderr(f'Your grid {grid_x}x{grid_y} is too small for {len(images)} images.')
return 1
elif args.vertical:
grid_x = 1
grid_y = len(images)
else: else:
direction = HORIZONTAL grid_x = len(images)
grid_y = 1
gapcount = len(images) - 1 # We produce a 2D list of images which will become their final arrangement,
# and calculate the size of each row and column to accommodate the largest
if direction is HORIZONTAL: # member of each.
width = sum(i.size[0] for i in images) + (gapcount * args.gap) arranged_images = [[] for y in range(grid_y)]
height = max(i.size[1] for i in images) column_widths = [1 for x in range(grid_x)]
else: row_heights = [1 for x in range(grid_y)]
width = max(i.size[0] for i in images) index_x = 0
height = sum(i.size[1] for i in images) + (gapcount * args.gap) index_y = 0
final_image = PIL.Image.new('RGBA', [width, height])
offset = 0
for image in images: for image in images:
if direction is VERTICAL: arranged_images[index_y].append(image)
final_image.paste(image, (0, offset)) column_widths[index_x] = max(column_widths[index_x], image.size[0])
offset += image.size[1] + args.gap row_heights[index_y] = max(row_heights[index_y], image.size[1])
if args.vertical:
index_y += 1
(bump_x, index_y) = divmod(index_y, grid_y)
index_x += bump_x
else: else:
final_image.paste(image, (offset, 0)) index_x += 1
offset += image.size[0] + args.gap (bump_y, index_x) = divmod(index_x, grid_x)
index_y += bump_y
final_width = sum(column_widths) + ((grid_x - 1) * args.gap)
final_height = sum(row_heights) + ((grid_y - 1) * args.gap)
final_image = PIL.Image.new('RGBA', [final_width, final_height])
offset_y = 0
for (index_y, row) in enumerate(arranged_images):
offset_x = 0
for (index_x, image) in enumerate(row):
pad_x = int((column_widths[index_x] - image.size[0]) / 2)
pad_y = int((row_heights[index_y] - image.size[1]) / 2)
final_image.paste(image, (offset_x + pad_x, offset_y + pad_y))
offset_x += column_widths[index_x]
offset_x += args.gap
offset_y += row_heights[index_y]
offset_y += args.gap
log.info(args.output) log.info(args.output)
final_image.save(args.output) final_image.save(args.output)
@ -52,8 +78,20 @@ def main(argv):
parser.add_argument('image_files', nargs='+') parser.add_argument('image_files', nargs='+')
parser.add_argument( parser.add_argument(
'--output', '--output',
metavar='filename',
required=True, required=True,
) )
parser.add_argument(
'--grid',
metavar='AxB',
help='''
Stitch the images together in grid of A columns and B rows. Your
numbers A and B should be such that A*B is larger than the number
of input images. If you add --horizontal, the images will be arranged
left-to-right first, then top-to-bottom. If you add --vertical, the
images will be arranged top-to-bottom first then left-to-right.
''',
)
parser.add_argument( parser.add_argument(
'--horizontal', '--horizontal',
action='store_true', action='store_true',