I am trying to merge multiple images and as per requirement its working as explained below.
I am expecting 3 images should come in one single row and 4th image should come in next row but as per provided output for below image i am getting improper sequence of images i.e. Cat, Dog and Apple should come in one single row as per my code given below. Currently mouse image is also is coming with Cat, Dog and Apple as well as Apple image is not visible.
from PIL import Image
im1 = Image.open('cat_image.jpg')
im2 = Image.open('dog.jpg')
im3 = Image.open("apple.jpg")
im4 = Image.open("mouse.jpg")
def get_concat_h_multi_resize(im_list, resample=Image.BICUBIC):
    min_height = min(im.height for im in im_list)
    print("min_height", min_height)
    im_list_resize = [im.resize((int(im.width * min_height / im.height), min_height), resample=resample)
                      for im in im_list]
    total_width = sum(im.width for im in im_list_resize)
    print("total width", total_width)
    dst = Image.new('RGB', (total_width, min_height))
    pos_x,pos_y = 0,0
    img_counter = 0
    for im in im_list_resize:
        img_counter += 1
        if img_counter == 3:
            dst.paste(im, (pos_x, pos_y))
            pos_y += im.width + 5
        else:
            dst.paste(im, (pos_x, 0))
            pos_x += im.width + 5
    return dst
get_concat_h_multi_resize([im1, im2, im3, im4]).save('pillow_concat_h_multi_resize.jpg')
Expected Output :- I want to display Cat,Dog ,Apple in single row and mouse in next row.
Please help me with solution.
Thanks In Advance !!
Advertisement
Answer
You just need to use proper total_width and total_height in your output image. Since you need two rows, the total_height should be 2*min_height. The total_width should be just the sum of width of the first three images. Also, the x-coordinate for the new line should be 0 (or 5 since you are using a margin of width 5)
import math
from PIL import Image
im1 = Image.open("1.png")
im2 = Image.open("2.png")
im3 = Image.open("3.png")
im4 = Image.open("4.png")
im5 = Image.open("5.png")
im6 = Image.open("6.png")
im7 = Image.open("7.png")
im8 = Image.open("8.png")
im9 = Image.open("9.png")
im10 = Image.open("10.png")
def get_concat_h_multi_resize(im_list, n_rows, resample=Image.BICUBIC):
    min_height = min(im.height for im in im_list)
    im_list_resize = [
        im.resize((int(im.width * min_height / im.height), min_height), resample=resample) for im in im_list
    ]
    max_width = max(im.width for im in im_list_resize)
    n_cols = math.ceil(len(im_list) / n_rows)
    total_width = (max_width) * n_cols  # compute total width
    total_height = (min_height) * n_rows
    dst = Image.new("RGB", (total_width, total_height))  # calculate the total height
    pos_x = 0
    pos_y = 0
    for i in range(len(im_list_resize)):
        im = im_list_resize[i]
        dst.paste(im, (pos_y, pos_x))
        pos_y += im.width
        if (i + 1) % n_cols == 0:
            # new row
            pos_x += im.height
            pos_y = 0
    print(" total: ", total_width, total_height)
    return dst
get_concat_h_multi_resize(im_list=[im1, im2, im3, im4, im5, im6, im7, im8, im9, im10], n_rows=3).save(
    "pillow_concat_h_multi_resize.jpg"
)
The final output appears as shown below:
 The trailing black areas in each row are because of reserving extra width to handle the image with maximum width. In this example, the number 10 has a larger width than the others, so we used the width of 10 to define our total width.
The trailing black areas in each row are because of reserving extra width to handle the image with maximum width. In this example, the number 10 has a larger width than the others, so we used the width of 10 to define our total width.
