我正在写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))。
答案 0 :(得分:2)
Core Image在处理图像时执行两次颜色匹配:
从颜色空间(如果输入图像)到CIContext
的工作颜色空间,以及在应用所有滤镜之后的最后渲染步骤中,从工作颜色空间到输出上下文的颜色空间。
这些颜色空间配置有默认值,根据我的经验,这些默认值取决于您所运行的设备(及其显示器)。但是,在创建CIContext
时,可以使用kCIContextWorkingColorSpace
和kCIContextOutputColorSpace
选项定义两个颜色空间。
如果将两个值都设置为NSNull()
,则Core Image将不执行任何颜色匹配,将所有颜色值都视为图像缓冲区中的值。但是,您的滤镜可能对输入样本的色彩空间有一些假设。因此,在处理来自像摄像机这样的来源的输入时,请记住这一点,根据设备和照相机的配置,这些来源可能具有不同的色彩空间。
确保输入样本始终位于所需色彩空间中的另一种方法是,在创建用作自定义内核输入的CISampler
时设置kCISamplerColorSpace
选项。