【问题标题】:CGImageRef consumes lot of memoryCGImageRef 消耗大量内存
【发布时间】:2014-01-04 19:14:18
【问题描述】:

我正在为我的一个应用程序屏幕创建模糊图像,为此我使用以下代码


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]];

到此行内存使用显示正常,但此行内存使用增加异常高,

hear 是执行前显示的内存使用截图。内存使用随着这个方法的执行而不断增加,这是之前的

这在执行CGImageRef cgImage = [context createCGImage:result fromRect:[inputImage extent]];行之后

这是常见的行为吗..?我搜索了答案,但我没有得到,所以任何人都面临同样的问题,请帮助我解决这个问题

一件事我“不使用 ARC”

【问题讨论】:

  • 你的图片有多大?内存分析器是在设备还是模拟器上运行?
  • 不多,但执行此方法后内存使用量有所增加
  • 第二个 UIGraphicsGetImageFromCurrentImageContext() 是一个私有API,如果你想提交到AppStore,你的应用可能会被拒绝
  • 正如您在屏幕截图中看到的,在执行这一行代码后,内存使用量几乎翻了一番,
  • 有没有其他方法可以做到这一点...?

标签: ios iphone cgimageref cifilter uigraphicscontext


【解决方案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;

这些不会受到您在使用 Core Image 时遇到的内存消耗问题的影响。 (另外,它是一种更快的模糊算法。)

这项技术在 WWDC 2013 视频Implementing Engaging UI on iOS 中有说明。

【讨论】:

  • @Shan BTW,我注意到如果您第二次使用 Core Image 过滤器,您不会看到内存的进一步消耗(最终图像除外),因此显然这种内存使用不是泄漏,本身,而是一些内部工作缓存或类似的东西。这看起来像是使用 Core Image 过滤器做生意的成本。但是UIImage+ImageEffects 完全绕过了这个问题。
【解决方案2】:

您使用屏幕截图的事实可能会改变内存使用情况,Retina 显示器可能比普通设备更多。在我看来,加倍是可以的,因为你有原始的 UIImage 和模糊图像存在于内存中,可能上下文也会保留一些内存。我猜:

  • 您正在使用大量自动释放的对象,它们将留在内存中 直到池被耗尽,尝试将代码包装在 自动释放块


@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);
}

【讨论】:

  • 感谢您的建议,我将更改“UIGraphicsGetImageFromCurrentImageContext()”,我会找到替代解决方案...谢谢... :)
  • 不,在这种情况下仅仅输入@autoreleasepool 不会完成任何事情。这在尝试缓解高水位标记问题时非常有用,因为在返回运行循环之前做了很多事情,但这不是这里的问题。此外,Shan 正在抓取非视网膜快照(因为他没有使用 UIGraphicsBeginImageContextWithOptions),所以我认为视网膜 v 非视网膜在这里不是问题。
  • 嗨@Rob 为什么不呢?我们有 2 个自动释放的图像:image 和 blurrImage,在池的末端不应该随池排放一起释放吗?
  • 因为一旦此方法完成,您将返回到运行循环,此时池已经为您排空,因此显式声明的池是多余的。现在,如果您有一些 for 循环,其中您正在模糊整个系列的图像(例如,一个接一个地重复模糊一个图像而不会在每个图像之后屈服于运行循环),那么显式声明的池可能很有用。但是在这种情况下,它是多余的,并且代表了对问题的概念误解,即即使在耗尽池之后,Core Image 也没有释放内存。
猜你喜欢
  • 1970-01-01
  • 2022-01-16
  • 2012-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多