HDR 图像格式:OpenEXR、Radiance HDR、HDR10、Dolby Vision
做 HDR 图像处理,第一件事不是调算法,而是搞清楚你手里的文件到底是什么格式。我见过不少新手,拿着一个 .exr 文件当普通图片去读,结果数据全乱套了。说白了,不同格式背后藏着完全不同的数据组织方式、位深、色彩空间,甚至商业授权逻辑。这一章我们就把这四种主流格式掰开揉碎讲清楚。
为什么 HDR 需要专用格式?
普通 8-bit JPEG 每个通道只能存 0-255 的整数,而真实世界的亮度范围可以跨越 10 个数量级。你想想看,太阳直射和阴影下的细节,JPEG 根本存不下。HDR 格式的核心能力就两个:高动态范围和宽色域。它们用浮点数或对数编码来保留亮部与暗部的完整信息。
一句话总结:HDR 格式不是“更清晰的图片”,而是“能存更多光信息的容器”。
四种格式速览
| 格式 | 位深 | 编码方式 | 典型用途 | 我的评价 |
|---|---|---|---|---|
| OpenEXR | 16-bit / 32-bit 浮点 | 线性浮点 + 无损/有损压缩 | 影视后期、VFX、合成 | 工业标准,没有之一 |
| Radiance HDR | 32-bit 每像素 | RGBE 共享指数 | 光照分析、全景图 | 老牌格式,兼容性好 |
| HDR10 | 10-bit 每通道 | PQ 曲线(ST 2084) | 流媒体、蓝光、游戏 | 消费级主流 |
| Dolby Vision | 12-bit 每通道 | PQ 曲线 + 动态元数据 | 高端影院、旗舰电视 | 画质天花板,但授权贵 |
OpenEXR —— 影视后期的“通用语”
我个人习惯把 OpenEXR 叫做“HDR 界的 PDF”。它由 Industrial Light & Magic 在 1999 年开源,现在已经是 VFX 管线的标准交换格式。为什么大家都用它?
- 浮点精度:16-bit half float 已经能覆盖 10 档曝光,32-bit full float 更是无脑保留所有信息。
- 多通道支持:一个 .exr 文件可以同时存 RGB、Alpha、Z-depth、运动向量、甚至自定义 AOV。
- 压缩灵活:PIZ 无损压缩对平滑区域效果极好,ZIP 适合小文件,DWAA/DWAB 有损压缩用于实时预览。
我的经验:做边缘保留滤波时,我强烈建议用 16-bit half float 的 OpenEXR 作为中间格式。它既保留了足够精度,又不会像 32-bit 那样把硬盘撑爆。我曾经在一个 4K 序列上用 32-bit 存,结果一个镜头就占了 200GB……
# 用 OpenEXR 读取像素值(Python 示意)
import OpenEXR
import numpy as np
exr_file = OpenEXR.InputFile("frame_001.exr")
header = exr_file.header()
dw = header['dataWindow']
width = dw.max.x - dw.min.x + 1
height = dw.max.y - dw.min.y + 1
# 读取 R 通道,返回的是 float16 字符串
r_str = exr_file.channel('R', Imath.PixelType(Imath.PixelType.HALF))
r = np.frombuffer(r_str, dtype=np.float16).reshape(height, width)
Radiance HDR —— 老将依然能打
Radiance HDR(.hdr / .pic)诞生于 1985 年,比 OpenEXR 还早。它的核心设计是 RGBE 编码:每个像素用 4 个字节,前三个是 RGB 尾数,第四个是共享指数。说白了,就是用 8-bit 的精度去模拟 32-bit 的动态范围。
优点很明显:文件小、解析快、几乎所有 HDR 工具都支持。缺点也很致命:精度不够,做细节增强时容易出现色带。我一般在做光照分析或环境贴图时才会用它,做精细滤波处理基本不考虑。
避坑指南:我曾经在某个项目里直接用 .hdr 做细节增强,结果暗部区域出现了明显的量化噪声。后来换成 OpenEXR 就没事了。如果你要做边缘保留滤波,不要用 Radiance HDR 作为中间格式,它只适合最终交付或预览。
HDR10 —— 消费电子的“标配”
HDR10 是目前最普及的消费级 HDR 格式。它基于 PQ(Perceptual Quantizer)曲线,也就是 SMPTE ST 2084。PQ 曲线的设计很有意思:它把亮度映射到人眼的感知均匀空间,而不是线性空间。10-bit 的精度在 PQ 域里已经能覆盖 0.0001 到 10000 cd/m² 的范围。
但 HDR10 有个硬伤:静态元数据。整部影片只用一个 MaxCLL(最大内容亮度)和一个 MaxFALL(最大帧平均亮度)来描述亮度范围。遇到场景切换时,暗场和亮场无法单独优化。
| 参数 | HDR10 | Dolby Vision |
|---|---|---|
| 位深 | 10-bit | 12-bit |
| 元数据 | 静态(全局) | 动态(逐场景) |
| 峰值亮度 | 最高 10000 cd/m² | 最高 10000 cd/m² |
| 色域 | BT.2020 | BT.2020(更宽) |
| 授权费用 | 免费 | 需授权 |
Dolby Vision —— 天花板级别的 HDR
Dolby Vision 在 HDR10 的基础上做了两件事:12-bit 精度和动态元数据。动态元数据意味着每一帧或每一个场景都可以有自己的亮度映射曲线。你想想看,一个爆炸场景和一个烛光场景,用同一套映射参数显然不合理。Dolby Vision 就是来解决这个问题的。
不过,Dolby Vision 的生态比较封闭。编码需要 Dolby 的认证工具,播放端也需要硬件支持。我在实际项目中很少拿它做算法开发,更多是作为最终交付目标去适配。
我的建议:做 HDR 图像处理研究,首选 OpenEXR。做工程落地,优先兼容 HDR10。Dolby Vision 和 Radiance HDR 按需使用,不要一开始就陷入格式细节里。
四种格式的核心关系
下面这张图帮你理清思路:
格式选择决策清单
- 做算法原型:OpenEXR 16-bit half float,无损压缩。
- 做光照分析:Radiance HDR,工具链成熟。
- 做流媒体适配:HDR10,兼容性最好。
- 做高端影院:Dolby Vision,但注意授权成本。
- 做中间交换:OpenEXR,多通道支持无可替代。
小技巧:如果你不确定该用哪种格式,先问自己三个问题:1)这个数据要保留多少精度?2)最终在哪里播放?3)团队里其他人用什么?答案自然就出来了。