在应用中支持 HDR 图片
Support HDR images in your app
2023年6月5日
一句话判断
Apple 在 2023 年同时推出了 ISO HDR 图片标准的技术规范和 Gain Map HDR(从 2020 年起 iPhone 拍摄的照片都包含隐藏的 HDR 数据)——只需几行代码就能在你的 App 中展示真正的 HDR 图片。
这场 Session 讲了什么
Session 系统性地介绍了 HDR 图片的技术原理和 Apple 的新 API。
HDR 基础:
- SDR 显示范围有限(0.2-80 cd/m²),HDR 显示可以在更高亮度范围内保留更多细节。
- Headroom:HDR 内容中超过 SDR 参考白的部分。在 Apple 的 EDR 模型中,参考白是 1.0,HDR 峰值可以超过 1.0。
- HDR 在几乎所有 Apple 平台上可用。
ISO HDR 技术规范(TS22028-5):
- Apple 与 ISO 合作制定的新标准。
- 编码方式:HLG 或 PQ 传输函数。
- 色域:BT.2020 宽色域。
- 位深:至少 10 位(HEIF 可以,传统 JPEG 不行)。
- 元数据:ICC 配置文件或 CICP 标签。
- 可选元数据:参考环境、漫反射白亮度、场景/显示参考标记等。
Gain Map HDR:
- 自 2020 年起,iPhone 拍摄的照片中包含额外的 HDR 重建数据。
- 可以从现有的 SDR 照片中还原出 HDR 表示。
- 数万亿张 iPhone 照片现在可以通过新 API 以 HDR 方式展示。
新 API: SwiftUI 和 UIKit 中新增动态范围控制:
.high:启用 HDR 显示,系统自动处理映射。.standard:强制 SDR 显示(tone mapping)。.constrainedHigh:部分 HDR,避免在混合 SDR/HDR 内容场景中 HDR 图片过于突出。
值得深挖的点
Gain Map HDR 是一个”考古”发现。自 iPhone 12(2020 年)以来拍摄的所有照片都包含了 Gain Map 数据,但直到现在才有 API 可以访问。这意味着用户的照片库中已经有大量可以以 HDR 展示的照片——你的 App 只需要用新 API 渲染就能释放这些隐藏的视觉信息。
constrainedHigh 的设计动机很有意思。当你把 HDR 图片和 SDR 图片放在同一个网格中时,如果用 .high 选项,HDR 图片会非常亮,旁边的 SDR 图片反而显得暗淡。constrainedHigh 限制了 HDR 的最大亮度,让混合内容场景的视觉平衡更好。这是一个细节,但在相册类 App 中影响很大。
10 位色深的要求排除了 JPEG。传统 JPEG 只有 8 位,在 HDR 编码中会出现色带(banding)问题。HEIF 是首选格式。如果你的 App 处理用户上传的图片,要注意 JPEG 图片无法以 ISO HDR 方式展示。
代码片段
SwiftUI 中展示 HDR 图片:
import SwiftUI
struct HDRImageView: View {
var body: some View {
// 展示 ISO HDR 图片文件
Image(uiImage: UIImage(contentsOfFile: hdrImagePath)!)
.allowedDynamicRange(.high) // 启用 HDR 渲染
// 系统自动处理 HDR 到当前显示的映射
// 包括显示状态变化时的更新
}
}
UIKit 中展示 HDR 图片:
import UIKit
class HDRViewController: UIViewController {
let imageView = UIImageView()
func displayHDRImage() {
imageView.image = UIImage(contentsOfFile: hdrImagePath)
// 启用 HDR 显示
imageView.preferredImageDynamicRange = .high
// 其他选项:
// .standard → 强制 SDR(tone mapping)
// .constrainedHigh → 部分 HDR,适合混合内容场景
}
}
混合内容场景中使用 constrainedHigh:
// 相册缩略图网格:混合 HDR 和 SDR 图片
LazyVGrid(columns: [GridItem(.adaptive(minimum: 100))]) {
ForEach(photos) { photo in
Image(uiImage: photo.image)
// 使用 constrainedHigh 避免 HDR 图片过于突出
.allowedDynamicRange(.constrainedHigh)
// HDR 图片会显示更多细节,但不会压过旁边的 SDR 图片
}
}
最佳实践
- 用
.high展示单张 HDR 图片(全屏查看器),用.constrainedHigh展示缩略图网格。 .high选项对非 HDR 图片没有副作用,可以安全地对所有图片使用。- 用户照片库中的 iPhone 照片自带 Gain Map HDR,用新 API 自动获得 HDR 效果。
- 保存 HDR 图片时使用 HEIF 格式(至少 10 位),JPEG 不支持 ISO HDR。
- 在不支持 HDR 的显示器上,
.high自动降级为 SDR,无需额外处理。 - 测试 HDR 效果需要在支持 HDR 的 Apple 显示器上进行。
还有什么值得关注
- EDR(Extended Dynamic Range)是 Apple 底层的 HDR 渲染技术,详见”Explore HDR Rendering with EDR”Session。
- ISO HDR 技术规范 TS22028-5 可以在 ISO 官网查看完整内容。
- Gain Map HDR 数据自 2020 年起就存在于 iPhone 照片中,不需要用户重新拍摄。
- AppKit(macOS)也有对应的 NSImage 动态范围属性。
- HDR 图片处理管线(Pipeline)的详细说明在 Session 后半部分由 David 介绍。