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 三种格式的结构对比图

下面这张图展示了三种格式的核心结构差异,方便你直观理解:

三种RAW格式结构对比 DNG (TIFF/EP标准) TIFF Header + IFD链 SubIFD → RAW数据 BlackLevel Tag (标准) Exif + Makernote CR2 (佳能魔改TIFF) TIFF Header + 私有偏移 IFD 0 → RAW信息 SensorInfo (私有Tag) Makernote + 拜耳信息 NEF (尼康加密TIFF) TIFF Header + 加密标识 加密RAW数据块 Makernote (含密钥) NEF压缩算法 DNG最规范,CR2有私有偏移,NEF有加密——解析策略完全不同 建议:通用工具优先支持DNG,专用工具按机型适配CR2/NEF 解析流程对比 解析流程对比 解析流程对比 读Header → 找SubIFD 读BlackLevel Tag 解压 → 提取RAW数据 读Header → 计算私有偏移 读SensorInfo 解压 → 提取RAW数据 读Header → 提取密钥 解密RAW数据块 解压 → 提取RAW数据

2.8 小结

RAW格式解析,说白了就是跟文件结构打交道。DNG最友好,CR2有私有坑,NEF有加密锁。我的建议是:先吃透DNG,再逐个攻克CR2和NEF。别想一口吃成胖子。