Ipphones

  • Subscribe to our RSS feed.
  • Twitter
  • StumbleUpon
  • Reddit
  • Facebook
  • Digg

Tuesday, 7 April 2009

Creating UIImages from TGA Data

Posted on 09:26 by Unknown
UIImage doesn't support as wide a range of file types as NSImage does in Cocoa . It's understandable, given the different natures of the devices they run on, however there are times when you will want to load data in a format that's not directly supported by UIImage. This happened recently while experimenting with creating a Milkshape 3D model loader for use in iPhone game development. Milkshape uses Targa and PCX files for the texture, and neither of these formats is supported by UIImage.

I haven't tackled PCX files, but I wrote a category on UIImage to let you instantiate a UIImage object from Targa data stored in a TGA file. This version doesn't support RLE encoded files, but generally for game models, RLE isn't encoded. If you need to save size in your image executable, zipping the uncompressed TGA data will save about the same amount of room. If you're looking at doing a game, I probably wouldn't recommend compressing the images at all unless you're very close to that ten meg limit that prevents people from downloading your game over 3G & Edge, since you'll have to expend processing cycles to decompress at launch or load time.

You can find the category and an Xcode project that shows how it can be used in the iPhone Bits repository over at Google Code.

This is a first draft and there is likely room for improvement. There are some known inefficiencies in this class. For example, the iPhone's native byte ordering is BGRA, and so is Targa's, This code, however, converts the Targa data to RGB, and likely under the hood, UIImage is converting back to BGRA. I'm pretty sure Core Graphics provides a way to avoid this conversion, but don't have time to research it right now. Also, if your only use of the Targa image is going to be in OpenGL, you probably want to skip this category altogether and just load the bitmap data into OpenGL directly. This category combined with the Texture2D from Apple's sample code certainly gives an easy way to setup a scaffold environment for early development.

UIImage-Targa.h
#import <UIKit/UIKit.h>

@interface UIImage(Targa)
+(id)imageFromTGAFile:(NSString *)filename;
+(id)imageFromTGAData:(NSData *)data;
+(id)imageWithRawRGBAData:(NSData *)data width:(int)width height:(int)height;
@end



UIImage-Targa.m
#import "UIImage-Targa.h"

void releaseImageData(void *info, const void *data, size_t size)
{
free((void *)data);
}


@implementation UIImage(Targa)
+(id)imageFromTGAFile:(NSString *)filename
{
NSData *data = [[NSData alloc] initWithContentsOfFile:filename];
id ret = [self imageFromTGAData:data];
[data release];
return ret;
}

+(id)imageFromTGAData:(NSData *)data
{

short imageHeight;
short imageWidth;
unsigned char bitDepth;
unsigned char imageType;
int colorMode;
long imageSize;
unsigned char *imageData;

unsigned char *bytes = (unsigned char *)[data bytes]+2; // skip first two bytes

memcpy(&imageType, bytes, sizeof(unsigned char));

if (imageType != 2 && imageType != 3)
{
NSException *exception = [NSException exceptionWithName:@"Unsupported File Format"
reason:@"Compressed TGA files are not supported yet"
userInfo:nil
]
;
[exception raise];
}

bytes += ( (sizeof(unsigned char) * 2) + (sizeof(short) * 4));
memcpy(&imageWidth, bytes, sizeof(short));
bytes += 2;
memcpy(&imageHeight, bytes, sizeof(short));
bytes += 2;
memcpy(&bitDepth, bytes, sizeof(char));
bytes+=2;

colorMode = bitDepth / 8;
imageSize = imageWidth * imageHeight * colorMode;

long newDataLength = imageWidth * imageHeight * 4;
imageData = (unsigned char *)malloc(newDataLength);
memcpy(imageData, bytes, imageSize * sizeof(unsigned char));

// Targa is BGR, swap to RGB
long byteCounter = 0;
for (long i = 0; i < imageSize; i += colorMode)
{
long start = (byteCounter++ * 4);
imageData[start] = bytes[i+2];
imageData[start+1] = bytes[i+1];
imageData[start+2] = bytes[i];
imageData[start+3] = (colorMode == 4) ? bytes[i+3] : 1.0;
}


// Targa uses more standard Y axis, so need to swap top & bottom bytes
// We can swap 32 bits at a time rather than going byte by byte
uint32_t *imageDataAsInts = (uint32_t *)imageData;
for (int y = 0; y < imageHeight / 2; y++)
{
for (int x = 0; x < imageWidth; x++)
{
uint32_t top = imageDataAsInts[y * imageWidth + x];
uint32_t bottom = imageDataAsInts[(imageHeight - 1 - y) * imageWidth + x];
imageDataAsInts[(imageHeight - 1 - y) * imageWidth + x] = top;
imageDataAsInts[y * imageWidth + x] = bottom;
}

}


NSData *swappedData = [[NSData alloc] initWithBytes:imageData length:newDataLength];
return [self imageWithRawRGBAData:swappedData width:imageWidth height:imageHeight];
}

