How to merge external images together in script? I'm trying to merge set of images together with script in Blender 2.8. At the moment there is no library like PIL available in Blender, but there is imbuf which one I can use to read the images from disk to list. There is not much documentation about this imbuf... Anyway I want to do this merge process with blender own libraries, so users not need to get PIL or similar library...

How I can merge multiple image files from disk together with Python in Blender? Is there pythonic way to do this without libraries, or can I do it with imbuf, or using imbuf and numpy, or how to do this in blender script? 

I'm lost how can I make this, so If someone knows how to do this in Blender 2.8, please show me.

import imbuf

def merge_image_parts(image_paths):

    images = []

    # Load images to list with imbuf
    for img in image_paths:
        img_path = os.path.realpath(bpy.path.abspath(img))
        images.append(imbuf.load(filepath))

    # MERGE TO NEW IMAGE BUT HOW?
Finally, I managed to combine image parts together with looping nested arrays. Although the script itself is not the most beautiful... I mark this answer to correct now, but if somebody is doing better that works in this context, I'll change it.

So here is "monster" that I've used in this case:

# First I need to order rendered part names correctly
rendered_images_ordered = []            
for y in range(parts_count, 0, -1):
    for x in range(parts_count):
        rendered_images_ordered.append(rendered_images[(y-1)+(x*parts_count)])

# Then I grab pixel data from all parts
part_pixels = []  
for image in rendered_images_ordered:
    filepath = os.path.join(scene.render_settings.render_folder, image)
    filepath = os.path.realpath(bpy.path.abspath(filepath))
    loaded_pixels = list(bpy.data.images.load(filepath, check_existing=False).pixels)
    part_pixels.append([loaded_pixels[ipx:ipx+4] for ipx in range(0, len(loaded_pixels), 4)])

# And finally loop all pixels together to final image
final_image_pixels = []
for i in range(parts_count, 0, -1):
    for row in range(part_height):    
        part_switch = -1           
        px_counter = -1            
        for col in range(final_image_width):
            if col % part_width == 0:
                part_switch += 1
                px_counter = 0
            if i-1 == 0:
                px_arr = i-1 + part_switch
            else:
                px_arr = ((i-1) * parts_count) + part_switch
            target_pixel = row * part_width + px_counter
            final_image_pixels.append(part_pixels[px_arr][target_pixel])
            px_counter += 1 

# And then save output image
output_image = bpy.data.images.new(final_image_name, alpha=True, width=final_image_width, height=final_image_height)
output_image.alpha_mode = 'STRAIGHT'          
output_image.pixels = final_image_pixels
output_image.filepath_raw = final_image_filepath
output_image.file_format = scene.render.image_settings.file_format
output_image.save()     


Result:



If you want to investigate more about where I use this loop check here. This is part of RenderFart blender addon. I hope my answer or addon is helpful for someone...