2011-07-14 58 views
1

我在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); 

但是,内存不会出现根据仪器被释放。我错过了什么吗?它被这些函数之一缓存了吗?此外,当我稍后重新载入图像时,它似乎会被加载两次,即alpha通道是第一次的两倍。再次,当我(试图)释放内存并重新加载第三次时,alpha通道是第一次的三倍。应该是几乎透明的部分变得越来越不透明。

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

请有人可以帮助我吗?我花了很多时间搞乱图像!此外,我不认为我使用了一个愚蠢的图像:我正在制作一个使用大约40张图像的游戏,其中大部分是128x128 PNG。我如何快速用完内存?这种情况下的“常见”做法是什么?当我不需要图像时,我是否试图释放内存?

回覆将不胜感激!谢谢。

回答

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框架可能精确定额罚款,即提高应用的整体内存占用(由于装载框架和实例我不知道哪些物体);但每次绘制纹理时都不会遇到意想不到的内存增加。

+0

我用[image release]取代了免费版,但问题仍然存在。看起来和以前完全一样。有任何想法吗? – Sam

+0

此外,当我释放图像时,仍然可以在屏幕上看到它(它是对象的纹理)。是否有任何openGL函数缓存图像?肯定有东西缓存了它,因为它仍然可见!非常感谢! – Sam

+0

经过更多调查后,我发现512 * 512 PNG图像的磁盘上有大小为86 KB(在Finder中)。那么为什么它会在应用程序中占用超过3 MB的内存呢?我删除了调用加载该图像的函数(上面粘贴的所有东西)后,在它上面运行了Profiler/Instruments,并且它稳定在3.51 MB“Live Bytes”,但是如果函数被调用(它肯定只会调用一次, NSLogged它),那么“Live Bytes”稳定在6.80 MB。请帮忙!!为什么它会占用如此多的内存? – Sam

1

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

释放由UIImage的使用的存储器相比,释放由OpenGL的使用的纹理是几乎没有明显的。问题就出在下面的代码:

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谁帮助我的问题!

+0

很好知道,谢谢! +1 – sergio

+0

这也意味着你可以释放的UIImage CGContextDrawImage后(即不必等到你实际上与图像结束)。这对某些人来说可能是显而易见的,但我花了很多时间试图找出为什么释放UIImage没有释放内存! – Sam