Image Packing or How to Make a Texture Atlas

I had a little bit of time today to implement something i should have implemented a long time ago. It’s an image packer which will takes a bunch of images and pack them tightly into a single output image. I first wanted to come up with my own method but eventually decided that i was to lazy to mess with kd-trees and searched all mighty Google. I found that great article by Blackpawn at http://www.blackpawn.com/texts/lightmaps/default.html which i’ve read a couple of years ago already when i wanted to code my own lightmapper, a recurring theme of mine…

I extended the basic packing functionality with padding and border duplication so you can savely use that for pixel perfect drawing in OpenGL without seams or other nasty artifacts. The code is pure Java and uses the Java 2D API so it should be pretty portable. The basic operation of the little thing:

  1. put images with names in
  2. get output image plus the info where each original image is located in the atlas
  3. profit!

Here’s 100 generated images packed into a single 512×512 atlas with padding and border duplication (which are not very obvious given the nature of the generated images :p).

Here’s how you’d use it:

I plan adding JSON export to the packer which will be the basis for a neat new TextureAtlas class in libgdx.

You can find the source code over at the libgdx SVN repository. It’s a single self-contained class, steal it!

Fun trivia: the image packer is a heuristic approach to an instance of the set of packing problems. The problem at hand is actually NP-complete and closely related to… Tetris. Yes, Alexey Pajitnov, the guy who invented Tetris was originally working on a very similar packing problem. One of the side products was Tetris the game. Here’s a fun read discussing the complexity of Tetris.

7 thoughts on “Image Packing or How to Make a Texture Atlas

  1. Hey Mario, this is great. The only suggestion I would have is to support multiple output formats. This is especially relevant in cross platform dev. iOS has built in support for the PLIST format, and the packers for it all use those types of files.

    I actually use http://zwoptexapp.com/ to do my packing (I use the flash version). I convert the PLIST to a java array (using a quick program I wrote), and use the java array in my Android app. My buddy who’s helping with the iOS port uses same texture but he takes the original PLIST file.

    It would be nice to have one program do everything though, which is why I’m very interested in this project.

  2. Zwoptex is a lot more advanced than the above packer. For one thing it also allows automatic cropping of transparent images along with insert by rotation. I don’t plan on adding the later, i’ll probably add transparent pixel cropping though.

    I do not aim to provide a complete replacement for Zwoptex, i just don’t have time for that. The idea was to have a very simple Java class that takes as input a set of imagse and outputs a texture atlas plus the coordinates. How you encode your coordinates is completely up to you. There will never be a stand alone application i’m afraid. It should be straight forward to write a smal Java app that does exactly what you want using the ImagePacker class. Just get the coordinates via packer.getRects() and write them out in whatever format you want.

  3. Argh. I should wait a day before doing anything. Only yesterday I resurrected some old image packing code for this very purpose.

    Nonetheless, it’s interesting to see a different approach as this is an interesting problem to solve.

  4. I have been working on some thumb controllers and buttons, converted to .7, and just started working on some sprite management.

    I was thinking of doing something similar to how pyglet does it: http://www.pyglet.org/doc/programming_guide/image_sequences_and_atlases.html#texture-bins-and-atlases but tying it into the existing gdx classes. I like how they do image grids and sprite groups.

    Gdx Texture already has pixmap draw and SpriteBatch.draw has the src parameters. I was thinking of having a Sprite class that takes a TextureRegion which would have a ref to the texture and region. Maybe have it accept a list of regions for animation. Sprites would be added to a list somewhere, which would call update, and render the sprites, calling spritebatch only once, and draw in order of groups.

    If using Texture like this it would be good to be able to easily convert a Texture to a Pixmap and be able to save to a file.

    I read that you can not draw to the new Managed textures, maybe we could have a way to convert or lock an unManaged texture once it is full?

  5. Hi!

    I guess this is an old thread, but I’ll give it a try. I’m trying to write a little program that converts a zwoptex plist to a ‘pack’ file readable with TextureAtlas (something like Mark Udit mentioned), but can’t figure out how some fields of the ‘pack’ file work (rotate and offset for example).

    Is there any documentation about the format and composition of the ‘pack’ file?

    Regards!

  6. Hi Sergio, sorry there isn’t. You can look at the code in TextureAtlas. Rotate means the image is rotated 90 degrees in the packed image, this is an optional feature that allows the packer to be more efficient sometimes. Offset is for whitespace stripping, it’s the distance from the upper left of the original image to the upper left of the whitespace stripped image.

Leave a Reply

Your email address will not be published.