带金属的核心图像滤镜

我们可以创建在iOS 11或更高版本中以金属阴影语言(MSL)编写的自定义核心图像滤镜。

A8或更高版本的设备上受支持。

它可以在构建时进行预编译,因此可以获得更好的性能。 现有方法(GLSL或CIKernel语言)在运行时进行编译。

以下是添加到CIKernel的新API:

 公共便利init(functionName名称:字符串,fromMetalLibraryData数据:数据)引发公共便利init(functionName名称:字符串,fromMetalLibraryData数据:数据,outputPixelFormat格式:CIFormat)引发 

这是CIColorKernel的简单MSL实现:

  #include  
使用命名空间金属;
#include //包含CIKernelMetalLib.h
extern“ C” {名称空间coreimage {
float4 myColor(sample_t s){
返回s.grba;
}
}}

让我们将其另存为kernel.metal或其他名称(任何名称都可以,但是扩展名应该是.metal )。

可以使用新的API初始化使用着色器功能的CIColorKernel

 让url = Bundle.main.url(forResource:“ default”,withExtension:“ metallib”)! 
让数据=尝试! 数据(contentsOf:url)
让内核=尝试! CIColorKernel(functionName:“ myColor”,fromMetalLibraryData:data)

因此,可以像这样实现具有自定义内核的CIFilter子类:

 导入CoreImage 
MetalFilter类:CIFilter {
专用let内核:CIColorKernel
var inputImage:CIImage?
覆盖init(){
让url = Bundle.main.url(forResource:“ default”,withExtension:“ metallib”)!
让数据=尝试! 数据(contentsOf:url)
内核=试试! CIColorKernel(functionName:“ myColor”,fromMetalLibraryData:data)
super.init()
}
需要初始化吗?(编码器aDecoder:NSCoder){
fatalError(“ init(coder :)尚未实现”)
}
func outputImage()-> CIImage? {
卫队让inputImage = inputImage else {返回零}
返回kernel.apply(范围:inputImage.extent,参数:[inputImage])
}
}

自定义过滤器可以这样使用:

 让过滤器= MetalFilter() 
filter.inputImage = inputImage
让outputImage = filter.outputImage()

而已!

好的,现在我们可以构建项目了。 让我们在您的设备上运行它!

  + [CIKernel kernelWithFunctionName:fromMetalLibraryData:outputPixelFormat:error:]函数'myColor'不存在。 

嗯,但是它说myColor不存在。 但是它存在…

我在这里找到解决方案:

  • kernelWithFunctionName:fromMetalLibraryData:错误:— CIKernel
    Apple开发人员文档

我们需要在构建设置中指定一些选项:

  • 在“ Other Metal Compiler Flags选项中指定-fcikernel标志
  • 使用名为MTLLINKER_FLAGS的键添加用户定义的设置,该键的值为-cikernel