GPUImageFilter vs CIFilter(GPUImage的内存问题)

时间:2013-12-26 22:42:03

标签: objective-c gpuimage cifilter

GPUImage有内存问题吗?下面有两个不同的Vignette滤镜效果代码。第一个(Apple的CI过滤器)使用19 MB内存,而GPUImage使用超过75 MB。我的代码出了什么问题?

带有CIFilter的暗角滤镜

CIImage *ciImage = [[CIImage alloc] initWithImage:image];
CIFilter *filter = [CIFilter filterWithName:@"CIVignetteEffect" keysAndValues:kCIInputImageKey, ciImage, nil];

CIContext *context = [CIContext contextWithOptions:nil];
CIImage *outputImage = [filter outputImage];
CGImageRef cgImage = [context createCGImage:outputImage fromRect:[outputImage extent]];

UIImage *result = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);

return result;

这是GPUImage版本:

GPUImageFilter * f = [[GPUImageVignetteFilter alloc] init];
UIImage *result = [f imageByFilteringImage:image];

return result;

我在项目中使用“ARC”。你有什么主意吗?我该怎么做才能“释放”GPUImage过滤内存?

1 个答案:

答案 0 :(得分:1)

对于上面代码中的GPUImage方法,内存中会短暂存在四个图像副本:原始UIImage及其字节,此图像在GPU上传到的纹理,过滤操作的结果,以及由于该操作而创建的UIImage及其字节。

上面使用的便捷方法可能很简单,但它们并不是减少内存压力的最佳方法。相反,我会尝试以下内容:

GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithImage:image smoothlyScaleOutput:NO];
GPUImageVignetteFilter *vignetteFilter = [[GPUImageVignetteFilter alloc] init];
[stillImageSource addTarget:vignetteFilter];
[stillImageSource prepareForImageCapture];
[stillImageSource processImage];
UIImage *result = [vignetteFilter imageFromCurrentlyProcessedOutput];

根据原始UIImage的创建方式,您可能希望将第一行包装在@autoreleasepool中,同时创建原始UIImage。在第一行之后不再需要原始的UIImage,因此在任何给定时间内最多应该在内存中有两个图像。

-prepareForImageCapture位是一种优化,它使得从此返回的UIImage与来自过滤器的输出纹理共享内存映射。这样就无需在最后使用其中一个图像副本,但它会将过滤器锁定到UIImage,如果您尝试重用该过滤器或UIImage,可能会导致奇怪的行为。我还不完全确定在内存映射的UIImage之前释放过滤器时释放所有内存,因此在该方法结束时将该图像编码为JPEG或PNG可能更安全,并且仅返回NSData表示。