These two classes can pack surfaces of different sizes into one big surface.

import pygame class PackNode(object): """ Creates an area which can recursively pack images into itself. """ def __init__(self, area): # if tuple contains two elements, assume they are width and height, # and origin is (0,0) if len(area) == 2: area = (0,0,area[0],area[1]) self.area = area def get_width(self): return self.area[2] - self.area[0] width = property(fget=get_width) def get_height(self): return self.area[3] - self.area[1] height = property(fget=get_height) def insert(self, area): if hasattr(self, 'child'): a = self.child[0].insert(area) if a is None: return self.child[1].insert(area) return a area = PackNode(area) if area.width <= self.width and area.height <= self.height: self.child = [None,None] self.child[0] = PackNode((self.area[0]+area.width, self.area[1], self.area[2], self.area[1] + area.height)) self.child[1] = PackNode((self.area[0], self.area[1]+area.height, self.area[2], self.area[3])) return PackNode((self.area[0], self.area[1], self.area[0]+area.width, self.area[1]+area.height)) class Pack(object): def __init__(self, size=(512,512)): self.tree = PackNode(size) self.image = pygame.Surface(size, pygame.SRCALPHA, 32) self.wr = 1.0 / float(size[0]) self.hr = 1.0 / float(size[1]) def pack(self, img): wr = self.wr hr = self.hr if not isinstance(img, pygame.Surface): img = pygame.image.load(img).convert(32, pygame.SRCALPHA) img = img.convert_alpha(img) uv = self.tree.insert(img.get_size()) if uv is None: raise ValueError('Pack size too small.') area = tuple(uv.area) self.image.blit(img, area) uv = area[0] * wr, area[1] * hr, area[2] * wr, area[3] * hr return (uv[0],uv[1]),(uv[0], uv[3]), (uv[2],uv[3]), (uv[2], uv[1]) if __name__ == "__main__": import time import glob pygame.init() s = pygame.display.set_mode((512,512)) p = Pack() for filename in glob.glob("*.png"): p.pack(filename) pygame.image.save(p.image, 'out.png') s.blit(p.image, (0,0)) pygame.display.flip() time.sleep(1)