2011-07-14 61 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