Can't Use PNG For OpenGL Textures

Discussion in 'Mac Programming' started by davbeck, Dec 14, 2008.

  1. davbeck macrumors regular

    Joined:
    May 16, 2008
    Location:
    Reno, NV
    #1
    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.

    Code:
    - (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];
    }
     
  2. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #2
    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.
     
  3. davbeck thread starter macrumors regular

    Joined:
    May 16, 2008
    Location:
    Reno, NV
    #3
    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.
     

    Attached Files:

  4. lazydog macrumors 6502a

    Joined:
    Sep 3, 2005
    Location:
    Cramlington, UK
    #5
    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
     
  5. davbeck thread starter macrumors regular

    Joined:
    May 16, 2008
    Location:
    Reno, NV
    #6
    Why would the dimensions need to be power of two? That seems like a huge disadvantage.
     
  6. davbeck thread starter macrumors regular

    Joined:
    May 16, 2008
    Location:
    Reno, NV
    #7
    I finally got it working using imageio. I am posting the function for future generations.

    Code:
    - (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);
    }
     
  7. Krevnik macrumors 68030

    Krevnik

    Joined:
    Sep 8, 2003
    #8
    You can get rid of the warning by using an explicit type cast, like so:
    Code:
    	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.
     
  8. lazydog macrumors 6502a

    Joined:
    Sep 3, 2005
    Location:
    Cramlington, UK
    #9
    Yes, I guess that's why GL_TEXTURE_RECTANGLE_ARB etc was introduced!
    b e n
     

Share This Page