【问题标题】:MTKView display HDR10 CIImageMTKView 显示 HDR10 CIImage
【发布时间】:2021-11-25 03:25:03
【问题描述】:

我需要使用 MTKView 在 HDR10(kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange / BT2020 PQ 颜色空间)中显示 CVPixelBuffers。我有以下代码要显示,但它会产生失真的图像,我无法确定它是显示 10 位颜色还是钳位颜色。还有是bgra10_xr还是bgra10_xr_srgb应该是colorPixelFormat的正确选择以及两者的区别。

class CIImageView: MTKView {

    var image: CIImage? {
       didSet {
          self.draw()
      }
     }

   var originalImageExtent: CGRect = CGRect.zero 

   var scale: CGFloat {
       return max(self.frame.width / originalImageExtent.width, self.frame.height / originalImageExtent.height)
   } 


   func update() {
      guard let img = image, destRect.size.width <=    img.extent.size.width && destRect.size.height <=   img.extent.size.height else {
          return
       }
    
      self.draw()
   }

let context: CIContext
let commandQueue: MTLCommandQueue

convenience init(frame: CGRect) {
    let device = MetalCamera.metalDevice
    self.init(frame: frame, device: device)
    colorPixelFormat = .bgra10_xr_srgb
}

override init(frame frameRect: CGRect, device: MTLDevice?) {
    guard let device = device else {
        fatalError("Can't use Metal")
    }
    
    
    guard let cmdQueue = device.makeCommandQueue(maxCommandBufferCount: 5) else {
        fatalError("Can't make Command Queue")
    }
    
    commandQueue = cmdQueue
    
    context = CIContext(mtlDevice: device, options: [CIContextOption.cacheIntermediates: false])
    
    super.init(frame: frameRect, device: device)
    
    self.framebufferOnly = false
    self.enableSetNeedsDisplay = false
    self.isPaused = true
    self.clearColor = MTLClearColor(red: 0, green: 0, blue: 0, alpha: 0)
}

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

override func draw(_ rect: CGRect) {
    
    guard let image = self.image else {
        return
    }
    
    let dRect = destRect
    
    let drawImage: CIImage
    
    if dRect == image.extent {
        drawImage = image
    } else {
        let scale = max(dRect.height / image.extent.height, dRect.width / image.extent.width)
        drawImage = image.transformed(by: CGAffineTransform(scaleX: scale, y: scale))
    }
    
    let commandBuffer = commandQueue.makeCommandBufferWithUnretainedReferences()
    guard let texture = self.currentDrawable?.texture else {
        return
    }
    
    let colorSpace = drawImage.colorSpace ?? CGColorSpaceCreateDeviceRGB()
    
    context.render(drawImage, to: texture, commandBuffer: commandBuffer, bounds: dRect, colorSpace: colorSpace)
    
    commandBuffer?.present(self.currentDrawable!)
    commandBuffer?.commit()
}

private var destRect: CGRect {
    
    let scale: CGFloat
    if UIScreen.main.scale == 3 {
        // BUG?
        scale = 2.0 * (2.0 / UIScreen.main.scale) * 2
    } else {
        scale = UIScreen.main.scale
    }
    let destRect = self.bounds.applying(CGAffineTransform(scaleX: scale, y: scale))
    
    return destRect
 }


func displayPixelBuffer(_ pixelBuffer: CVPixelBuffer, flip:FlipDirection) {
    self.image = CIImage(cvImageBuffer: pixelBuffer)
}

编辑:我尝试了手动设置 colorSpace 的建议,但颜色被洗掉了。

这是 iPhone 上使用 AVCaptureVideoPreviewLayer 的同一场景的屏幕截图。

【问题讨论】:

  • 您能否尝试使用此颜色空间:CGColorSpace(name: CGColorSpace.itur_2100_PQ) (in context.render(…))
  • 我必须明确指定颜色空间吗,drawImage.colorSpace 不是已经有正确的颜色空间了吗?
  • A CIImage 只有在直接从具有颜色空间的源加载时才有 colorSpace。但是您(可能)正在对其应用转换,因此它会丢失源的颜色空间信息。
  • 让我试着回复你
  • 颜色似乎被洗掉了。我将使用示例图像更新问题

标签: ios metal core-image ciimage mtkview


【解决方案1】:

请在apple forum 上查看此框架开发人员的回答:

CAMetalLayer.wantsExtendedDynamicRangeContent 仅适用于 苹果系统。 Metal 没有公开在 iOS 上显示 HDR 内容的方法 设备。 HDR 只能用于视频和图像。

通过将 CAMetalLayer.pixelFormat 设置为 XR 格式之一(例如 MTLPixelFormatBGR10_XR_sRGB),Metal 确实提供了一种获取一些 额外的动态余量可提供比标准更好的色调映射 HDR 效果 sRGB。虽然这不是像 HDR10 或杜比视界这样的真正 HDR,但它确实如此 提高效果。


另外,bgra10_xr 还是 bgra10_xr_srgb 应该是正确的选择 colorPixelFormat和两者的区别。

要显示真正的 HDR 内容,您应该使用MTLPixelFormatRGBA16Float 像素格式。

【讨论】:

    猜你喜欢
    • 2019-04-02
    • 2019-07-13
    • 2019-12-24
    • 2019-08-12
    • 2018-11-12
    • 1970-01-01
    • 1970-01-01
    • 2017-12-30
    • 2012-03-09
    相关资源
    最近更新 更多