ios 用于HDR显示的CIContext选项

zbsbpyhn  于 12个月前  发布在  iOS
关注(0)|答案(1)|浏览(99)

我有两个配置了以下选项的CIContexts:

let options1:[CIContextOption:Any] = [CIContextOption.cacheIntermediates: false, CIContextOption.outputColorSpace: NSNull(), CIContextOption.workingColorSpace: NSNull()];

let options2:[CIContextOption:Any] = [CIContextOption.cacheIntermediates: false];

字符串
和一个MTKView与CAMetalLayer配置HDR输出。

metalLayer = self.layer as? CAMetalLayer
    
    metalLayer?.wantsExtendedDynamicRangeContent = true
    metalLayer.colorspace = CGColorSpace(name: CGColorSpace.itur_2100_HLG)
    
    colorPixelFormat = .bgr10a2Unorm


当输入在BT.2020像素缓冲区中时,这两个上下文选项会产生不同的输出。但我认为输出不应该有所不同。因为第一个选项只是禁用了颜色管理。第二个选项在sRGB扩展线性颜色空间中执行中间缓冲区计算,然后在输出中将这些缓冲区转换为BT.2020颜色空间。输出不同是因为中间步骤?
最后,在显示HDR采样缓冲区时,哪个选项是正确的?

2w3rbyxf

2w3rbyxf1#

让我先回答你的最后一个问题:是的,这是设置MTKView显示HDR内容的有效和好方法。但是,正如你指出的,你还需要告诉MTLView通过设置metalLayer.edrMetadata = .hlg将EDR值色调Map到显示器的亮度范围。
另外,我发现以下设置也适用于显示EDR内容:

metalLayer.wantsExtendedDynamicRangeContent = true
metalLayer.colorspace = CGColorSpace(name: CGColorSpace.extendedLinearSRGB)
colorPixelFormat = .rgba16Float

字符串
在这种情况下,视图似乎知道如何自动将扩展线性EDR值色调Map到其显示屏-无需设置edrMetadata
剩下的我想分成两个主题:

工作颜色空间

你是对的:当设置CIContextOption.workingColorSpace: NSNull()时,您可以有效地禁用Core Image的自动颜色管理。然而,我建议您只在以下情况下才这样做:

  • 你知道输入的颜色空间是什么,
  • 不应用任何内置滤镜(因为它们假设输入在CI的默认工作颜色空间中),
  • 您将输出配置为与输入在相同的颜色空间中。

所以在你的例子中,如果你不想在你的管道中应用滤镜,你可能可以通过设置工作空间为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())和打开之间的区别。

相关问题