iDevGames Forums
Best way to deal with loading textures? - Printable Version

+- iDevGames Forums (http://www.idevgames.com/forums)
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: Graphics & Audio Programming (/forum-9.html)
+--- Thread: Best way to deal with loading textures? (/thread-3457.html)



Best way to deal with loading textures? - bronxbomber92 - Feb 28, 2007 07:07 PM

Hey, I was wondering what is the best way to deal with loading textures API wise? I want to keep this ias portable as possible, though I wouldn't mind writing two versions, one for Mac OS X, and the other for my other targeted platform (PlayStation Portable).

If I went portable, what would I use? libpng?

If I went OS specific, for Mac, could I use Quartz or Cocoa to load the image (preferably Quartz)?

Thanks


Best way to deal with loading textures? - OneSadCookie - Feb 28, 2007 07:15 PM

If you want portable, libpng or libjpeg are the obvious choices, though there's also FreeImage which wraps libpng, libjpeg, libtiff and a few others.

If you want Mac-only, Quartz or ImageIO (nearly the same thing) will do the job, as long as you don't care about 10.3 compatibility. If you want 10.3 compatibility, you'll need to use QuickTime instead.


Best way to deal with loading textures? - bronxbomber92 - Feb 28, 2007 07:41 PM

All right, thanks Smile


Best way to deal with loading textures? - TomorrowPlusX - Mar 1, 2007 08:16 AM

OSC: Can you clarify the difference between Quartz and ImageIO? I've read over apple docs over and over and I've never once seen a reference to ImageIO. All I see are CG* methods.


Best way to deal with loading textures? - bronxbomber92 - Mar 1, 2007 03:15 PM

Here ya go: http://developer.apple.com/graphicsimaging/workingwithimageio.html


Best way to deal with loading textures? - TomorrowPlusX - Mar 1, 2007 03:26 PM

bronxbomber92 Wrote:Here ya go: http://developer.apple.com/graphicsimaging/workingwithimageio.html

So, the CG* functions are imageio. That's too bad, I was hoping I was missing something. You can't load a 32-bit PNG without getting your color channels pre-multiplied using those methods. This means I can't use a normal/specular map in one texture.

That being said, I just use libPNG. But it sure would be nice if Apple's image loaders would let you get bitmap data unmodified.


Best way to deal with loading textures? - OneSadCookie - Mar 1, 2007 03:26 PM

ImageIO is a part of Quartz, basically. It was introduced in 10.4.

There is a new simple API in Quartz that you can call to open any image file, which calls through to ImageIO underneath, or you can use the ImageIO APIs yourself for maximum control.


Best way to deal with loading textures? - OneSadCookie - Mar 1, 2007 03:33 PM

TomorrowPlusX Wrote:So, the CG* functions are imageio. That's too bad, I was hoping I was missing something. You can't load a 32-bit PNG without getting your color channels pre-multiplied using those methods. This means I can't use a normal/specular map in one texture.

Not so much true that it couldn't happen (Quartz supports nonpremultiplied images) as that you have no choice (ImageIO doesn't appear to have a flag to premultiply or not when creating the CGImage)...


Best way to deal with loading textures? - ThemsAllTook - Mar 1, 2007 04:43 PM

TomorrowPlusX Wrote:You can't load a 32-bit PNG without getting your color channels pre-multiplied using those methods.
I've managed it. What I had to do was load the nonpremultiplied RGB channels in with one function call, load the alpha channel with a separate function call, and stitch the bytes together afterward. I don't have the code on me at the moment, but I'll paste it here as soon as I get home...


Best way to deal with loading textures? - ThemsAllTook - Mar 1, 2007 10:16 PM

ThemsAllTook Wrote:I'll paste it here as soon as I get home...
...and here it is:

