过去3天我一直在努力解决这个问题,我无法弄清楚为什么/如何解决因图像过滤导致的内存警告/崩溃。
就是这么简单:用户可以在不同的过滤器之间进行选择,然后保存图片。
我有不同的问题,我设法克服,这是我的最终代码(在那里我删除了一切不重要的东西)。
- (void)viewDidLoad{
// Setting up the filter chain, it's better to do it now to avoid lags
// if we had done it in the "filter" methods, about 3 sec lag.
stillImageSource = [[GPUImagePicture alloc]initWithImage:_photo];
GPUImageBrightnessFilter *soft;
GPUImageContrastFilter *medium;
soft = [[GPUImageBrightnessFilter alloc]init];
medium = [[GPUImageContrastFilter alloc]init];
soft.brightness = -0.5;
medium.contrast = 1.6;
}
- (IBAction)mediumFilter:(id)sender {
[stillImageSource addTarget:medium];
[medium useNextFrameForImageCapture];
[stillImageSource processImage];
//[medium endProcessing]; // Not sure what this does but i've seen it around.
[self.imgPicture setImage:[medium imageFromCurrentFramebuffer]];
[stillImageSource removeAllTargets];
}
- (IBAction)denseFilter:(id)sender {
[stillImageSource addTarget:soft];
[soft addTarget:medium];
[medium useNextFrameForImageCapture];
[stillImageSource processImage];
//[soft endProcessing];
//[medium endProcessing]; // Not sure what this does but i've seen it around.
[self.imgPicture setImage:[medium imageFromCurrentFramebuffer]];
[stillImageSource removeAllTargets];
}
- (IBAction)softFilter:(id)sender {
[stillImageSource addTarget:soft];
[soft useNextFrameForImageCapture];
[stillImageSource processImage];
//[soft endProcessing];
[self.imgPicture setImage:[soft imageFromCurrentFramebuffer]];
[stillImageSource removeAllTargets];
}
用户可以自由选择不同的过滤器。如果他每3秒使用一次,它只会给出内存警告(使用没有正在运行的应用程序的空iPhone 4S)。如果他连续使用3个应用程序崩溃并发出内存警告。
Xcode显示的内存大约为50M,考虑到我们正在处理图像,这是可以的。
我尝试过的: - 如果我在filter方法中分配/初始化图像和过滤器,我设法将其降低到8M。这意味着用户有一个良好的3秒滞后,仍然有内存警告。在过滤方法的最后,我将所有内容都设置为nil,这是间隔的:它不会回到8M,有时会回到8M,但大多数时候它只会堆叠到40到75/80。
使用默认过滤器:它工作正常,但过滤图像大约需要10到15秒。我的用户在他的图像被过滤时将会死亡,这是无法完成的。
将所有内容都归零。不过,在下一个视图中,Xcode内存显示约为70,而这只是常规内存。由于我设法只用8来获取内存警告和崩溃,我很确定GPU内存也是红色的。
缩小尺寸并压缩我正在使用的图像。没有太大变化。它将内存使用量(由Xcode显示)减少到大约45,但在3或4个过滤器后仍然会得到相同的内存警告和崩溃。
注意:如果我走得很慢,我真的可以做我想要的尽可能多的过滤器,我只得到内存警告,但没有崩溃。
我对建议和问题持开放态度,我完全没有想法。它真的只是将最基本的滤镜应用于真正的经典画面。如有必要,我可以显示其他代码。
答案 0 :(得分:7)
以下是我回复您刚刚发送给我的电子邮件的内容:
嗯,这里的一个大问题是你要往返于UIImages。每次执行此操作时,您都会分配一个非常大的图像,并且您不会给我的某些帧缓冲区优化提供运行机会。这将导致大量内存峰值,特别是如果您将这些结果图像设置为UIImageView并因此保持它们。
不是每次要过滤它时都创建一个新的GPUImagePicture,而是创建一次输入GPUImagePicture,并使用addTarget:链接过滤器。用GPUImageView替换你的UIImageView并在那里定位过滤后的图像。当您需要更新过滤器选项时,请更换过滤器或在过滤器上设置新选项,然后在原始源图像上调用-processImage。这将导致所有图像处理完全驻留在GPU上(速度更快),并且内存效率会更高。
我还建议在链中的第一个过滤器上使用-forceProcessingAtSize:或-forceProcessingAtSizeRespectingAspectRatio:并将其设置为视图的目标像素大小。以高于您显示的分辨率处理图像是没有意义的。这也将大大减少过滤时间和内存使用量。当您需要将最终图像捕获到磁盘时,可以将图像大小重置为0,0以删除这些约束并获得全分辨率图像。