我发现带有CIGaussianBlur过滤器的CIFilter有一个非常奇怪的行为。
我正在为不同的图像快速连续多次执行此方法。有时,会返回"最后处理的图像",而不是我发送的图像。例如,如果我有图像:
A、B和C。
如果我连续快速执行模糊,有时我会得到这样的结果:
A模糊、C模糊
+(UIImage *)applyBlurToImageAtPath:(NSURL *)imageUrlPath
{
if (imageUrlPath == nil)
return nil;
//Tried to create new contexts each loop, and also tried to use a singleton context
// if(CIImageContextSingleton == nil)
// {
// CIImageContextSingleton = [CIContext contextWithOptions:nil];
// }
CIContext *context = [CIContext contextWithOptions:nil];//[Domain sharedInstance].CIImageContextSingleton;
CIFilter *gaussianBlurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
[gaussianBlurFilter setDefaults];
CIImage *inputImage = [CIImage imageWithContentsOfURL:imageUrlPath];
[gaussianBlurFilter setValue:inputImage forKey:kCIInputImageKey];
[gaussianBlurFilter setValue:@(1) forKey:kCIInputRadiusKey];
//Tried both these methods for getting the output image
CIImage *outputImage = [gaussianBlurFilter valueForKey:kCIOutputImageKey];
// CIImage *outputImage = [gaussianBlurFilter outputImage];
//If I'm doing this, the problem never occurs, so the problem is isolated to the gaussianBlurFilter:
//outputImage = inputImage;
CGImageRef cgimg = [context createCGImage:outputImage fromRect:[inputImage extent]];
UIImage *resultImage = [UIImage imageWithCGImage:cgimg];
//Tried both with and without releasing the cgimg
CGImageRelease(cgimg);
return resultImage;
}
我在循环中尝试了这两种方法,并在做出手势或类似动作时运行该方法,结果出现了相同的问题。(imageUrlPath上的图片是正确的。)此外,请参阅代码中的注释,了解我尝试过的东西。
我是不是错过了什么?CIFilter是否有一些内部缓存?该方法始终在主线程上运行。
根据给定的代码,并假设此方法总是在主线程上调用,您应该没事,但我确实在代码中看到了一些不明智的地方:
- 不要每次调用该方法时都重新创建
CIContext
。我建议以不同的方式构建,而不是像辛格尔顿那样。在执行大量渲染时,请保留CIContext
并重复使用相同的上下文 - 如果您的
CIFilter
没有更改,也没有必要每次都重新创建它。如果在同一个线程上调用该方法,只需在筛选器上设置inputImage
键即可。每当输入图像发生更改时,您都需要从过滤器中获得一个新的outputImage
我的猜测是,问题可能围绕着核心图像上下文渲染到相同的底层图形环境(可能是GPU渲染),但由于您不断地重新创建CIContext,可能发生了一些不稳定的事情。
真的只是猜测,因为我手头没有代码来测试自己。如果您有一个测试项目来演示这个问题,那么调试会更容易。此外,我仍然对线程持怀疑态度。事实上,它在不应用模糊的情况下工作并不一定证明是模糊导致了问题——根据我的经验,随机性更可能涉及线程问题。