def create_imagefont(res_path, font_filename, point_size, text, color): done = False curr_size = 64 texture_packer = None image_dict = None packResult = None # Retry until optimal font atlas size is found. while not done: try: result = pack_fonts(font_filename, point_size, text, color, curr_size) texture_packer = result[0] packResult = result[1] image_dict = result[2] done = True except PackerError: curr_size = next_power_of_two(curr_size) print "Failed, trying next power of two", curr_size borderSize = 1 font_image_name = os.path.join( get_fonts_path(res_path), "%s_%s.%s" % (os.path.basename(font_filename).split(".")[0], str(point_size), "tga") ) atlas_data = AtlasData( name=font_image_name, width=packResult[0], height=packResult[1], color_mode="RGBA", file_type="tga", border=borderSize, ) for tex in texture_packer.texArr: atlas_data.add_texture(tex) parser = get_parser("xml") parser.parse(atlas_data) parser.save("%s.%s" % (font_image_name.split(".")[0], parser.get_file_ext())) atlas_image = Image.new("RGBA", (packResult[0], packResult[1]), color) index = 0 for name in image_dict.keys(): tex = texture_packer.get_texture(name) atlas_image.paste(image_dict[name], (tex.x, tex.y)) index += 1 atlas_image.save(os.path.join(get_fonts_path(res_path), font_image_name), "tga")
def create_atlas(texMode, dirPath, atlasPath, dirName, args): done = False curr_size = int(args['maxrects_bin_size']) texture_packer = None imagesList = None packResult = None # Retry until optimal font atlas size is found. while not done: try: result = pack_atlas(args, dirPath, curr_size) texture_packer = result[0] packResult = result[1] imagesList = result[2] done = True except PackerError: curr_size = next_power_of_two(curr_size) print "Failed, trying next power of two", curr_size borderSize = 1 atlas_name = '%s.%s' % (dirName, args['atlas_type']) atlas_data = AtlasData(name=dirName, width=packResult[0], height=packResult[1], color_mode=texMode, file_type=args['atlas_type'], border=borderSize) for tex in texture_packer.texArr: atlas_data.add_texture(tex) parser = get_parser(args['output_data_type']) parser.parse(atlas_data) parser.save('%s.%s' % (os.path.join(atlasPath, os.path.basename(dirPath)), parser.get_file_ext())) atlas_image = Image.new(texMode, (packResult[0], packResult[1]), get_color(args['bg_color'])) index = 0 for image in imagesList: tex = texture_packer.get_texture(image[0]) atlas_image.paste(image[1], (tex.x, tex.y)) index += 1 atlas_image.save(os.path.join(atlasPath, os.path.basename(dirPath)) + "." + args['atlas_type'], args['atlas_type']) if (args['verbose']): atlas_image.show()
def pack_textures(self, forcePowerOfTwo, onePixelBorder): # 0 = width # 1 = height # 3 = returnValue returnList = [] if (onePixelBorder): i = 0 for t in self.texArr: t.width += 2 t.height += 2 self.texArr[i] = t i += 1 self.longestEdge += 2 if (forcePowerOfTwo): self.longestEdge = next_power_of_two(self.longestEdge) width = self.longestEdge count = self.totalArea / (self.longestEdge * self.longestEdge) height = (count + 2) * self.longestEdge self.add_node(0, 0, width, height) # We must place_texture each texture loopI = 0 while (loopI < self.get_texture_count()): index = 0 longestEdge = 0 mostArea = 0 # We first search for the texture with the longest edge, placing it first. # And the most area... j = 0 for texture in self.texArr: #print "Checking texture ", tmpTex.GetName() if (not texture.placed): if (texture.longestEdge > longestEdge): mostArea = texture.area longestEdge = texture.longestEdge index = j elif (texture.longestEdge == longestEdge): if (texture.area > mostArea): mostArea = texture.area index = j j += 1 # For the texture with the longest edge we place_texture it according to this criteria. # (1) If it is a perfect match, we always accept it as it causes the least amount of fragmentation. # (2) A match of one edge with the minimum area left over after the split. # (3) No edges match, so look for the node which leaves the least amount of area left over after the split. tex = self.texArr[index] #print "Going to try and place_texture ", tex.GetName() leastY = 0x7FFFFFFF leastX = 0x7FFFFFFF nodeIndex = 0 idx = 0 previousBestFitNodeIdx = 0 bestFitNode = Node(0, 0, 0, 0) previousNodeIdx = 0 edgeCount = 0 # Walk the singly linked list of free nodes # see if it will fit into any currently free space for currNode in self.freeArr: resultdoes_rect_fitArr = currNode.does_rect_fit(tex.get_rect().get_width(), tex.get_rect().get_height()) ec = resultdoes_rect_fitArr[1] # see if the texture will fit into this slot, and if so how many edges does it share. if (resultdoes_rect_fitArr[0] is True): if (ec == 2): previousBestFitNodeIdx = previousNodeIdx bestFitNode = currNode nodeIndex = idx edgeCount = ec break if (currNode.y < leastY): leastY = currNode.y leastX = currNode.x previousBestFitNodeIdx = previousNodeIdx bestFitNode = currNode nodeIndex = idx edgeCount = ec elif (currNode.y == leastY and currNode.x < leastX): leastX = currNode.x previousBestFitNodeIdx = previousNodeIdx bestFitNode = currNode nodeIndex = idx edgeCount = ec previousNodeIdx = idx idx += 1 # we should always find a fit location! if(bestFitNode.x == 0 and bestFitNode.y == 0 and bestFitNode.get_rect().get_width() == 0 and bestFitNode.get_rect().get_height() == 0): print "TexturePacker::pack_textures() BestFit node not found!!" exit(1) self.validate() if (edgeCount == 0): if (tex.longestEdge <= bestFitNode.get_rect().get_width()): if (tex.height > tex.width): tex.flip_dimensions() tex.flipped = True tex.place_texture(bestFitNode.x, bestFitNode.y, tex.flipped) self.add_node(bestFitNode.x, bestFitNode.y + tex.height, bestFitNode.get_rect().get_width(), bestFitNode.get_rect().get_height() - tex.height) bestFitNode.x += tex.width bestFitNode.width -= tex.width bestFitNode.height = tex.height self.validate() else: if (tex.longestEdge <= bestFitNode.height): print("TexturePacker::PackTexture() ERROR - Current textures longest edge is less than the BestFitNodes Height!!!") exit(1) if (tex.height < tex.width): tex.flip_dimensions() tex.flipped = True tex.place_texture(bestFitNode.x, bestFitNode.y, tex.flipped) self.add_node(bestFitNode.x, bestFitNode.y + tex.height, bestFitNode.get_rect().width, bestFitNode.get_rect().height - tex.height) bestFitNode.x += tex.width bestFitNode.width -= tex.width bestFitNode.height = tex.height self.validate() elif(edgeCount == 1): if (tex.width == bestFitNode.get_rect().get_width()): tex.place_texture(bestFitNode.x, bestFitNode.y, False) bestFitNode.y += tex.height bestFitNode.height -= tex.height self.validate() elif (tex.height == bestFitNode.get_rect().get_height()): tex.place_texture(bestFitNode.x, bestFitNode.y, False) bestFitNode.x += tex.width bestFitNode.width -= tex.width self.validate() elif (tex.width == bestFitNode.get_rect().get_height()): tex.place_texture(bestFitNode.x, bestFitNode.y, True) bestFitNode.x += tex.height bestFitNode.width -= tex.height self.validate() elif (tex.height == bestFitNode.get_rect().get_width()): tex.place_texture(bestFitNode.x, bestFitNode.y, True) bestFitNode.y += tex.width bestFitNode.height -= tex.width self.validate() elif(edgeCount == 2): flipped = tex.width != bestFitNode.get_rect().get_width() or tex.height != bestFitNode.get_rect().get_height() tex.place_texture(bestFitNode.x, bestFitNode.y, flipped) if (previousBestFitNodeIdx >= 0): previousBestFitNodeIdx = index self.validate() # Save latest version of texture and Node back into lists since python is pass by value self.freeArr[nodeIndex] = bestFitNode self.texArr[index] = tex loopI += 1 while (self.merge_nodes()): print "Merging nodes" index = 0 height = 0 for t in self.texArr: if (onePixelBorder): t.width -= 2 t.height -= 2 t.x += 1 t.y += 1 self.texArr[index] = t y = 0 if (t.flipped): y = t.y + t.width else: y = t.y + t.height if (y > height): height = y index += 1 if (forcePowerOfTwo): height = next_power_of_two(height) returnList.append(width) returnList.append(height) returnList.append((width * height) - self.totalArea) return (returnList)