Skip to content

Instantly share code, notes, and snippets.

@julsam
Created March 27, 2011 11:17
Show Gist options
  • Save julsam/889130 to your computer and use it in GitHub Desktop.
Save julsam/889130 to your computer and use it in GitHub Desktop.
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment