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;
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));
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;
}
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
11 comments:
You are missing a library if this example is expected to work. I'm compiling against the standard set of libraries and frameworks an OpenGL application would provide.
Building target “MyProject” of project “MyProject” with configuration “Debug” — (5 errors)
cd /Users/todd/Desktop/MyProject
setenv MACOSX_DEPLOYMENT_TARGET 10.5
setenv PATH "/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 -arch i386 -isysroot /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.0.sdk -L/Users/todd/Desktop/MyProject/build/Debug-iphonesimulator -F/Users/todd/Desktop/MyProject/build/Debug-iphonesimulator -filelist /Users/todd/Desktop/MyProject/build/MyProject.build/Debug-iphonesimulator/MyProject.build/Objects-normal/i386/MyProject.LinkFileList -mmacosx-version-min=10.5 -framework UIKit -framework OpenGLES -framework QuartzCore -framework Foundation -o /Users/todd/Desktop/MyProject/build/Debug-iphonesimulator/MyProject.app/MyProject
Undefined symbols:
"_CGImageRelease", referenced from:
+[UIImage(Targa) imageWithRawRGBAData:width:height:] in UIImage_Targa.o
"_CGImageCreate", referenced from:
+[UIImage(Targa) imageWithRawRGBAData:width:height:] in UIImage_Targa.o
"_CGColorSpaceCreateDeviceRGB", referenced from:
+[UIImage(Targa) imageWithRawRGBAData:width:height:] in UIImage_Targa.o
"_CGDataProviderRelease", referenced from:
+[UIImage(Targa) imageWithRawRGBAData:width:height:] in UIImage_Targa.o
"_CGDataProviderCreateWithData", referenced from:
+[UIImage(Targa) imageWithRawRGBAData:width:height:] in UIImage_Targa.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
"_CGImageRelease", referenced from:
+[UIImage(Targa) imageWithRawRGBAData:width:height:] in UIImage_Targa.o
"_CGImageCreate", referenced from:
+[UIImage(Targa) imageWithRawRGBAData:width:height:] in UIImage_Targa.o
"_CGColorSpaceCreateDeviceRGB", referenced from:
+[UIImage(Targa) imageWithRawRGBAData:width:height:] in UIImage_Targa.o
"_CGDataProviderRelease", referenced from:
+[UIImage(Targa) imageWithRawRGBAData:width:height:] in UIImage_Targa.o
"_CGDataProviderCreateWithData", referenced from:
+[UIImage(Targa) imageWithRawRGBAData:width:height:] in UIImage_Targa.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
Build failed (5 errors)
You must be compiling under an older version of the SDK that doesn't automatically link the CoreGraphics.framework into your project.
You mention that you think that UIImage converts the data back to BGRA. I don't know for sure, but I think that CGImage leaves the data in the byte order you specify. However, it's not obvious how to specify a byte order.
The trick is the CGBitmapInfo passed to CGImageCreate. The combination of byte order and alpha info determines the specific byte ordering. kCGBitmapByteOrderDefault is RGB (I think). kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast is RGBA.
kCGBitmapByteOrder32Little is BGR. kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst is BGRA.
Armed with that knowledge, you can probably skip the byte flipping, create the bitmap with the appropriate flags, jam the data into the bitmap, and draw the image at full speed.
This post on the Apple mailing list was useful to me.
What type of .tga files you've used?
I've tried your code with 16 bit, 24 bit and 32 bit uncompressed tgas exported from Photoshop cs2, and none worked (it would display a gray image, nothing in it). I've tried your logo.tga from google code but it crashes telling it will not support compressed tgas (your error in console with some numbers).
Hi Good day to all.....
This is Gopal. I'm new to iphone application development. In one application i need to access a image when i touch on the iphone, that perticular x,y co-ordination values and background image pixel(co-ordinate)colur of an image with respect the co-ordinates.
those co-ordinate need to place in a buffer.
from that buffer create i need to create provider.
using these i want to generate CGImage.
from CGImage i need to convert it in to UIImage format.
so i can utilize this is in my application. please any body can help me out from this......????
Thanq.
scrub m65 kamagra attorney lawyer body scrub field jacket lovegra marijuana attorney injury lawyer
Above you say :
"you probably want to skip this category altogether and just load the bitmap data into OpenGL directly."
Do you know how to do that? Has this been covered before?
Thanks.
What youre saying is completely true. I know that everybody must say the same thing, but I just think that you put it in a way that everyone can understand. I also love the images you put in here. They fit so well with what youre trying to say. Im sure youll reach so many people with what youve got to say.
Arsenal vs Huddersfield Town live streaming
Arsenal vs Huddersfield Town live streaming
Wolverhampton Wanderers vs Stoke City Live Streaming
Wolverhampton Wanderers vs Stoke City Live Streaming
Notts County vs Manchester City Live Streaming
Notts County vs Manchester City Live Streaming
Bologna vs AS Roma Live Streaming
Bologna vs AS Roma Live Streaming
Juventus vs Udinese Live Streaming
Juventus vs Udinese Live Streaming
Napoli vs Sampdoria Live Streaming
Napoli vs Sampdoria Live Streaming
Fulham vs Tottenham Hotspur Live Streaming
Fulham vs Tottenham Hotspur Live Streaming
AS Monaco vs Marseille Live Streaming
AS Monaco vs Marseille Live Streaming
Alajuelense vs Perez Zeledon Live Streaming
Alajuelense vs Perez Zeledon Live Streaming
Technology News | News Today | Live Streaming TV Channels
Hi!
Great work on the targa loader, I am using it in an upcoming game to allow me to have large animations stored as targas (which when zipped are tiny compared to pbgs, yay uncompressed image formats).
Anyway,
I ran into quite a large memory leak, which I have fixed:
In the method imageFromTGAData, you are calling imageData = (unsigned char *)malloc(newDataLength);
With no corresponding call to free.
I added free(imageData) just above the return, and it solved the leak. (Before the fix, my app's memory footprint was growing 500kb every 12th of a second due to on the fly tga loading).
Also:
For TGA alpha, you can change:
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
To
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault|kCGImageAlphaLast;
Hope this helps.
Regards,
Owen
Hello,
Before you make any hirings, you should be well aware of all the terms and conditions laid down by the iPhone development company, along with the payment details, so that you do not have to face any problems at the later stage of development.
Hire iphone Developer
Post a Comment