Capture and process ProRAW images
Photos & Camera 进阶 25m

拍摄和处理 ProRAW 图像

Capture and process ProRAW images

2021年6月9日

在 Apple 官方观看视频

一句话判断

ProRAW 不只是”另一种 RAW 格式”——它是 Apple 把计算摄影的魔法和 RAW 的灵活性打包在一起的方案,如果你做摄影类 App,不理解 ProRAW 的文件结构就无法正确处理它。

这场 Session 讲了什么

Session 详细介绍了 Apple ProRAW 图像格式的技术细节,包括如何在 App 中拍摄、读取和处理 ProRAW 图像。ProRAW 是 Apple 在 iPhone 12 Pro 上引入的图像格式,它使用 DNG(Digital Negative)容器,但在标准 DNG 的基础上加入了 Apple 自定义的计算摄影数据。

ProRAW 的独特之处在于:它同时包含了 RAW 传感器的线性数据和 Apple 的计算摄影处理参数(Deep Fusion、Smart HDR 的处理结果)。这意味着你的 App 可以选择两种处理路径:一是完全自己从零处理 RAW 数据(像传统 RAW 编辑器那样),二是利用 Apple 预计算的处理参数作为起点(获得更好的初始画质)。Session 展示了如何通过 CIFilter 和 Core Image 的 RAW 处理能力来解码 ProRAW,以及如何读取嵌入在 DNG 中的 Apple 自定义 tag(比如 AppleProRAW 标签下的语义分割图)。

值得深挖的点

ProRAW DNG 文件的内部结构

ProRAW 使用标准的 DNG 1.5 格式,但在标准 tag 之外添加了 Apple 的私有 IFD(Image File Directory)。关键 tag 包括:SemanticMasks(语义分割掩码,区分天空、人物、毛发等区域)、RenderingParameters(Apple 的计算摄影参数)、以及 LinearizationTable(从传感器的 12-bit 原始值到线性光的映射)。语义分割掩码是 ProRAW 最强大的特性——你的 App 可以基于这些掩码做区域化的调整(比如只提亮人脸、只压暗天空),不需要自己做语义分割推理。

从 AVCaptureSession 拍摄 ProRAW

拍摄 ProRAW 需要使用 AVCapturePhotoOutputAVCapturePhotoSettings,设置 photoFormat[kCVPixelBufferPixelFormatTypeKey: kCVPixelFormatType_14Bayer_GRBG] 并启用 isProRAW。得到的 AVCapturePhoto 对象包含 DNG 数据。拍摄过程会触发 Apple 的计算摄影管线——和用户在相机 App 中按快门的效果一样,包括 Deep Fusion 和 Smart HDR 的处理。

代码片段

// 拍摄 ProRAW 图像
func captureProRAW(photoOutput: AVCapturePhotoOutput) {
    let settings = AVCapturePhotoSettings(format: [
        kCVPixelBufferPixelFormatTypeKey: kCVPixelFormatType_14Bayer_GRBG
    ])
    
    // 启用 ProRAW 格式输出
    settings.isRAWCapture = true
    // iPhone 12 Pro 及以上支持
    
    photoOutput.capturePhoto(with: settings, delegate: self)
}

// 处理拍摄回调
func photoOutput(_ output: AVCapturePhotoOutput,
                 didFinishProcessingPhoto photo: AVCapturePhoto,
                 error: Error?) {
    guard error == nil else { return }
    
    // 获取 DNG 数据
    guard let dngData = photo.fileDataRepresentation() else { return }
    
    // 保存为 DNG 文件
    let url = FileManager.default.temporaryDirectory
        .appendingPathComponent("capture_proraw.dng")
    try? dngData.write(to: url)
    
    // 使用 Core Image 解码 ProRAW
    processProRAW(at: url)
}
// 使用 Core Image 解码和处理 ProRAW
func processProRAW(at url: URL) {
    let ciContext = CIContext()
    
    // 从 DNG 文件创建 CIImage(Core Image 内置 DNG 解码)
    guard let ciImage = CIImage(contentsOf: url) else { return }
    
    // 应用 Core Image 的 RAW 调整参数
    let filter = CIFilter("CIRAWFilter", 
                          parameters: [
                            kCIInputImageKey: ciImage,
                            kCIInputExposureKey: 0.5,      // 增加曝光
                            kCIInputContrastKey: 1.1,      // 提高对比度
                            kCIInputSharpnessKey: 0.3      // 适度锐化
                          ])
    
    guard let outputImage = filter?.outputImage else { return }
    
    // 输出为高画质 JPEG
    let colorSpace = CGColorSpace(name: CGColorSpace.displayP3)!
    if let jpegData = ciContext.jpegRepresentation(of: outputImage,
                                                     colorSpace: colorSpace,
                                                     options: [CIContextRepresentationOption(kCIImageQualityKey): 0.95]) {
        let jpegURL = url.deletingPathExtension().appendingPathExtension("jpg")
        try? jpegData.write(to: jpegURL)
    }
}
// 读取 ProRAW 中的语义分割掩码
func extractSemanticMasks(from dngURL: URL) {
    guard let source = CGImageSourceCreateWithURL(dngURL as CFURL, nil),
          let properties = CGImageSourceCopyPropertiesAtIndex(source, 0, nil) as? [String: Any],
          let appleData = properties["AppleProRAW"] as? [String: Any],
          let masks = appleData["SemanticMasks"] as? [[String: Any]] else {
        print("此 DNG 文件不包含 ProRAW 语义掩码")
        return
    }
    
    for mask in masks {
        let type = mask["Type"] as? String ?? "unknown"
        let confidence = mask["Confidence"] as? Double ?? 0
        print("语义区域: \(type), 置信度: \(confidence)")
        // 可用的类型包括: Skin, Sky, Hair, Teeth, Glasses 等
    }
}

最佳实践

  • ProRAW 文件体积约 25MB/张,比 HEIC 的 2-3MB 大一个数量级。确保你的 App 有合理的存储空间预估和用户提示。
  • 处理 ProRAW 时优先利用 Apple 预计算的处理参数作为起点,而不是完全从零处理——Apple 的计算摄影管线经过大量场景训练,初始效果通常比手动调整更好。
  • 如果你的 App 只需要编辑后的最终图像(不涉及 RAW 编辑),可以让用户在系统相册中导出为 JPEG/HEIC 后再导入,避免自己处理 DNG 的复杂性。

还有什么值得关注

  • CIRAWFilter 在 iOS 15 中新增了对 ProRAW 的 Apple 署名曲线(tone curve)的支持,解码结果更接近系统相册的预览效果。
  • iPhone 13 Pro 的 ProRAW 支持了新的 cinematic mode(电影效果模式)的深度数据,可以用于后期重新调焦。
  • ProRAW 的语义掩码只在 iPhone 12 Pro 及以上设备拍摄时才包含,第三方 DNG 文件不会有这些数据。
WWDC 2021