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

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像素缓冲区中时,这两个上下文选项产生不同的输出.但我认为,输出应该不会有什么不同.因为第一个选项只是禁用 colored颜色 管理.第二种方法在sRGB扩展线性色彩空间中执行中间缓冲区计算,然后在输出中将这些缓冲区转换为BT.2020色彩空间.是否因为中间步骤中的信息丢失而导致输出不同?

最后,在显示HDR样本缓冲区时,哪个选项是正确的?

推荐答案

让我先回答您的最后一个问题:是的,这是设置MTKView以显示HDR内容的有效且很好的方式.但是,正如您所指出的,您还需要告诉MTLView通过设置metalLayer.edrMetadata = .hlg将EDR值映射到显示器的亮度范围.

或者,我发现以下设置也适用于显示EDR内容:

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

在这种情况下,视图似乎知道如何将扩展的线性EDR值自动映射到其显示器上-不需要设置edrMetadata.


剩下的我想分成两个主题:

Working Color Space

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

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

因此,在您的情况下,如果您永远不想在流水线中应用滤镜,您可能可以通过将工作空间设置为NSNull()来禁用 colored颜色 匹配.这甚至会节省一点处理时间,尽管不是很多,因为 colored颜色 空间转换相当便宜.

在大多数情况下,我建议不要使用workingColorSpace选项,让CI决定使用什么.

Output Color Space

CIContextOption.outputColorSpace章很有误导性它似乎并没有在几乎所有的用例中使用-至少到目前为止我还没有看到任何效果.

那是因为通常你要么

  • 将输出色彩空间直接传递给渲染API CIContext,如createCGImage(_ image:, from fromRect:, format:, colorSpace:)中所示,
  • 或者渲染目的地定义 colored颜色 空间.

第二点是这里的症结所在.我相信您正在使用CIRenderDestinationAPI呈现到视图中,可能定义如下:

let destination = CIRenderDestination(width: Int(drawableSize.width),
                                      height: Int(drawableSize.height),
                                      pixelFormat: self.colorPixelFormat,
                                      commandBuffer: commandBuffer,
                                      mtlTextureProvider: { () -> MTLTexture in
                                          return currentDrawable.texture
                                      })

这里的问题是,CIRenderDestination本身不能完全推断目标的 colored颜色 空间(它通常默认为sRGB).这就是为什么您必须明确设置它的原因.

在这里,您知道视图期望可绘制纹理包含以itur_2100_HLG为单位的像素数据.因此,要么直接设置,要么直接将其设置为视图的 colored颜色 空间:

destination.colorSpace = metalLayer.colorspace

然后,Core Image将知道在渲染到目标时要转换到哪个 colored颜色 空间.

有了这一更改,色彩管理关闭(CIContextOption.workingColorSpace: NSNull())和打开之间现在应该没有更多区别.

Ios相关问答推荐

验证开发人员应用程序证书是否已在您的设备上验证

SwiftUI图表-默认情况下,X轴数据点的间距不相等

如何将模糊输入/模糊输出添加到SwiftUI中的非对称过渡?

如何在SwiftUI中将图像整合到文本标签中间?

swift|在具有自定义单元格的多个TableView中没有任何内容

清除/删除 NavigationController 中的多个 ViewController

如何在SwiftUI中实现淡入淡出加粘标题屏幕效果

如何制作支持不同语言的iOS应用

动画文本位置

占位符文本未显示在 TextEditor 上

在 Swift 中从 Objective C 集合调用块

如何在字段包含字典数组的firestore上查询?

Swift如何表示单位转换的标准大气压

为什么我的应用在 Testflight 中没有下载 dSYM 按钮?

如何在通用应用程序中同时支持 iPad 和 iPhone 视网膜图形

UIView 和 initWithFrame 以及一个 NIB 文件.如何加载 NIB 文件?

将 iPhone xib 转换为 iPad xib?

NSURLSession:如何增加 URL 请求的超时时间?

在 iOS 上没有显示数字键盘

dismissModalViewController 并传回数据