2013-12-17 165 views
2

我創造模糊圖像我的應用程序的屏幕之一,爲此我使用下面的代碼CGImageRef消耗大量的內存


UIGraphicsBeginImageContext(self.view.bounds.size); 
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()]; 
UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 

CIContext *context = [CIContext contextWithOptions:nil]; 
CIImage *inputImage = [CIImage imageWithCGImage:image.CGImage]; 


CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"]; 
[filter setValue:inputImage forKey:kCIInputImageKey]; 
[filter setValue:[NSNumber numberWithFloat:5] forKey:@"inputRadius"]; 
CIImage *result = [filter valueForKey:kCIOutputImageKey]; 

CGImageRef cgImage = [context createCGImage:result fromRect:[inputImage extent]]; 

blurrImage = [UIImage imageWithCGImage:cgImage]; 
    self.blurrImageView.image = blurrImage; 
    CGImageRelease(cgImage); 


表格上面的代碼我是獲取正確的模糊圖像,但問題在於此線路上的CGImageRef cgImage = [context createCGImage:result fromRect:[inputImage extent]];

高達該行存儲器的使用表示是正常的,但此行存儲器使用量增加後異常高,

聽到的是執行前顯示內存使用的screenchot。內存使用情況是繼續沿着這個方法的執行增加,這是

enter image description here

之前,該行執行後CGImageRef cgImage = [context createCGImage:result fromRect:[inputImage extent]];

enter image description here

是,這是共同的行爲..?我搜索的答案,但我沒有得到,所以任何一個面臨着同樣的問題,請幫我在這

一件事我是「沒有使用ARC」

+0

你的形象有多大?內存分析器在設備或模擬器上運行? – Andrea

+0

沒有這麼多,但在執行此方法後內存使用量有所增加 –

+0

第二個UIGraphicsGetImageFromCurrentImageContext()是一個私有API,如果您想要提交到AppStore – Andrea

回答

1

我遇到了與Core Image相同的內存消耗問題。

如果您正在尋找替代品,在iOS 7中,您可以使用UIImage+ImageEffects類別,該類別作爲iOS_UIImageEffects項目的一部分在WWDC 2013 sample code頁面提供。它提供了一些新的方法:

- (UIImage *)applyLightEffect; 
- (UIImage *)applyExtraLightEffect; 
- (UIImage *)applyDarkEffect; 
- (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor; 
- (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage; 

這些不會遇到您遇到的與核心映像有關的內存消耗問題。 (另外,這是一個更快的模糊算法。)

該技術在WWDC 2013視頻Implementing Engaging UI on iOS中有說明。

+0

感謝羅布它是真正有用的... :) –

+0

@Shan BTW,我注意到,如果你使用的核心圖像過濾器第二次,你看不到的內存(比最終圖像等)進一步消耗,所以顯然這內存使用本身不是泄漏,而是一些內部工作緩存或類似的東西。它看起來像使用Core Image過濾器進行業務的成本。但是'UIImage + ImageEffects'完全繞過了這個問題。 – Rob

+0

感謝它工作正常.. :) :) –

1

事實上你正在使用的截圖可以改變記憶在視網膜顯示器上的使用可能更多的是正常的設備。在我看來,加倍是好的,因爲你有原始的UIImage和模糊圖像生活在內存中,也許上下文會保留一些內存。我做一個猜想:

  • 您使用的是大量的自動釋放的對象,他們將留在記憶 直到池排出,儘量包裹代碼在 autoreleaseblock


@autoreleasepool{ 
UIGraphicsBeginImageContext(self.view.bounds.size); 
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()]; 
UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 

CIContext *context = [CIContext contextWithOptions:nil]; 
CIImage *inputImage = [CIImage imageWithCGImage:image.CGImage]; 


CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"]; 
[filter setValue:inputImage forKey:kCIInputImageKey]; 
[filter setValue:[NSNumber numberWithFloat:5] forKey:@"inputRadius"]; 
CIImage *result = [filter valueForKey:kCIOutputImageKey]; 

CGImageRef cgImage = [context createCGImage:result fromRect:[inputImage extent]]; 

blurrImage = [UIImage imageWithCGImage:cgImage]; 
    self.blurrImageView.image = blurrImage; 
    CGImageRelease(cgImage); 
} 
+0

感謝您的建議我會改變「UIGraphicsGetImageFromCurrentImageContext()」,我會找到替代的解決方案...... thnks ... :) –

+1

沒有,只是在'@ autoreleasepool'扔將無法完成在這種情況下任何東西。在回退到運行循環之前,在嘗試緩解高水位標記問題時做這些工作很有用,但這不是問題。此外,Shan還抓住了非視網膜快照(因爲他沒有使用UIGraphicsBeginImageContextWithOptions),所以我不認爲視網膜對非視網膜是一個問題。 – Rob

+0

嗨@Rob爲什麼不呢?我們有2個自動發佈的圖像:圖像和blurrImage,在游泳池的盡頭不應該隨游泳池排水而被釋放? – Andrea