如何以正确的方式加载和卸载图像

时间:2011-07-14 16:45:43

标签: iphone image memory

我的iPhone应用中的图像有问题。我按如下方式加载图像:

UIImage *image = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:name ofType:@""]];

CGImageRef imageRef = image.CGImage;
NSInteger texWidth = CGImageGetWidth(*imageRef);
NSInteger texHeight = CGImageGetHeight(*imageRef);
GLubyte *textureData = (GLubyte *)malloc(texWidth * texHeight * 4);
CGContextRef textureContext = CGBitmapContextCreate(textureData, texWidth, texHeight, 8,
                                          texWidth * 4, CGImageGetColorSpace(*imageRef),
                                          kCGImageAlphaPremultipliedLast);


CGContextDrawImage(textureContext, CGRectMake(0.0, 0.0, (float)texWidth,
                                              (float)texHeight), *imageRef);
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);

我想释放图片使用的所有内存。我试着这样做:

CGImageRelease(imageRef);
free(image);

但是,根据Instruments,内存似乎没有被释放。我错过了什么吗?它是否被其中一个功能缓存?此外,当我稍后重新加载图像时,它似乎被加载两次,即alpha通道是第一次加载的两倍。而且,当我(尝试)释放内存并第三次重新加载时,alpha通道是第一次的三倍。应该几乎透明的部分变得越来越不透明。

iOS 3中没有注意到透明度的问题,只有iOS 4.但两者都注意到内存未被释放的问题。

请有人帮我这个吗?我花了很多时间搞乱图像!此外,我认为我没有使用愚蠢的图像:我正在制作一个使用大约40张图像的游戏,其中大多数是128x128 PNG。为什么我这么快就耗尽了内存?这种情况的“常见”做法是什么?在不需要图像时我是否正确地试图释放内存?

回复将不胜感激!谢谢。

2 个答案:

答案 0 :(得分:1)

使用OpenGL时释放内存的答案很简单:http://www.opengl.org/sdk/docs/man/xhtml/glDeleteTextures.xml

与释放OpenGL使用的纹理相比,释放UIImage使用的内存几乎不可见。问题在于以下代码:

GLuint textures[100]; // allows total of 100 textures

location = textures[imageNo];

glBindTexture(GL_TEXTURE_2D, location);

它通过以下方式解决:

void unloadImage(GLuint imageNo)
{
    [textureImages[imageNo] release];
    glDeleteTextures(1, &textures[imageNo]);
}

我真的希望这对于在iPhone上使用OpenGL纹理的其他人来说非常有用,因为它让我在圈子中玩了很长时间!

感谢@sergio帮助解决了我的问题!

答案 1 :(得分:0)

我认为你应该这样做:

[image release];

而不是

CGImageRelease(imageRef);

实际上,您分配的对象是image,然后您可以获得对其中一个成员的引用;您不需要释放对成员的引用,而是释放您分配的原始对象。您无需致电free(*image);

编辑:

*image*imageRef的所有使用对我来说都不正确;您应该使用imageimageRef

CGImageRef imageRef = image.CGImage;
NSInteger texWidth = CGImageGetWidth(imageRef);
NSInteger texHeight = CGImageGetHeight(imageRef);
GLubyte *textureData = (GLubyte *)malloc(texWidth * texHeight * 4);
CGContextRef textureContext = CGBitmapContextCreate(textureData, texWidth, texHeight, 8,
                                      texWidth * 4, CGImageGetColorSpace(imageRef),
                                      kCGImageAlphaPremultipliedLast);

CGContextDrawImage(textureContext, CGRectMake(0.0, 0.0, (float)texWidth,
                                          (float)texHeight), imageRef);
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);

关于内存消耗:我认为使用OpenGLES框架可能会产生固定的损失,即增加应用程序的总内存占用量(由于加载框架并实例化我不知道哪些对象);但是每次绘制纹理时都不应该出现意外的内存增加。