Texture Atlases for UIKit with TexturePacker
I use UIKit for my UI, but one issue I was facing is the sheer number of separate image files I was building up in my project. Texture atlas generation is common in OpenGL libraries like cocos2d, and TexturePacker has an export option specifically for these libraries. I couldn’t find anything for UIKit however.
I wrote a quick function to parse TexturePacker’s “Generic XML” data format and generate an NSDictionary of UIImages.
It depends on XMLReader, so you’ll need to include that in your project too.
Updates
- 13/01/13 – Fixed unnecessary allocation of UIImage which caused a leak.
UIImage+Sprite.h
// Created by Daniel Sefton, 2012 // Do what you want license #import <Foundation/Foundation.h> /** UIImage category to handle parsing of TexturePacker's Generic XML format. */ @interface UIImage (Sprite) /** The method returns a dictionary of UIImages. Use this function once and reference its contents. @param filename the XML file to load, which should be added to your project's bundle @returns dictionary of UIImages */ + (NSDictionary*)spritesWithContentsOfFile:(NSString*)filename; @end |
UIImage+Sprite.m
// Created by Daniel Sefton, 2012 // Do what you want license #import "UIImage+Sprite.h" #import "XMLReader.h" @implementation UIImage (Sprite) + (NSDictionary*)spritesWithContentsOfFile:(NSString*)filename { NSString* file = [[filename lastPathComponent] stringByDeletingPathExtension]; if ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && ([UIScreen mainScreen].scale == 2.0)) { file = [NSString stringWithFormat:@"%@@2x", file]; } NSString* extension = [filename pathExtension]; NSData* data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:file ofType:extension]]; NSError* error = nil; NSDictionary* xmlDictionary = [XMLReader dictionaryForXMLData:data error:&error]; NSDictionary* xmlTextureAtlas = [xmlDictionary objectForKey:@"TextureAtlas"]; UIImage* image = [UIImage imageNamed:[xmlTextureAtlas objectForKey:@"imagePath"]]; CGSize size = CGSizeMake([[xmlTextureAtlas objectForKey:@"width"] integerValue], [[xmlTextureAtlas objectForKey:@"height"] integerValue]); if (!image || CGSizeEqualToSize(size, CGSizeZero)) return nil; CGImageRef spriteSheet = [image CGImage]; NSMutableDictionary* tempDictionary = [[[NSMutableDictionary alloc] init] autorelease]; NSArray* xmlSprites = [xmlTextureAtlas objectForKey:@"sprite"]; for (NSDictionary* xmlSprite in xmlSprites) { CGImageRef sprite = CGImageCreateWithImageInRect(spriteSheet, CGRectMake( [[xmlSprite objectForKey:@"x"] integerValue], [[xmlSprite objectForKey:@"y"] integerValue], [[xmlSprite objectForKey:@"w"] integerValue], [[xmlSprite objectForKey:@"h"] integerValue])); [tempDictionary setObject:[UIImage imageWithCGImage:sprite] forKey:[xmlSprite objectForKey:@"n"]]; CGImageRelease(sprite); } return [NSDictionary dictionaryWithDictionary:tempDictionary]; } @end |
Usage
self.mySprites = [UIImage spritesWithContentsOfFile:@"mysprites.xml"]; UIImage* myImage = [self.mySprites objectForKey:@"myimage"]; |
5 Responses to Texture Atlases for UIKit with TexturePacker
Leave a Reply Cancel reply
About Me
I'm a 21 year old from York, England now living in Mountain View, CA. I'm an all-in-one programmer, designer and entrepreneur working in one of the fastest growing mobile startups by day, and disrupting the freemium mobile games industry by night. Read more...
Twitter: danielsefton
- RT @gamasutra: The problem with investors and game developers http://t.co/LZLGcR2cP5 about 4 hours ago from web ReplyRetweetFavorite
- RT @eeen: I can’t wait for the iBox where everyone gets to publish their games (hint: it will be the Apple TV). about 9 hours ago from web ReplyRetweetFavorite
- Really hard to get visa as an entrepreneur -> #iMarch for Innovation. Tell Congress we need smart #immigration reform http://t.co/kfVhAXzQ0X about 9 hours ago from Thunderclap ReplyRetweetFavorite
- RT @SlaunchaMan: Fixing a show stopper bug on the backend before Apple reviews your app http://t.co/YQlNGGqTBg about 11 hours ago from Twitter for iPhone ReplyRetweetFavorite
Categories












This is great. I added a repo on github with a working xcodeproj
https://github.com/zeiteisen/Texture-Atlases-for-UIKit-with-TexturePacker-
Hi,
nice job
I’ll link to it from codeandweb.com
The only thing I see missing is support for rotated sprites.
Cheers
Andreas
Very cool. Thank you. Don’t ‘spose there is a way to get Interface Builder to use recognise the sprite images?
That’s pretty cool. Having the same problem with tons of resources and getting hard to manage in the project.
So basically it makes sense to use a spritesheet all graphics it contains where to appear on that single screen right?
How are you actually using it with UIKit, 1 spritesheet for entire app? have you have any memory issues or overhead?
Thanks Daniel!
Hi Bach,
Yes, the idea is that you bunch together multiple images in one spritesheet. It’s up to you if you want to use multiple spritesheets, and that may even be necessary if you have so many. I wouldn’t go any larger than 2048×2048 per spritesheet.
By default the function pre-allocates all the UIImages at once, which will use more memory but reduce the number of runtime allocations, which is often preferable. I really don’t think it’s an issue, but if you want you can check it out in Instruments.