Reputation: 9538
I have searched for this topic of how to merge or concatenate multiple images using python.
from PIL import Image
def get_concat_v():
dst = Image.new('RGB', (im1.width, im1.height + im2.height + im3.height + im4.height))
dst.paste(im1, (0, 0))
dst.paste(im2, (0, im1.height))
dst.paste(im3, (0, im1.height + im2.height))
dst.paste(im4, (0, im1.height + im2.height + im3.height))
return dst
im1 = Image.open('First.png')
im2 = Image.open('Second.png')
im3 = Image.open('Third.png')
im4 = Image.open('Fourth.png')
get_concat_v().save('concat_v.png')
How can I loop through a folder that has multiple images (Say 9 images) and merge every four images into one image? So the final folder should have three images (the first image would contain 4 images, the second image would contain 4 images, the third image would contain 1 image)
Upvotes: 2
Views: 3717
Reputation: 3518
Does this do what you're looking for?
It uses more_itertools.chunked
to get image file paths in groups of four, including the final group which may be less than four. I also rewrote your concatenation function to accept any number of images, and expand to fit the widest one, if their widths differ.
from pathlib import Path
from more_itertools import chunked
from PIL import Image
def concat_images(*images):
"""Generate composite of all supplied images."""
# Get the widest width.
width = max(image.width for image in images)
# Add up all the heights.
height = sum(image.height for image in images)
composite = Image.new('RGB', (width, height))
# Paste each image below the one before it.
y = 0
for image in images:
composite.paste(image, (0, y))
y += image.height
return composite
if __name__ == '__main__':
# Define the folder to operate on (currently set to the current
# working directory).
images_dir = Path('.')
# Define where to save the output (shown here, will be in `output`
# inside the images dir).
output_dir = images_dir / 'output'
# Create the output folder, if it doesn't already exist.
output_dir.mkdir(exist_ok=True)
# Iterate through the .png files in groups of four, using an index
# to name the resulting output.
png_paths = images_dir.glob('*.png')
for i, paths in enumerate(chunked(png_paths, 4), start=1):
images = [Image.open(path) for path in paths]
composite = concat_images(*images)
composite.save(output_dir / f'{i}.png')
Upvotes: 1
Reputation: 2013
Trying to improve upon the already present answer.
You can join 4 images in a folder at a time getting their filenames with os.listdir()
and composing every 4 iterations.
from PIL import Image
import os
def get_concat_v(im1, im2, im3, im4):
dst = Image.new('RGB', (im1.width, im1.height + im2.height + im3.height + im4.height))
dst.paste(im1, (0, 0))
dst.paste(im2, (0, im1.height))
dst.paste(im3, (0, im1.height + im2.height))
dst.paste(im4, (0, im1.height + im2.height + im3.height))
return dst
images = []
for i, filename in enumerate(os.listdir("yourdirectory")):
images.append(Image.open(filename)) # keep track of read image
if i % 3 == 0: # every 4 images, save a new one
res = get_concat_v(images[0], images[1], images[2], images[3])
res.save("somewhere")
images = []
Upvotes: 0