+(id)imageWithRawRGBAData:(NSData *)data width:(int)width height:(int)height
{
const void * buffer = [data bytes];
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer, [data length], releaseImageData);

const int bitsPerComponent = 8;
const int bitsPerPixel = 4 * bitsPerComponent;
const int bytesPerRow = 4 * width;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

CGImageRef imageRef = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
CGDataProviderRelease(provider);

UIImage *myImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);

return myImage;
}

@end

Email ThisBlogThis!Share to XShare to Facebook
Posted in | No comments
Newer Post Older Post Home

0 comments:

Post a Comment

Subscribe to: Post Comments (Atom)

Popular Posts

  • Making OpenGL ES Screenshot
    The Bit-101 Blog has an entry that shows how to take a screenshot when using OpenGL ES . I tested this in my much-delayed particle-generato...
  • Adding CLANG to Your Build Process
    Frasier Spiers has a nifty piece this morning on using Git pre-commit hooks to automatically run the CLANG Static Analyzer. I'm not a G...
  • CLANG Static Analyzer
    If you aren't using the LLVM/Clang Static Analyzer , you really should be. The Clang Project is an attempt to write a front end for the...
  • A Little Help
    I'm having a problem with OpenGL ES, and it's keeping me from finishing my particle engine post. I was hoping someone here could see...
  • WWDC Accommodations
    Staying downtown in San Francisco is very expensive in the summertime. Bu, if you're going to WWDC, you really want to stay downtown. Yo...
  • Xcode File Templates and a Mystery
    One of the things that confuses many newcomers to Xcode is how to set it up so that your company name gets automatically filled in when you ...
  • Brain Surgery?
    Craig Hockenberry has an interesting post on his blog today about the iPhone background processing issue. Craig speaks from personal experi...
  • Book's Almost Done
    I just finished Chapter 16. I'll give it another read-over in the morning then it will go off to my writing partner for his review, then...
  • iPhone Alley
    Looks like Dave and I are going to make an appearance on the iPhone Alley Podcast next week. We're recording on Sunday night, so I woul...
  • Shuffling Arrays
    Ever want to randomize an array of items? It's a task that, for some reason, I've had to do a lot in recent programs. So, I wrote a ...

