Metal Custom CIFilter不同的返回值

时间:2018-12-04 18:21:27

标签: ios swift metal cifilter

我正在写CIFilter,但是结果像素的颜色不同于金属函数返回的值。

kernel.metal

#include <CoreImage/CoreImage.h>

extern "C" { namespace coreimage {

    float4 foo(sample_t rgb){

        return float4(0.3f, 0.5f, 0.7f, 1.0f);

    }
}

MetalFilter.swift

import CoreImage

class MetalFilter: CIFilter {

    private let kernel: CIColorKernel

    var inputImage: CIImage?

    override init() {
        let url = Bundle.main.url(forResource: "default", withExtension: "metallib")!
        let data = try! Data(contentsOf: url)
        kernel = try! CIColorKernel(functionName: "foo", fromMetalLibraryData: data)
        super.init()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func outputImage() -> CIImage? {
        guard let inputImage = inputImage else {return nil}
        return kernel.apply(extent: inputImage.extent, arguments: [inputImage])
    }
}

当我获得outputImage时,我具有以下值:
R = 0.58431372549019611
G = 0.73725490196078436
B = 0.85490196078431369

这是金属函数返回值后的某种后处理(如pow(x,1 / 2.373))。

1 个答案:

答案 0 :(得分:2)

Core Image在处理图像时执行两次颜色匹配: 从颜色空间(如果输入图像)到CIContext工作颜色空间,以及在应用所有滤镜之后的最后渲染步骤中,从工作颜色空间到输出上下文的颜色空间

这些颜色空间配置有默认值,根据我的经验,这些默认值取决于您所运行的设备(及其显示器)。但是,在创建CIContext时,可以使用kCIContextWorkingColorSpacekCIContextOutputColorSpace选项定义两个颜色空间。

如果将两个值都设置为NSNull(),则Core Image将不执行任何颜色匹配,将所有颜色值都视为图像缓冲区中的值。但是,您的滤镜可能对输入样本的色彩空间有一些假设。因此,在处理来自像摄像机这样的来源的输入时,请记住这一点,根据设备和照相机的配置,这些来源可能具有不同的色彩空间。

确保输入样本始终位于所需色彩空间中的另一种方法是,在创建用作自定义内核输入的CISampler时设置kCISamplerColorSpace选项。