这是一个奇怪的问题–我什至不知道如何开始。
我正在使用CIFilter
来模糊图像。这是代码的本质,实现为UIImage
的类别:
- (void)imageByApplyingBlur:(CGFloat)radius completion:(void (^)(UIImage *))completion {
// If no completion, then nothing to do
if (completion == nil) {
return;
}
// If no radius, self is the result
if (radius == 0.0) {
completion(self);
return;
}
UIApplicationState appState = [UIApplication sharedApplication].applicationState;
CIImage *imageToBlur = [CIImage imageWithCGImage:self.CGImage];
CGFloat scale = [UIScreen mainScreen].scale;
// Do the thread-safe CIImage blurring on a high-priority concurrent thread.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSDictionary *contextOptions = nil;
// Always include the kCIContextPriorityRequestLow : @(YES) pair, because
// otherwise, the foreground animation framerate suffers while blurring.
if (appState == UIApplicationStateBackground) {
contextOptions = @{
kCIContextPriorityRequestLow : @(YES),
// If we're not active, force CIContext to use the CPU renderer
// CPU rendering should be allowed even in the background
kCIContextUseSoftwareRenderer : @(YES)
};
} else {
contextOptions = @{
kCIContextPriorityRequestLow : @(YES),
};
}
CIContext *context = [CIContext contextWithOptions:contextOptions];
CIFilter *gaussianBlurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
[gaussianBlurFilter setValue:imageToBlur forKey:@"inputImage"];
[gaussianBlurFilter setValue:@(radius) forKey:@"inputRadius"];
CIImage *resultImage = [gaussianBlurFilter valueForKey:@"outputImage"];
CGRect cropRect = {
.origin.x = radius,
.origin.y = radius,
.size.width = (imageToBlur.extent.size.width - (2 * radius)),
.size.height = (imageToBlur.extent.size.height - (2 * radius))
};
// Crop transparent edges from blur
resultImage = [resultImage imageByCroppingToRect:cropRect];
// Generate returnable UIImage (important to make the image "from" a CGImage, not a CIImage)
CGImageRef resultCGImage = [context createCGImage:resultImage fromRect:resultImage.extent];
UIImage *resultUIImage = [UIImage imageWithCGImage:resultCGImage
scale:scale
orientation:UIImageOrientationUp];
CGImageRelease(resultCGImage);
// The completion block has to happen on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
completion(resultUIImage);
});
});
}
大约90%的时间,这种方法都可以正常工作。但是,有时,它从不向回调块提交有效的图像,而且我看到了难以置信的错误日志。错误日志很长,因此我将等到问题结束将其复制粘贴。
一些注意事项:
CIFilter
from multiple threads safely,但是据我所知,我已经满足了这些要求。从理论上讲,我可以为此移到串行队列中,但是我不明白为什么这样做一定有帮助。 那么,我的问题是怎么回事?而且,理想情况下,我该如何解决?
以下是我没有图像时的相关日志输出:
liblib:3:15: error: :unkown type or function name: 'mix'
3:15: error: unkown type or function name: 'mix'
return mix(y, z, step(0.0,x));
^
return mix(y, z, step(0.0,x));
^
lib:lib:1:16:6:: error : error: non-void function should return a value
non-void function should return a value
vec4 compare (vec4 x, vec4 y, vec4 z)
^
vec4 compare (vec4 x, vec4 y, vec4 z)
^
lib:24:12: error: unkown type or function name 'tan'; did you mean 'tan_'?
return tan(x);
^~~
tan_
lib:51:26: error: unkown type or function name: 'max'
return vec4(s.rgb/max(s.a,0.00001), s.a);
^
lib:49:6: error: non-void function should return a value
vec4 unpremultiply (vec4 s)
^
lib:56:28: error: unkown type or function name: 'mix'
s.rgb = sign(s.rgb)*mix(s.rgb*0.077399380804954, pow(abs(s.rgb)*0.947867298578199 + 0.052132701421801, vec3(2.4)), step(0.04045, abs(s.rgb)));
^
lib:62:28: error: unkown type or function name: 'mix'
s.rgb = sign(s.rgb)*mix(s.rgb*12.92, pow(abs(s.rgb), vec3(0.4166667)) * 1.055 - 0.055, step(0.0031308, abs(s.rgb)));
^
filter:4:12: error: unkown type or function name: 'clamp'
x = clamp(min(x, x.yzwx), 0.0, 1.0);
^
filter:1:55: error: unkown type or function name: 'max'
vec4 _ci_unpremultiply(vec4 s) { return vec4(s.rgb/max(s.a,0.00001), s.a); }
^
filter:1:6: error: non-void function should return a value
lib:24:12: error: unkown type or function name 'tan'; did you mean 'tan_'?
return tan(x);
vec4 _ci_unpremultiply(vec4 s) { return vec4(s.rgb/max(s.a,0.00001), s.a); }
^
^~~
tan_
filter:3:26: error: unkown type or function name: 'mix'
lib:51:26: error: unkown type or function name: 'max'
s.rgb = sign(s.rgb)*mix(s.rgb*0.077399380804954, pow(abs(s.rgb)*0.947867298578199 + 0.052132701421801, vec3(2.4)), step(0.04045, abs(s.rgb)));
^
return vec4(s.rgb/max(s.a,0.00001), s.a);
^
lib:49:6: error: non-void function should return a value
vec4 unpremultiply (vec4 s)
^
lib:56:28: error: unkown type or function name: 'mix'
s.rgb = sign(s.rgb)*mix(s.rgb*0.077399380804954, pow(abs(s.rgb)*0.947867298578199 + 0.052132701421801, vec3(2.4)), step(0.04045, abs(s.rgb)));
^
lib:62:28: error: unkown type or function name: 'mix'
s.rgb = sign(s.rgb)*mix(s.rgb*12.92, pow(abs(s.rgb), vec3(0.4166667)) * 1.055 - 0.055, step(0.0031308, abs(s.rgb)));
^
lib:3:15: error: unkown type or function name: 'mix'
return mix(y, z, step(0.0,x));
^
lib:1:6: error: non-void function should return a value
vec4 compare (vec4 x, vec4 y, vec4 z)
^
filter:4:12: error: unkown type or function name: 'clamp'
x = clamp(min(x, x.yzwx), 0.0, 1.0);
^
lib:24:12: error: unkown type or function name 'tan'; did you mean 'tan_'?
filter:1: return tan(x);
55: ^~~
tan_error
: unkown type or function name: 'max'
vec4 _ci_unpremultiply(vec4 s) { return vec4(s.rgb/max(s.a,0.00001), s.a); }
^
libfilter::511::266:: errorerror: : unkown type or function name: 'max'
non-void function should return a value
return vec4(s.rgb/max(s.a,0.00001), s.a);
^
lib:49:vec4 _ci_unpremultiply(vec4 s) { return vec4(s.rgb/max(s.a,0.00001), s.a); }6
: ^
error: non-void function should return a value
vec4 unpremultiply (vec4 s)
^
filter:3:26: error: unkown type or function name: 'mix'
lib:56:28: error: unkown type or function name: 'mix'
s.rgb = sign(s.rgb)*mix(s.rgb*0.077399380804954, pow(abs(s.rgb)*0.947867298578199 + 0.052132701421801, vec3(2.4)), step(0.04045, abs(s.rgb)));
^
s.rgb = sign(s.rgb)*mix(s.rgb*0.077399380804954, pow(abs(s.rgb)*0.947867298578199 + 0.052132701421801, vec3(2.4)), step(0.04045, abs(s.rgb)));
^
lib:62:28: error: unkown type or function name: 'mix'
s.rgb = sign(s.rgb)*mix(s.rgb*12.92, pow(abs(s.rgb), vec3(0.4166667)) * 1.055 - 0.055, step(0.0031308, abs(s.rgb)));
^
lib:3:15: error: unkown type or function name: 'mix'
return mix(y, z, step(0.0,x));
^
filter:lib1:1:6::55: error : error: unkown type or function name: 'max'non-void function should return a value
vec4 compare (vec4 x, vec4 y, vec4 z)
^
vec4 _ci_unpremultiply(vec4 s) { return vec4(s.rgb/max(s.a,0.00001), s.a); }
^
filter:1:6: error: non-void function should return a value
vec4 _ci_unpremultiply(vec4 s) { return vec4(s.rgb/max(s.a,0.00001), s.a); }
^
filter:3:26: error: unkown type or function name: 'mix'
lib:24:12: error: unkown type or function name 'tan'; did you mean 'tan_'?
s.rgb = sign(s.rgb)*mix(s.rgb*12.92, pow(abs(s.rgb), vec3(0.4166667)) * 1.055 - 0.055, step(0.0031308, abs(s.rgb))); return tan(x);
^
^~~
tan_
filter:1:47: error: unkown type or function name: 'clamp'
lib:51:26: errorvec4 _ci_clamp_to_alpha(vec4 s) { return clamp(s, 0.0, s.a); }
^
filter:1:6: error: non-void function should return a value
: unkown type or function name: 'max'
vec4 _ci_clamp_to_alpha(vec4 s) { return clamp(s, 0.0, s.a); }
^
return vec4(s.rgb/max(s.a,0.00001), s.a);
^
lib:49:6: error: non-void function should return a value
vec4 unpremultiply (vec4 s)
^
lib:56:28: error: unkown type or function name: 'mix'
s.rgb = sign(s.rgb)*mix(s.rgb*0.077399380804954, pow(abs(s.rgb)*0.947867298578199 + 0.052132701421801, vec3(2.4)), step(0.04045, abs(s.rgb)));
^
lib:62:28: error: unkown type or function name: 'mix'
s.rgb = sign(s.rgb)*mix(s.rgb*12.92, pow(abs(s.rgb), vec3(0.4166667)) * 1.055 - 0.055, step(0.0031308, abs(s.rgb)));
^
filter:1:55: error: unkown type or function name: 'max'
vec4 _ci_unpremultiply(vec4 s) { return vec4(s.rgb/max(s.a,0.00001), s.a); }
^
filter:1:6: error: non-void function should return a value
vec4 _ci_unpremultiply(vec4 s) { return vec4(s.rgb/max(s.a,0.00001), s.a); }
^
filter:3:26: error: unkown type or function name: 'mix'
s.rgb = sign(s.rgb)*mix(s.rgb*12.92, pow(abs(s.rgb), vec3(0.4166667)) * 1.055 - 0.055, step(0.0031308, abs(s.rgb)));
^
filter:1:47: error: unkown type or function name: 'clamp'
vec4 _ci_clamp_to_alpha(vec4 s) { return clamp(s, 0.0, s.a); }
^
filter:1:6: error: non-void function should return a value
vec4 _ci_clamp_to_alpha(vec4 s) { return clamp(s, 0.0, s.a); }
^
ERROR - could not find uniform for argument 0
ERROR - could not find uniform for argument 0
ERROR - could not find uniform for argument 1
ERROR - could not find uniform for argument 1
ERROR - could not find uniform for argument 2
ERROR - could not find uniform for argument 2
ERROR - could not find uniform for argument 3
ERROR - could not find uniform for argument 3
最佳答案
这与您的主要问题无关,但是有一种更好的方法来“从模糊中裁剪透明边缘”。试试这个:
CGRect originalExtent = img.extent;
img = [img imageByClampingToExtent:originalExtent];
img = [img imageByApplyingFilter:@"CIGaussianBlur"
params:@{@"inputRadius" : @(radius)}];
img = [imageByCroppingToRect:originalExtent]
关于ios - CIFilter似乎在GPU上失败,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29593839/