您好,我一直在努力让采样器功能与自定义颜色内核一起使用。以下是我尝试过的:
extern "C" { namespace coreimage {
float4 myColor3(sampler inputImage3, float firstpass) {
float4 color = inputImage3.sample(inputImage3.coord());
if (firstpass == 1){
color.y = 1;
}
return color;
}
我收到以下错误消息,我从 MetalLibraryData 加载函数: 致命错误:“尝试!”表达式意外引发错误:Foundation._GenericObjCError.nilError:文件/Users/...第 163 行
使用sample_t编写内核工作正常(没有这样的错误)...但我正在编写一个需要当前像素坐标的过滤器(尚未实现,只是试图让内核运行)。
所以我的主要问题是为什么采样器的行为不像sample_t?
float4 myColor3(sample_t inputImage3, float firstpass) {
if (firstpass == 1){
inputImage3.b = 1;
}
return inputImage3;
}
这就是我设置 CIFilter 的方式:
override var outputImage: CIImage? {
guard let inputImage3 = inputImage3,
let firstpass = firstpass
else { return nil }
return self.kernel3.apply(extent: inputImage3.extent, roiCallback: { _, rect -> CGRect in
return CGRect(x: rect.minX, y: rect.minY,
width: rect.width,
height: rect.height) },
arguments: [inputImage3, firstpass])
编辑:
我的 .metal 文件(应该命名为其他名称吗?)
#include <metal_stdlib>
using namespace metal;
#include <CoreImage/CoreImage.h> // includes CIKernelMetalLib.h
extern "C" { namespace coreimage {
float4 myColor(constructors…){
…filter 1
}
float4 myColor2 (constructors…){
….filter 2
}
}}
我如何设置过滤器类以达到良好的效果:
class MetalFilter: CIFilter {
var kernel: CIColorKernel
var kernel2: CIColorKernel
override init() {
let url = Bundle.main.url(forResource: "default", withExtension: "metallib")!
let data = try! Data(contentsOf: url)
kernel = try! CIColorKernel(functionName: "myColor", fromMetalLibraryData: data)
kernel2 = try! CIColorKernel(functionName: "myColor2”, fromMetalLibraryData: data)
super.init()
}
…
试试这个:
float2 inputImage3Coord = inputImage.coord();
float4 color = inputImage3.sample(inputImage3Coord);
if (firstpass == 1){
color.y = 1;
}
return color;
}
CIColorKernel
。
文档摘录:
这意味着 适用于每个图像中的各个像素,而不是整个图像本身。 这就是为什么一般 CIColorKernel 看起来像这样:它可能使用零个或多个输入图像。每个输入图像都被表示 通过 __sample(核心图像内核语言)类型的参数或 sample_t(金属着色语言),可以将其视为单个 vec4(核心图像内核语言)或 float4(Metal 着色语言);.
#include <CoreImage/CoreImage.h>
extern "C" {
namespace coreimage {
float4 do_nothing(sample_t s) { // s - is a pixel of input image
return s;
}
}
}
因此,如果您想使用输入图像的任意像素,您应该考虑将 作为更通用的图像处理类。因为它是 CIColorKernel
最通用的替代品
也来自文档:
它可能使用零个或多个输入图像。每个输入图像都被表示 通过采样器类型的参数。也许您正在寻找的东西:
内核例程通常通过计算源来产生其输出 图像坐标(使用 destCoord 和 SamplerTransform 函数 或samplerTransform函数),来自源图像的样本 (使用样本函数),并计算最终像素颜色(输出 使用 return 关键字)。例如,金属着色语言 下面的源代码实现了一个通过其输入图像的过滤器 不变。
还有此类内核的示例:
#include <CoreImage/CoreImage.h>
extern "C" {
namespace coreimage {
float4 do_nothing(sampler src) {
return src.sample(src.coord());
}
}
}
: 如果您想通过执行采样和其他操作来处理整个图像,请使用 CIKernel。 否则,如果您的自定义过滤器同时使用 color 和 geometry 信息,但不需要同时处理两者,您可以通过分离图像处理代码来提高性能:使用 CIColorKernel 对象进行颜色处理步骤,用于几何处理步骤的 CIWarpKernel 对象。