拍摄和处理 ProRAW 图像
Capture and process ProRAW images
2021年6月9日
一句话判断
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 需要使用 AVCapturePhotoOutput 的 AVCapturePhotoSettings,设置 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 文件不会有这些数据。