Code:
CGImageSourceRef imageSource;
  CGImageRef image;
  CGContextRef bitmapRenderContext;
  unsigned char * pixels;
  unsigned char * alphaChannel;
  int pixelIndex;
  
  imageSource = CGImageSourceCreateWithURL((CFURLRef) [NSURL fileURLWithPath: filePath], NULL);
  if (imageSource == NULL) {
    [self release];
    return nil;
  }
  
  image = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL);
  CFRelease(imageSource);
  if (image == NULL) {
    [self release];
    return nil;
  }
  
  width = CGImageGetWidth(image);
  height = CGImageGetHeight(image);
  pixels = (unsigned char *) malloc(4 * width * height);
  
  bitmapRenderContext = CGBitmapContextCreate(pixels,
                                              width,
                                              height,
                                              8,
                                              width * 4,
                                              CGColorSpaceCreateDeviceRGB(),
                                              kCGImageAlphaNoneSkipLast);
  CGContextDrawImage(bitmapRenderContext, (CGRect) {{0, 0}, {width, height}}, image);
  CGContextRelease(bitmapRenderContext);
  
  alphaChannel = (unsigned char *) calloc(width, height);
  bitmapRenderContext = CGBitmapContextCreate(alphaChannel,
                                              width,
                                              height,
                                              8,
                                              width,
                                              NULL,
                                              kCGImageAlphaOnly);
  CGContextDrawImage(bitmapRenderContext, (CGRect) {{0, 0}, {width, height}}, image);
  CGContextRelease(bitmapRenderContext);
  
  for (pixelIndex = 0; pixelIndex < (width * height); pixelIndex++) {
    pixels[(pixelIndex * 4) + 0] = ((pixels[(pixelIndex * 4) + 0] * (alphaChannel[pixelIndex] + 1)) >> 8);
    pixels[(pixelIndex * 4) + 1] = ((pixels[(pixelIndex * 4) + 1] * (alphaChannel[pixelIndex] + 1)) >> 8);
    pixels[(pixelIndex * 4) + 2] = ((pixels[(pixelIndex * 4) + 2] * (alphaChannel[pixelIndex] + 1)) >> 8);
    pixels[(pixelIndex * 4) + 3] = alphaChannel[pixelIndex];
  }
  free(alphaChannel);



Best way to deal with loading textures? - TomorrowPlusX - Mar 2, 2007 07:46 AM

Hey, that's brilliant! I'm going to give it a stab, since I feel "icky" bloating my framework with libPNG.

Thanks!

EDIT: I think it's amusing you're manually pre-multiplying at the end. Rasp


Best way to deal with loading textures? - TomorrowPlusX - Mar 2, 2007 01:17 PM

Interestingly, even with your manual pre-multiplication code removed, I'm seeing pre-multiplication halos on alpha transparent PNGs.

It's neat code, nonetheless.


Best way to deal with loading textures? - socisub - Mar 10, 2007 06:27 PM

I just disovered this from GLSLShowpiece at developers.apple.com. Look for NSBitmapImageRep *LoadImage(NSString *path, int shouldFlipVertical) function. It even works for a png with alpha!

Code:
NSImage *image = [[NSImage alloc] initWithContentsOfFile: aPath];
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithData:[image TIFFRepresentation]];
unsigned char *data = [bitmap bitmapData];



Best way to deal with loading textures? - tigakub - May 4, 2007 01:01 PM

Why is NSBitmapImageRep not recommended? Doesn't it just call down to Quartz?


Best way to deal with loading textures? - OneSadCookie - May 4, 2007 05:31 PM

NSBitmapImageRep is fine if you create it yourself with the initializer that takes about 17 parameters, because that way you know that you have the data in a format that's useful for OpenGL.

No other way of creating an NSBitmapImageRep makes any such guarantee. The image could be planar; could have alpha or not; could have 8- 16- or 32-bit channels, could have floating-point channels, etc. Even detecting whether the image is useful for OpenGL and deciding how to pass the data in is not easy, and when it's not, what do you do then? There's no way to blit from an NSBitmapImageRep of useless format to one of known good format...

You must also not assume that just because it returns a good format for your particular image on your particular OS/hardware combination, that it will return the same format for that image on every OS/hardware combination. People who did that got bit with the 10.3-10.4 transition when Apple changed the formats NSBitmapImageRep preferred to use. They will change their minds again.