2. RAW文件格式解析:DNG、CR2、NEF的结构差异
做RAW域处理,第一关就是跟各种文件格式打交道。我刚开始接触这行时,以为RAW就是RAW,无非就是传感器数据加个文件头。后来被坑了几次才明白——不同厂商的RAW格式,结构差异大得离谱。
今天咱们就掰开揉碎,看看最常见的三种格式:Adobe的DNG、佳能的CR2、尼康的NEF。搞清楚它们的结构,你才能知道数据到底存在哪、怎么读、哪些坑不能踩。
2.1 为什么会有这么多RAW格式?
说白了,每家相机厂商都想把自己的数据格式做成行业标准。佳能推CR2,尼康推NEF,索尼用ARW,哈苏用3FR……各玩各的。Adobe看不下去了,搞了个开放标准DNG,想一统江湖。
但现实是,DNG虽然开放,厂商们并不买账。为啥?因为RAW格式里藏着厂商的看家本领——去马赛克算法、降噪参数、色彩映射表。这些是商业机密,谁愿意公开?
核心认知:RAW文件不是单纯的传感器数据,而是一个容器。里面装了原始像素数据、元数据、缩略图、甚至相机设置参数。解析RAW,本质上是解析这个容器的结构。
2.2 DNG:Adobe的开放标准
DNG基于TIFF/EP标准,说白了就是用TIFF的壳装RAW的数据。它的结构非常清晰,我个人觉得是最好解析的格式。
2.2.1 DNG文件结构
DNG的核心是IFD(Image File Directory)链。每个IFD指向一块数据,IFD之间通过指针串联。你想想看,这就像链表一样,顺着IFD就能找到所有数据块。
DNG文件结构示意:
[TIFF Header] → [IFD 0: 主图像] → [IFD 1: 缩略图] → [IFD 2: RAW数据]
↓ ↓
[SubIFD: 原始数据] [Exif元数据]
| IFD编号 | 内容 | Tag示例 |
|---|---|---|
| IFD 0 | 主图像(通常是JPEG预览) | ImageWidth, ImageLength |
| SubIFD | RAW传感器数据 | NewSubFileType=0 |
| IFD 1 | 缩略图 | JPEGInterchangeFormat |
| Exif IFD | 拍摄参数 | ISOSpeed, ExposureTime |
我的经验:解析DNG时,先找SubIFD。很多新手直接读IFD 0,结果拿到的是JPEG预览图,不是RAW数据。SubIFD的Tag 0x014A(NewSubFileType)值为0时,才是原始数据。
2.2.2 DNG的压缩方式
DNG支持两种压缩:线性无损压缩和JPEG-LS。我建议你用线性无损,因为JPEG-LS在某些相机上会有精度损失。嗯,这里要注意——虽然JPEG-LS号称无损,但实际测试中,暗部细节会有微小差异。
2.3 CR2:佳能的私有格式
CR2是佳能基于TIFF魔改的格式。说它魔改,是因为佳能在TIFF标准上加了大量私有Tag。我第一次解析CR2时,差点被这些私有Tag搞疯。
2.3.1 CR2的文件布局
CR2的文件头跟TIFF很像,但偏移量计算方式不同。佳能用了自己的偏移算法,你得小心处理字节对齐问题。
CR2文件结构:
[TIFF Header] → [IFD 0: RAW数据信息] → [IFD 1: 缩略图]
↓
[RAW数据块: 传感器数据]
↓
[Sensor Info: 黑电平、白平衡等]
| 偏移量 | 内容 | 字节数 |
|---|---|---|
| 0x0000 | Byte Order (MM/II) | 2 |
| 0x0002 | Magic Number (0x002A) | 2 |
| 0x0004 | IFD偏移量 | 4 |
| 0x0008 | RAW数据偏移量(佳能私有) | 4 |
我曾经踩过的坑:CR2的RAW数据偏移量不是标准的TIFF偏移,而是佳能自定义的。如果你按TIFF标准去读,拿到的数据全是错的。必须用Tag 0x0110(StripOffsets)配合佳能的私有算法计算。
2.3.2 CR2的拜耳排列
佳能CR2的拜耳排列通常是RGGB,但不同机型有差异。我建议你从Makernote里读SensorInfo,里面有拜耳排列的标识。别硬编码,否则换个机型就崩。
2.4 NEF:尼康的加密格式
NEF是尼康的格式,它最大的特点是——加密。尼康在RAW数据上做了简单的异或加密,目的是防止第三方软件直接读取。说实话,这个加密并不强,但足够让新手头疼。
2.4.1 NEF的加密机制
尼康的加密算法其实很简单:用一个固定密钥对RAW数据做逐字节异或。密钥可以从Makernote里提取。我记得第一次破解这个加密时,花了整整两天。
NEF解密伪代码:
uint8_t key[4] = {0x55, 0xAA, 0x33, 0xCC}; // 示例密钥
for (int i = 0; i < raw_size; i++) {
raw_data[i] ^= key[i % 4];
}
避坑指南:不同尼康机型的密钥不同。D800和D850的密钥就不一样。我建议你从Makernote的Tag 0x0097(NikonEncryptionKey)里读,别用硬编码。
2.4.2 NEF的压缩算法
NEF使用尼康自家的NEF压缩算法,这是一种有损压缩。压缩比大约2:1,但暗部细节会有损失。如果你做高精度图像处理,建议用未压缩的NEF。
2.5 三种格式的核心差异对比
咱们用一张表总结一下:
| 特性 | DNG | CR2 | NEF |
|---|---|---|---|
| 基础标准 | TIFF/EP | TIFF魔改 | TIFF魔改 |
| 加密 | 无 | 无 | 有(异或加密) |
| 压缩 | 线性无损/JPEG-LS | 佳能CR2压缩 | NEF压缩(有损) |
| 拜耳排列 | Tag中指定 | Makernote中指定 | Makernote中指定 |
| 黑电平信息 | BlackLevel Tag | SensorInfo中 | Makernote中 |
| 解析难度 | 低 | 中 | 高 |
2.6 实战:如何选择解析策略?
你可能会问:那我到底该用哪种格式?我的建议是:
- 做通用工具:优先支持DNG。它最规范,解析成本最低。
- 做相机配套软件:直接读CR2或NEF,但要做好机型适配。
- 做科研/高精度:用DNG,因为它保留了最完整的元数据。
核心原则:无论哪种格式,第一步永远是读元数据。黑电平、白平衡、拜耳排列、传感器尺寸——这些信息决定了后续所有处理是否正确。我见过太多人跳过元数据直接读像素,结果处理出来的图像全是错的。
2.7 三种格式的结构对比图
下面这张图展示了三种格式的核心结构差异,方便你直观理解:
2.8 小结
RAW格式解析,说白了就是跟文件结构打交道。DNG最友好,CR2有私有坑,NEF有加密锁。我的建议是:先吃透DNG,再逐个攻克CR2和NEF。别想一口吃成胖子。