This uses SciPy, NumPy, and illustrates how NumPy arrays can be used to manipulate png images. {{{c """ pngcat Concatenates PNG files Usage: import pngcat pngcat_v(["file1.png","file2.png",...,"filen.png"],"output.png") # above each other pngcat_h(["file1.png","file2.png",...,"filen.png"],"output.png") # beside each other """ import numpy as np from imageio import imread,imwrite def pngcat_v(input_filenames, output_filename, bgcolor = [255,255,255,255]): """pngcat_v([filenames],output_filename)""" input_data = list(map(imread,input_filenames)) input_heights = list(map(lambda t: t.shape[0],input_data)) input_widths = list(map(lambda t: t.shape[1],input_data)) input_dtype = input_data[0].dtype output_height = sum(input_heights) output_width = max(input_widths) output_array = np.zeros((output_height,output_width,4),dtype=input_dtype) output_array[:,:] = bgcolor start_row = 0 for src in input_data: h,w,_ = src.shape output_array[start_row:start_row+h,:w,:] = src start_row += h imwrite(output_filename,output_array) def pngcat_h(input_filenames, output_filename, bgcolor = [255,255,255,255]): """pngcat_h([filenames],output_filename)""" input_data = list(map(imread,input_filenames)) input_heights = list(map(lambda t: t.shape[0],input_data)) input_widths = list(map(lambda t: t.shape[1],input_data)) input_dtype = input_data[0].dtype output_height = max(input_heights) output_width = sum(input_widths) output_array = np.zeros((output_height,output_width,4),dtype=input_dtype) output_array[:,:] = bgcolor start_col = 0 for src in input_data: h,w,_ = src.shape output_array[0:h,start_col:start_col+w,:] = src start_col += w imwrite(output_filename,output_array) }}}%TIME=1616260412