Texture Loading in Cocoa...

dave05
Unregistered
 
Post: #1
There are so many threads about this, I hate to start a new one unnecessarily... but the method I'm posting below was taken directly from an example provided by apple, and I like its simplicity. However, there are some problems with it...

Code:
-(void) makeTextureFromImage:(NSImage*)theImg forTexture:(GLuint*)texName {

    NSBitmapImageRep* bitmap = [NSBitmapImageRep alloc];
    int samplesPerPixel = 0;
    NSSize imgSize = [theImg size];

    [theImg lockFocus];
    [bitmap initWithFocusedViewRect:NSMakeRect(0.0, 0.0, imgSize.width, imgSize.height)];
    [theImg unlockFocus];

    // Set proper unpacking row length for bitmap.
    glPixelStorei(GL_UNPACK_ROW_LENGTH, [bitmap pixelsWide]);

    // Set byte aligned unpacking (needed for 3 byte per pixel bitmaps).
    glPixelStorei (GL_UNPACK_ALIGNMENT, 1);

     // Generate a new texture name if one was not provided.
    if (*texName == 0)
        glGenTextures (1, texName);
    glBindTexture (GL_TEXTURE_RECTANGLE_EXT, *texName);
    
    // Non-mipmap filtering (redundant for texture_rectangle).
    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER,  GL_LINEAR);
    samplesPerPixel = [bitmap samplesPerPixel];

    // Nonplanar, RGB 24 bit bitmap, or RGBA 32 bit bitmap.
    if(![bitmap isPlanar] && (samplesPerPixel == 3 || samplesPerPixel == 4)) {

        glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0,
            samplesPerPixel == 4 ? GL_RGBA8 : GL_RGB8,
            [bitmap pixelsWide],
            [bitmap pixelsHigh],
            0,
            samplesPerPixel == 4 ? GL_RGBA : GL_RGB,
            GL_UNSIGNED_BYTE,
            [bitmap bitmapData]);
    } else {
        // Don't handle other bitmap formats.
        [NSException raise:@"makeTextureFromImage:forTexture:" format:@"unsupported image format provided"];
    }

    // Clean up.
    [bitmap release];
}

The texture seems to load properly as a valid (GLuint) textureID is returned. However:

1) the image size obtained from the NSImage * object is invalid. The first texture i am attempting to load and display is 128x512 pixels in size. However, the ridiculous Apple-proprietary NSSize structure is actually an array of 2 floats, and it seems that short floating point values cannot accurately represent the number 512.000000, as debugging the application shows the height of 511.935974. In addition, converting this to an integer defaults to truncation so the bitmap is initialized with the OpenGL-incompatible size of 128x511.

Fixing this did not cause the texture to be correctly drawn. Any suggestions? The image file is currently in .PNG format. I am going to try some others...

By the way, if you intend to use this in your code, note that the following line needs to be placed in the awakeFromNib method in your NSOpenGLView subclass:

Code:
[[self openGLContext] makeCurrentContext];


otherwise, all gl*() calls will cause the application to crash. Interesting.

Thanks in advance if anyone can help out!
Quote this message in a reply
Moderator
Posts: 133
Joined: 2008.05
Post: #2
Don't use NSBitmapImageRep, build and use libpng for loading png images. Check out OneSadCookie's code repository for image loading code, this particular gem should prove useful.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #3
NSBitmapImageRep is a highly dangerous way to load textures. Apple sample code notwithstanding, I wouldn't touch it with a barge pole.

NSImage takes DPI into account, maybe that's screwing stuff up? Certainly 512.0f *is* exactly representable as a float.

http://onesadcookie.com/svn/SimpleImage ( and http://onesadcookie.com/svn/SimpleImageCDemo ) is a simple API around libpng/libjpeg, and http://onesadcookie.com/svn/Third-Party builds libpng and libjpeg for all the architectures you have SDKs for.

NSOpenGLView only ensures that its context is current during -drawRect: (and maybe a couple of the other methods it expects you to override). I don't personally like making the context current in other places; if you only have one context in your app it's fine, but as soon as you have more you get into which-is-the-current-context-now hell.
Quote this message in a reply
DoG
Moderator
Posts: 869
Joined: 2003.01
Post: #4
There's pixelsWide and pixelsHigh methods on NSImageRep, which is what you want instead of [imgrep size] in this case.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  iPhone texture loading issue yotryu 0 3,460 Mar 11, 2009 03:40 AM
Last Post: yotryu
  Texture Mapping: Loading a texture from a .bmp file? ishrock 5 6,458 Dec 13, 2008 09:27 AM
Last Post: ThemsAllTook
  OpenGL Texture Loading & Sprites corporatenewt 2 11,117 Jan 30, 2008 12:39 PM
Last Post: ynda20
  Loading and using textures with alpha in OpenGL with Cocoa corporatenewt 4 6,540 Dec 8, 2007 02:06 PM
Last Post: Malarkey
  loading textures - cocoa openGL mDmarco 20 9,559 Aug 28, 2007 08:48 PM
Last Post: OneSadCookie