1

I have an iPhone game that uses images to display things such as buttons on screen to control the game. The images aren't huge, but I want to load them "lazily" and unload them from memory when they are not being used.

I have a function that loads images as follows:

void loadImageRef(NSString *name, GLuint location, CGImageRef *textureImage)
{
    *textureImage = [UIImage imageNamed:name].CGImage;

    if (*textureImage == nil) {
        NSLog(@"Failed to load texture image");
        return;
    }

    NSInteger texWidth = CGImageGetWidth(*textureImage);
    NSInteger texHeight = CGImageGetHeight(*textureImage);

    GLubyte *textureData = (GLubyte *)malloc(texWidth * texHeight * 4);

    CGContextRef textureContext = CGBitmapContextCreate(textureData,
                                                        texWidth, texHeight,
                                                        8, texWidth * 4,
                                                        CGImageGetColorSpace(*textureImage),
                                                        kCGImageAlphaPremultipliedLast);

    CGContextTranslateCTM(textureContext, 0, texHeight);
    CGContextScaleCTM(textureContext, 1.0, -1.0);

    CGContextDrawImage(textureContext, CGRectMake(0.0, 0.0, (float)texWidth, (float)texHeight), *textureImage);
    CGContextRelease(textureContext);

    glBindTexture(GL_TEXTURE_2D, location);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);

    free(textureData);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}

The reason I pass the CGImageRef to the function is so that I can free it later. But I don't know if this is the correct thing to do?

I call the function as follows (for example):

loadImageRef(@"buttonConfig.png", textures[IMG_CONFIG], &imagesRef[IMG_CONFIG]);

And when I'm finished with it I unload it as follows:

unloadImage(&imagesRef[IMG_CONFIG]);

which calls the function:

void unloadImage(CGImageRef *image)
{
    CGImageRelease(*image);
}

But when I run the app, I get EXC_BAD_ACCESS error, either when unloading, or loading for the second time (i.e. when it is needed again). I don't see anything else to help determine the real cause of the problem.

Perhaps I am attacking this issue from the wrong angle. What is the usual method of lazy loading of images, and what is the usual way to unload the image to free up the memory?

Many thanks in advance,

Sam

4

1 回答 1

1

如果你想确保事情不会被缓存,你应该不惜一切代价避免使用 [UIImage imageNamed:name] 方法。imageNamed 缓存它通过的所有图像。你想用

UIImage *image = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:fileNameWithoutExtension ofType:fileNameExtension]];

这样,您可以在完成后简单地释放对象并释放内存。

Apple 已经使用 [UIImage imageNamed:] 改进了缓存,但它仍然不是按需提供的。

于 2011-06-01T15:10:06.517 回答