采样器功能不适用于自定义颜色内核

问题描述 投票:0回答:2

您好,我一直在努力让采样器功能与自定义颜色内核一起使用。以下是我尝试过的:

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()
}
…
swift kernel metal core-image
2个回答
0
投票

试试这个:

    float2 inputImage3Coord = inputImage.coord();
    float4 color = inputImage3.sample(inputImage3Coord);

    if (firstpass == 1){
        color.y = 1;    
    }
    
    return color;
    
}

0
投票

我知道这是很晚的答案,但你应该检查文档

CIColorKernel

文档摘录:

它可能使用零个或多个输入图像。每个输入图像都被表示 通过 __sample(核心图像内核语言)类型的参数或 sample_t(金属着色语言),可以将其视为单个 vec4(核心图像内核语言)或 float4(Metal 着色语言);.

这意味着

CIColorKernel

 适用于每个图像中的各个像素,而不是整个图像本身。

这就是为什么一般 CIColorKernel 看起来像这样:

#include <CoreImage/CoreImage.h> extern "C" { namespace coreimage { float4 do_nothing(sample_t s) { // s - is a pixel of input image return s; } } }
因此,如果您想使用输入图像的任意像素,您应该考虑将 

CIKernel

 作为更通用的图像处理类。因为它是 CIColorKernel
最通用的替代品

也来自文档:

它可能使用零个或多个输入图像。每个输入图像都被表示 通过采样器类型的参数。

也许您正在寻找的东西:

内核例程通常通过计算源来产生其输出 图像坐标(使用 destCoord 和 SamplerTransform 函数 或samplerTransform函数)

,来自源图像的样本 (使用样本函数),并计算最终像素颜色(输出 使用 return 关键字)。例如,金属着色语言 下面的源代码实现了一个通过其输入图像的过滤器 不变。

还有此类内核的示例:

#include <CoreImage/CoreImage.h> extern "C" { namespace coreimage { float4 do_nothing(sampler src) { return src.sample(src.coord()); } } }

总结一下

: 如果您想通过执行采样和其他操作来处理整个图像,请使用 CIKernel。 否则,如果您的自定义过滤器同时使用 colorgeometry 信息,但不需要同时处理两者,您可以通过分离图像处理代码来提高性能:使用 CIColorKernel 对象进行颜色处理步骤,用于几何处理步骤的 CIWarpKernel 对象。

© www.soinside.com 2019 - 2024. All rights reserved.