如果难以或不可能将多个 CIFilter 调用“链接”在一起以达到预期效果 - 可能是由于类具有单一属性,解决此问题的一种方法是执行以下操作:
- 子类
CIFilter,覆盖您需要的一切。这可能包括attributes、setValue(forKey:),最重要的是outputImage。
- 继承
CIFilterConstructor,并创建registerFilter()方法。
例如,假设您希望组合高斯模糊,然后为图像添加单色红色调。最基本的你可以这样做:
class BlurThenColor:CIFilter {
let blurFilter = CIFilter(name: "CIGaussianBlur")
override public var attributes: [String : Any] {
return [
kCIAttributeFilterDisplayName: "Blur then Color",
"inputImage": [kCIAttributeIdentity: 0,
kCIAttributeClass: "CIImage",
kCIAttributeDisplayName: "Image",
kCIAttributeType: kCIAttributeTypeImage]
]
}
override init() {
super.init()
}
@available(*, unavailable) required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override public func setValue(_ value: Any?, forKey key: String) {
switch key {
case "inputImage":
blurFilter?.setValue(inputImage, forKey: "inputImage")
default:
break
}
}
override public var outputImage: CIImage {
return (blurFilter?.outputImage)! .applyingFilter("CIColorMonochrome", parameters: ["inputColor": CIColor(red: 1.0, green: 0.0, blue: 0.0)])
}
}
如果您希望公开更多属性,您可以简单地将它们添加到 attributes 和 setValue(forKey:) 覆盖以及添加变量和 setDefaults。这里我只是使用默认值。
现在您已将效果链接到一个自定义过滤器中,您可以注册并使用它:
let CustomFilterCategory = "CustomFilter"
public class CustomFilterConstructor: NSObject, CIFilterConstructor {
static public func registerFilter() {
CIFilter.registerName(
"BlurThenColor",
constructor: CustomFilterConstructor(),
classAttributes: [
kCIAttributeFilterCategories: [CustomFilterCategory]
])
}
public func filter(withName name: String) -> CIFilter? {
switch name {
case "BlurThenColor":
return BlurThenColor()
default:
return nil
}
}
}
要使用它,请务必注册过滤器(如果可能,我倾向于将我的过滤器放在AppDelegate):
CustomFilterConstructor.registerFilter()
从那里,您可以像使用任何其他 CIFilter 一样使用 BlurThenColor。实例化它,使用setValue,然后调用outputImage。
请注意,由于inputImage 的强制解包和/或拼写错误,此代码将崩溃。我相信你可以让它更安全 - 但请放心,我已经测试过它并且它有效。 (我创建了这个自定义过滤器并将其替换为不会发生强制展开的应用程序。)