Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import Image
- import math
- import re
- import os
- import sys
- import glob
- import array
- class Img:
- def __init__(self, sprite, image, dx, dy, x, y, w, h):
- self.sprite = sprite
- self.image = image
- self.x = x
- self.y = y
- self.w = w
- self.h = h
- self.dx = dx
- self.dy = dy
- def __cmp__(self, other):
- return cmp(other.h, self.h)
- def power_of_two(input):
- value = 1
- while (value < input):
- value <<= 1
- return value
- def inRange(value, vmin, vmax):
- return (value >= vmin) and (value < vmax)
- def rectOverlap(a, b):
- Ax1,Ay1,Ax2,Ay2 = a
- Bx1,By1,Bx2,By2 = b
- xOverlap = inRange(Ax1, Bx1, Bx2) or inRange(Bx1, Ax1, Ax2)
- yOverlap = inRange(Ay1, By1, By2) or inRange(By1, Ay1, Ay2)
- return xOverlap and yOverlap
- class Packer:
- def __init__(self, imagelist, tile=False):
- if not tile:
- sq = 0
- for s in imagelist:
- sq += s.w * s.h
- mw = power_of_two( math.sqrt(sq) )
- mh = mw
- else:
- mw = imagelist[0].w
- mh = mw * len(imagelist)
- print "Using image %dx%d" % (mw, mh)
- self.nodes = []
- self.rect = []
- self.nodes.append((0,0))
- self.imagelist = imagelist
- self.imap = Image.new("RGBA", (mw, mh))
- self.mask = array.array("i", [0] * mw * mh)
- self.imagelist = imagelist
- self.tile = tile
- def place(self, x, y, img):
- w, h = img.image.size
- mw, mh = self.imap.size
- self.rect.append((x,y, x+w, y+h))
- self.nodes.append((x+w,y))
- self.nodes.append((x,y+h))
- self.nodes.sort(key=lambda s:int(s[1]*0xff+s[0]))
- self.imap.paste(img.image, (x,y))
- img.x = x
- img.y = y
- return 1
- def checkpos(self, x, y, w, h):
- mw, mh = self.imap.size
- if x + w > mw or y + h > mh:
- return False
- for r in self.rect:
- if rectOverlap(r, (x, y, x+w, y+h)):
- return False
- return True
- def putimage(self, img):
- mw, mh = self.imap.size
- w, h = img.image.size
- for node in self.nodes:
- x,y = node
- if self.checkpos(x,y,w,h):
- return self.place(x,y,img)
- return 0
- def process(self):
- v = self.imagelist[:]
- if not self.tile:
- v.sort()
- placed = 0
- total = 0
- for img in v:
- perc = (total+1) * 100 / len(v)
- sys.stderr.write("\rPlacing: %d%%" % perc)
- placed += self.putimage(img)
- total += 1
- print "\nTotal images: %d placed: %d lost: %d" % (total, placed, (total-placed));
- b = self.imap.getbbox()
- if b:
- b = 0,0, power_of_two(b[2]), b[3]
- print "Cropping map to %dx%d" % (b[2], b[3])
- self.imap = self.imap.crop(b)
- return v
- def save_imap(self, outfile):
- print "Saving %s" % outfile
- self.imap.save(outfile);
- def fkey(fname):
- name, ext = os.path.splitext(os.path.basename(fname))
- try:
- return int(name)
- except:
- return name
- def import_directory(path, sprite=0):
- imagelist = []
- files = glob.glob( os.path.join(path, '*.png') )
- files.sort(key=fkey)
- for fname in files:
- image = Image.open(fname)
- if image:
- w, h = image.size
- dx, dy = (0, 0)
- m = re.search("\((\d+),(\d+)\).png", fname)
- if m:
- dx, dy = (int(m.group(1)), int(m.group(2)))
- imagelist.append(Img(sprite, image, dx, dy, 0, 0, w, h))
- sprite += 1
- if not imagelist:
- print "Could not open imagelist"
- exit(1)
- else:
- print "Loaded %d images" % len(imagelist)
- return imagelist
- def pack(fname):
- name, e = os.path.splitext(fname)
- pngfile = "%s.packed.png" % name
- imagelist = import_directory(name,0)
- packer = Packer(imagelist)
- imagelist = packer.process()
- packer.save_imap(pngfile)
- def main():
- if len(sys.argv) < 2:
- print "Usage: %s <image dir>" % sys.argv[0]
- pack('font10x14')
- # pack('font-border-buttons')
- else:
- pack(sys.argv[1])
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement