我的应用程序需要CIFilters,每个都有一个自定义的CIKernel,可以从Metal进行编译。 Swift不允许从自定义内核实例化CIFilter,相反,我必须为我需要的每个自定义过滤器创建基类CIFilter并在计算所得的outputImage属性中使用内核。我已经在符合CIFilterConstructor的类中限定了所有这些子容器,并通过方法提供了所需过滤器的实例
filter(withName name: String) -> CIFilter?
我似乎无法在CIFilter sublcass的外部范围内提供任何可用的东西。这意味着每个过滤器如下所示:
class deuteranopiaFilter: CIFilter {
var deuteranopiaKernel: CIKernel?
override var name: String {
get {
return "deuteranopia"
}
set {}
}
override init() {
super.init()
guard let url = Bundle.main.url(forResource: "default", withExtension: "metallib"),
let data = try? Data(contentsOf: url)
else { fatalError("Unable to get metallib") }
guard let deuteranopiaKernel: CIColorKernel = try? CIColorKernel(functionName: "deuteranopia",
fromMetalLibraryData: data)
else { fatalError("Couldn't create kernel \(self.name)") }
self.deuteranopiaKernel = deuteranopiaKernel
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override class func registerName(_ name: String,
constructor anObject: CIFilterConstructor,
classAttributes attributes: [String : Any] = [:]) {
CIFilter.registerName("Deuteranopia", constructor: FilterManager(), classAttributes: attributes)
}
@objc dynamic var inputImage: CIImage?
override var outputImage: CIImage? {
if let input = inputImage {
let src = CISampler(image: input)
return self.deuteranopiaKernel?.apply(extent: input.extent, roiCallback: {return $1}, arguments: [src])
} else {
return nil
}
}
}
这里有很多重用的代码。创建Metal库和内核,提供name属性,寄存器类函数和输出image属性。对于我将要使用的每个过滤器,我有什么办法可以避免将所有这些粘贴粘贴?