我有两个 CIContext 配置了以下选项:
let options1:[CIContextOption:Any] = [CIContextOption.cacheIntermediates: false, CIContextOption.outputColorSpace: NSNull(), CIContextOption.workingColorSpace: NSNull()];
let options2:[CIContextOption:Any] = [CIContextOption.cacheIntermediates: false];
以及配置了 HDR 输出的带有 CAMetalLayer 的 MTKView。
metalLayer = self.layer as? CAMetalLayer
metalLayer?.wantsExtendedDynamicRangeContent = true
metalLayer.colorspace = CGColorSpace(name: CGColorSpace.itur_2100_HLG)
colorPixelFormat = .bgr10a2Unorm
当输入位于 BT.2020 像素缓冲区中时,两个上下文选项会产生不同的输出。但我相信输出不应该有所不同。因为第一个选项只是禁用颜色管理。第二个在 sRGB 扩展线性色彩空间中执行中间缓冲区计算,然后将这些缓冲区转换为输出中的 BT.2020 色彩空间。输出是否因为中间步骤丢失信息而不同?
最后,哪个选项在显示 HDR 样本缓冲区时是正确的?
让我先回答您的最后一个问题:是的,这是设置
MTKView
显示 HDR 内容的有效且良好的方法。
剩下的我想分成两个主题:
你是对的:设置
CIContextOption.workingColorSpace: NSNull()
时,你实际上禁用了Core Image的自动颜色管理。但是,我只建议在以下情况下这样做:
因此,在您的情况下,如果您不想在管道中应用过滤器,您可能可以通过将工作空间设置为
NSNull()
来禁用颜色匹配。这甚至可以节省一点处理时间,尽管不是很多,因为色彩空间转换相当便宜。
在大多数情况下,我建议不要触及
workingColorSpace
选项,让 CI 决定使用什么。
不幸的是,
CIContextOption.outputColorSpace
非常具有误导性。它似乎并没有在几乎所有用例中使用——至少到目前为止我还没有看到任何效果。
那是因为通常你
CIContext
的渲染 API,如 createCGImage(_ image:, from fromRect:, format:, colorSpace:)
,第二点是这里的症结所在。我相信您正在使用
CIRenderDestination
API 渲染到视图中,可能定义如下:
let destination = CIRenderDestination(width: Int(drawableSize.width),
height: Int(drawableSize.height),
pixelFormat: self.colorPixelFormat,
commandBuffer: commandBuffer,
mtlTextureProvider: { () -> MTLTexture in
return currentDrawable.texture
})
这里的问题是
CIRenderDestination
无法自行完全推断目标的颜色空间(通常默认为 sRGB)。这就是为什么你必须明确设置它。
在这里您知道视图期望可绘制纹理包含
itur_2100_HLG
中的像素数据。因此,要么直接设置,要么简单地将其设置为视图的颜色空间:
destination.colorSpace = metalLayer.colorspace
然后 Core Image 将知道在渲染到目标时要转换到哪个颜色空间。
通过此更改,关闭 (
CIContextOption.workingColorSpace: NSNull()
) 和打开颜色管理之间现在应该不再有差异。