def testPackSequentialWidth(self): # AAAAAAAA # BBBBBBB # CCCCCC # DDDDD # EEEE # FFF # GG # H boxes = [Box(i, 1) for i in range(1, 9)] # AAAAAAAA # BBBBBBBH # CCCCCCGG # DDDDDFFF # EEEE packing = [ (0, 0, Box(8, 1)), (0, 1, Box(7, 1)), (7, 1, Box(1, 1)), (0, 2, Box(6, 1)), (6, 2, Box(2, 1)), (0, 3, Box(5, 1)), (5, 3, Box(3, 1)), (0, 4, Box(4, 1)), ] (_, _, actual) = pack_boxes(boxes, 8) self.assert_(check_no_overlap(actual)) self.assertEqual(actual, packing)
def testRandomNoOverlap(self): # Not having overlap is an important invariant we need to maintain. # This just checks it. boxes = [Box(random.randrange(1, 40), random.randrange(1, 40)) for _ in xrange(100)] (_, _, actual) = pack_boxes(boxes) self.assert_(check_no_overlap(actual))
def testPackSequenceHeightWidth(self): # A # B # B # C # C # C # DD # EE # EE # FF # FF # FF # GGG # HHH # HHH # III # III # III boxes = [Box(i, j) for i in range(1, 4) for j in range(1, 4)] # III # III # III # HHH # HHH # GGG # FFC # FFC # FFC # EEB # EEB # DDA packing = [ (0, 0, Box(3, 3)), (0, 3, Box(3, 2)), (0, 5, Box(3, 1)), (0, 6, Box(2, 3)), (2, 6, Box(1, 3)), (0, 9, Box(2, 2)), (2, 9, Box(1, 2)), (0, 11, Box(2, 1)), (2, 11, Box(1, 1)), ] (_, _, actual) = pack_boxes(boxes, 3) self.assert_(check_no_overlap(actual)) self.assertEqual(actual, packing)
def testPackEasy(self): # AA # B # C boxes = [ Box(2, 1), Box(1, 1), Box(1, 1), ] # AA # BC packing = [ (0, 0, Box(2, 1)), (0, 1, Box(1, 1)), (1, 1, Box(1, 1)), ] (_, _, actual) = pack_boxes(boxes, 2) self.assert_(check_no_overlap(actual)) self.assertEqual(actual, packing)
def testPackSingle(self): boxes = [Box(1, 1)] packing = [(0, 0, Box(1, 1))] (_, _, actual) = pack_boxes(boxes, 1) self.assert_(check_no_overlap(actual)) self.assertEqual(actual, packing)
def testCheckNoOverlap(self): # These boxes touch but do not overlap. packing = [(0, 0, Box(2, 2)), (2, 0, Box(2, 2))] self.assert_(check_no_overlap(packing))
def testCheckOverlap(self): # The second box has a top left point in the center of the first. packing = [(0, 0, Box(2, 2)), (1, 1, Box(2, 2))] self.assert_(not check_no_overlap(packing))
def handle_noargs(self, **options): version_stamp = str(int(time.mktime(datetime.now().timetuple()))) BUFFER_SIZE = 40 images = [] filenames = [] boxes = [] directories = getattr(settings, 'SPRITE_DIRS', ['/media/public_media/images/sprites']) for directory in directories: for image in [ f for f in os.listdir(directory) if f.endswith('.png') ]: image_file = Image.open('%s/%s' % ( directory, image, )) image_width, image_height = image_file.size boxes.append(Box(image_width, image_height, image_file)) max_width, y_off, packing = pack_boxes(boxes) master = Image.new(mode='RGBA', size=(max_width, y_off), color=(0, 0, 0, 0)) # fully transparent for x, y, image in packing: master.paste(image.filename, (x, y)) map_ouput = '%s' % getattr(settings, 'SPRITE_MAP_OUTPUT') location = '%ssprites.r%s.%s' % (getattr( settings, 'SPRITE_MAP_OUTPUT'), version_stamp, 'png') master.save(location) css_file_location = '%ssprites.css' % getattr(settings, 'SPRITE_CSS_OUTPUT') sprite_url = '../images/sprites.r%s.png' % version_stamp iconCssFile = open(css_file_location, 'w') print css_file_location for x, y, image in packing: image_file = image.filename image_width, image_height = image_file.size filename = image_file.filename.split('/')[-1].split('.')[0] css = """.sprite_%(filename)s { background-position: -%(top)spx -%(left)spx; width:%(width)spx; height:%(height)spx; display: inline-block; } """ % { 'filename': filename, 'top': x, 'left': y, 'width': image_width, 'height': image_height } iconCssFile.write(css) iconCssFile.write(""" .sprite, .sprite_inline { background-image: url('%s'); *background-image: url('%s'); } """ % (sprite_url, sprite_url)) iconCssFile.close()