PDA

View Full Version : Can't Use PNG For OpenGL Textures




davbeck
Dec 14, 2008, 06:16 PM
I am trying to figure out this crazy world of OpenGL, specifically on mac and iphone.

I have a function that takes a path to a image and turns it into an opengl texture. bmp seems to work fine but not png. The problem is that when I use NSBitmapImageRep to get the pixel data which represents it as having one pane. the cautionary if statement blocks any weird stuff from happening.

- (void)textureFromPath:(NSString *)path textureID:(GLuint *)texName {
NSBitmapImageRep *bitmap = [NSBitmapImageRep imageRepWithContentsOfFile:path];
int samplesPerPixel = 0;

//glPixelStorei(GL_UNPACK_ROW_LENGTH, [bitmap pixelsWide]); // 4
//glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // 5
if (*texName == 0)
glGenTextures (1, texName);

glBindTexture(GL_TEXTURE_2D, *texName);
//glBindTexture(GL_TEXTURE_RECTANGLE_ARB, *texName);

glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
samplesPerPixel = [bitmap samplesPerPixel];

if(![bitmap isPlanar] &&
(samplesPerPixel == 3 || samplesPerPixel == 4)) {
glTexImage2D(GL_TEXTURE_2D, //GL_TEXTURE_RECTANGLE_ARB,
0,
samplesPerPixel == 4 ? GL_RGBA8 : GL_RGB8,
[bitmap pixelsWide],
[bitmap pixelsHigh],
0,
samplesPerPixel == 4 ? GL_RGBA : GL_RGB,
GL_UNSIGNED_BYTE,
[bitmap bitmapData]);
}
[bitmap release];
}



kainjow
Dec 14, 2008, 09:52 PM
Not sure about the png issue, but the [bitmap release] is incorrect as bitmap is an autoreleased object and calling release without a retain will cause it to crash later when it gets released by the autorelease pool.

davbeck
Dec 14, 2008, 10:05 PM
Now that you mention it, it should crash later but it doesn't. curious.

I have attached an example of what happens when I try to bring in a png.

kainjow
Dec 14, 2008, 10:24 PM
This thread might be of help:
http://www.idevgames.com/forum/showthread.php?t=13452

lazydog
Dec 15, 2008, 04:28 AM
Hi
It looks to me like your image needs to be inverted… OpenGL uses the bottom left corner as ( 0, 0 ). The shearing effect might be because your image is using padding bytes at the end of each row, or the dimensions aren't a power of two.

b e n

davbeck
Dec 15, 2008, 11:58 AM
Why would the dimensions need to be power of two? That seems like a huge disadvantage.

davbeck
Dec 15, 2008, 12:37 PM
I finally got it working using imageio. I am posting the function for future generations.

- (void)textureFromPath:(NSString *)path textureID:(GLuint *)texName {
CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, NO);
//xCode troughs a warning about using NSString instead of CFString but since they are compatible it works anyway.

CGImageSourceRef myImageSourceRef = CGImageSourceCreateWithURL(url, NULL);
CGImageRef myImageRef = CGImageSourceCreateImageAtIndex (myImageSourceRef, 0, NULL);
size_t width = CGImageGetWidth(myImageRef);
size_t height = CGImageGetHeight(myImageRef);

CGRect rect = {{0, 0}, {width, height}};
void * myData = calloc(width * 4, height);
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGContextRef myBitmapContext = CGBitmapContextCreate (myData,
width, height, 8,
width*4, space,
kCGBitmapByteOrder32Host |
kCGImageAlphaPremultipliedFirst);
CGContextDrawImage(myBitmapContext, rect, myImageRef);
CGContextRelease(myBitmapContext);
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1, texName);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, *texName);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA8,
width, height,
0,
GL_BGRA_EXT,
GL_UNSIGNED_INT_8_8_8_8_REV,
myData);
free(myData);
}

Krevnik
Dec 15, 2008, 12:50 PM
CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, NO);
//xCode troughs a warning about using NSString instead of CFString but since they are compatible it works anyway.


You can get rid of the warning by using an explicit type cast, like so:

CFURLRef url = CFURLCreateWithFileSystemPath(NULL, (CFStringRef)path, kCFURLPOSIXPathStyle, NO);


Both types are pointers, so it will work. It will rid you of one more warning to worry about.

lazydog
Dec 15, 2008, 12:55 PM
Why would the dimensions need to be power of two? That seems like a huge disadvantage.

Yes, I guess that's why GL_TEXTURE_RECTANGLE_ARB etc was introduced!
b e n