Categories

  • 3D Models
  • Ad Hoc Distribution
  • ADC
  • Address Book
  • Amazon
  • Anaglyphs
  • App Store
  • Apple
  • Apple DTS
  • Apple Store
  • Application Store
  • articles
  • Award
  • Background Processing
  • Barcodes
  • Beta
  • Blog
  • Blogger
  • Blogging
  • Blogs
  • Blogspot
  • Book project
  • Bug Reporting
  • Captain Obvious
  • Categories
  • Censorship
  • CFFoundation
  • CGAffineTransform
  • Clang Static Analyzer
  • Cocoa
  • Cocoa Touch
  • Code Reuse
  • Code Signing
  • Computer
  • conferences
  • Controller Classes
  • Core Animation
  • Daring Fireball
  • Database
  • Debugging
  • Defect
  • Delegates
  • Design Awards
  • Developer Certifications
  • Discussion Forums
  • Edit Mode
  • employment opportunities
  • Encryption
  • Enterprise
  • Errata
  • free code
  • Free software
  • Full Screen
  • Game Programming
  • Gestures
  • Getting Started
  • goof
  • Google Code
  • Google Maps
  • Gotcha
  • Help
  • HIG
  • HTTP PUT
  • Idiots
  • Idle Timer
  • Images
  • Instruments
  • Interface Builder
  • iPHone
  • iPhone Applications
  • iPhone Dev Center
  • iPhone Developers
  • iPhone OS 3.0
  • iPhone SDK
  • iPhone SDK PNG
  • iPhone Simulator
  • iPhoneSDK
  • iPod
  • Job Opportunities.
  • k
  • Key Value Observing
  • Keynote
  • KVO
  • Landscape Mode
  • Learn Cocoa
  • Learn Cocoa on the Mac
  • libxml
  • Licensing
  • Mac Developers
  • Mac OS X
  • Macworld Expo
  • Microsoft
  • NDA
  • NeHe
  • New Category
  • New Release
  • NSFileHandle
  • NSMutableArray
  • NSMutableURLRequest
  • NSXML
  • Object-Oriented Design
  • Objective-C
  • Open Source
  • OpenGL ES
  • Optimizations
  • Other blogs
  • Paired Arrays
  • Parsing
  • Particle Engine
  • Party
  • PeopleSoft
  • Performance
  • Persistence
  • Pink Screen of Death
  • Piracy
  • Pixar
  • Podcasts
  • Press Release WTF
  • Press Releases WTF
  • private APIs Google
  • Project Template
  • Properties
  • Random Numbers
  • Rant
  • Rejected
  • Resources
  • Responder Chain
  • REST
  • Reverse Engineering
  • Rumors
  • Runtime
  • Sample Code
  • Screencast
  • screenshot
  • Scroll Views
  • snippet
  • Snow Leopard.
  • SOAP
  • Sockets
  • Source
  • Splash Screen
  • SQLite
  • SQLitePersistentObjects
  • Steve Jobs
  • Steve-Note
  • Strings
  • Stupidity
  • Subversion
  • Table Views
  • Taps
  • Template
  • Tip
  • Tips
  • Tririga
  • tutorials
  • Twitter
  • UIAlertView
  • UIColor
  • UIImage
  • UIPickerView
  • UIScrollView
  • UITextField
  • UIView
  • UIWebView
  • Update
  • Utilities
  • UUID
  • Vacation
  • Version Control
  • Web Services
  • Writing
  • WTF
  • WWDC
  • Xcode
  • XML

Blog Archive

  • ▼  2009 (141)
    • ►  May (14)
    • ▼  April (30)
      • WWDC Has Sold Out
      • Project Template Bugfix
      • OpenGL ES From the Ground Up, Part 3: Viewports in...
      • Learn Cocoa Update
      • Using Instruments to check iPhone Texture Memory U...
      • Something to Make Apple Fan-Boys Turn Rhodamine (P...
      • Another Fine Quarter
      • OpenGL ES From the Ground Up, Part 2: A Look at Si...
      • Out of Pocket
      • Another Apple Store Sighting
      • OpenGL ES From the Ground Up, Part 1: Basic Concepts
      • MarsEdit
      • Crypto Library
      • Wavin' in the Breeze
      • A Different Flag
      • Coming Soon -Another OpenGL Example Ported to iPhone
      • Clark Cox on VLAs
      • WWDC Session Lists are Out
      • Handling Big XML Files on iPhone
      • Creating UIImages from TGA Data
      • Another Microsoft Ad
      • Multi-Row Delete Project in Google Code
      • Apple Design Awards
      • Anti-Piracy Snippet
      • Adding CLANG to Your Build Process
      • Zip & Unzip Objective-C Code
      • Apple's Xcode Team is Hiring
      • Automated Commit and Build Number Incrementing
      • Fundamental Misunderstandings
      • Happy Birthday, Apple, Inc.
    • ►  March (48)
    • ►  February (26)
    • ►  January (23)
  • ►  2008 (163)
    • ►  December (46)
    • ►  November (25)
    • ►  October (44)
    • ►  September (2)
    • ►  August (5)
    • ►  July (2)
    • ►  June (9)
    • ►  May (2)
    • ►  April (11)
    • ►  March (17)
Powered by Blogger.

About Me

Unknown
View my complete profile