读取 raw 数据的工具
Dcraw
最著名的读取 raw 数据的工具莫过于 dcraw。Dcraw 能够将各种编码方式的 raw 文件转换成 TIFF 或 PPM 格式。
使用命令行 dcraw -4 -T -D file_name 就能够获得一个 16 bit 的 TIFF 文件,记录了 raw 的直接数值,没有经过包括解拜尔、白平衡、扣除黑电平在内的操作。
遗憾的是,dcraw 的最后一次更新是 2018 年 6 月 1 日。因此之后相机的附加参数(白平衡,颜色矩阵等)不再包含,仅用于提取 raw 数据的功能也不一定能够正常使用。
比如说:对于索尼在四代机(ILCE-7M4)中加入的无损压缩 RAW 格式,虽然后缀名都是 arw,但 dcraw 会报 cannot decode file 的错误,而和之前一样的无压缩 RAW 是可以解的。
dcraw.c 是 dcraw 的核心文件,由一万多行纯 c 语言完成。
Rawpy/Libraw
Rawpy 是 libraw 的 python warpper。Libraw 提供了访问 raw 数据的统一接口,用于提取像素值,它基于 dcraw,将 dcraw.c 重构为更现代和模块化的库,并在 dcraw 停止维护后继续支持。
各方法和品牌的差别
Sony
无压缩 RAW
测试机型是 ILCE-7 CM2:
以下方式读取的无压缩 RAW 结果是一样的:
- Dcraw 转 tiff 后用 openimageio 读取
- 直接用 rawpy 读取
- 用 adobe DNG converter 转换后用 rawpy 读取
- 用 adobe camera raw 转换后用 rawpy 读取(同上,虽然在 acr 中查看尺寸时不同)
- 用 adobe DNG converter 转换后,用 dcraw 转 tiff 再用 oiio 读取
以上方法读出的尺寸是 (4688, 7040),33003520 像素,范围是 0-16383.
实际上,用 adobe dng converter 和 adobe camera raw 转换的 dng 是一样的,以下不再赘述。Rawpy 和 dcraw 读取 dng 也是等效的。
以下是会发生变化的:
- Captrue One 转换 dng 后,用 rawpy 读取(或用 dcraw 转 tiff 再读取)。图像会变成 (4672, 7008) 范围是 0-65535。高少的 16 个像素是上下各 8 个,长少的 32 个像素是左 12 右 20。裁切后和上面几种方法也有区别,按照商(都归一化,按照 65535 或 16383)来看,最大 1.04,最小 0.95,平均 1.00。这个对齐是在 ps 里用肉眼完成的。
无损压缩 RAW
索尼的无损压缩 RAW 原理是先补 0 到 512 的倍数,然后分块,再按照 bayer 分四个子图进行差分编码和霍夫曼编码。
对于无损压缩 RAW 来说,情况比较复杂,因为目前没有办法在无压缩的 ARW 和无损压缩的 ARW 间转换(如果分两次拍,即使使用联机拍摄,带来的位移等误差也大于一个像素)。以下是经过测试的情况:
- Dcraw 不支持无损压缩 RAW(因为索尼引入无损压缩 RAW 时 dcraw 已不再更新)。
- Rawpy 读取 ARW,得到的是 (5120, 7168) 尺寸,这是由于分块压缩导致的(512 的倍数),只有左上角 (4688, 7040) 区域有内容,剩下的是 0(而不是黑电平),数值是 0-16383。
- 用 adobe DNG converter 转换成 dng 后用 rawpy 读取,得到的尺寸是 (4686, 7038),比无压缩 RAW 等少两个像素。上一种情况中再去掉底部和右边各 2 像素,可以完全匹配,也是 0-16383。
- 用 Capture One 转换出的 dng 用 rawpy 读取,得到的尺寸也是 (4672, 7008),范围 0-65535。同样是上下 8 像素,左 12 右 20,裁切 rawpy 读取的 ARW 的有内容部分后基本匹配(甚至差值的平均值都是一样的 -5e-6 左右,需要进一步测试)。
关于 Capture One 的 DNG
理论上,一个解码 RAW 并编码到 DNG 的编解码器不会带来太复杂的误差。但 Capture One 导出的 DNG 不仅尺寸有区别,还会将原本 14 bit 的数据拉伸到 16 bit,且不能与其它方法读的 raw 完全匹配。
在 Gemini 和 DeepSeek 的帮助下,进行了一些更细致的分析。关于如何从 14 bit 到 16 bit,Capture One 进行的应该是左移两位,即直接 *4。将 rawpy 读取的 arw 左移后与 C1 导出的 dng 相除与相减,得到的商为 1.000004,差也是 e-7 的数量级。其中,R 和 B 通道是完全匹配的,误差全部来自两个 G 通道,而且和图像内容有关,个别图像中,G 的最大误差甚至能达到 10%,多数情况下,最大误差不超过 5%。
Sony RAW 的最佳实践
综上,最推荐的 Sony RAW 使用方法是拍摄无压缩的 RAW 之后直接用 Rawpy 读取,用 dng converter 可以方便的把无压缩 RAW 转换成无损压缩的 DNG 来减少体积,同时不会有任何损失,或是无损压缩 RAW 用 Rawpy 读取并做裁切,但注意无损压缩 RAW 转换成 DNG 时会损失两行两列像素。而其它方法获得的 DNG 存在未知因素,不应使用。
Canon
测试机型是 600D,输出的是 CR2。
用 rawpy 和转成 dng 之后读取是一致的,图像尺寸是 (3516, 5344),左边 142 像素和上方 51 像素应该是光学黑场(被物理遮盖用于黑电平校正的部分),能读出近似黑电平的数值,剩余部分是图像。
Dcraw 是可以处理 600D 的,读出的是没有光学黑场的部分,这一部分和裁切后的 rawpy 或 dng 匹配。
R6 Mark 2 输出的 CR3 (用 rawpy 或转成 dng 读取)也类似,左侧 154 个像素、顶部 96 个像素是光学黑场,另外右侧还有 8 个像素的白色区域。
Hasselblad
测试机型为哈苏 X2D-100C,相机直接输出 3FR 格式的 RAW 文件。其传感器型号可从 3FR 文件中直接确认,为索尼 IMX461-BQR。
哈苏的 RAW 工作流历史上涉及 3FR 和 FFF 两种文件格式。
随着新版 Phocus 的发布,FFF 文件已被移出 RAW 工作流,现在无需先转换到 FFF 再处理 RAW 图像。
在旧版流程中,用户可以通过 Phocus 软件将 3FR 转换为 FFF。转换时有一些可选的调整选项,但这不影响 FFF 文件本身的原始数据(例如,使用 rawpy 读取的结果都相同)。从文件头可以发现,3FR (49 49 2A 00) 遵循小端序 TIFF 规范,而 FFF (4D 4D 00 2A) 则是大端序 TIFF。
IMX461-BQR 的公开规格显示,其总像素为 11760×8896,有效像素为 11664×8750。然而,使用 dcraw 或 rawpy 等工具直接解析 3FR 文件,会得到一个 11904×8842 的超大图像。这个图像包含了以下几个区域:
- 图像内容区: 尺寸为 11664×8750,与 461 的有效像素一致。
- 光学黑场 (Optical Black): 包围在图像内容区外,左右各 48px,上方 90px。
- 额外内容: 在最外围,包含左侧 76px、右侧 68px 和上方 2px 的非图像数据。
分析可知,包含光学黑场在内的图像宽度为 11760px(与传感器总像素宽度吻合),但高度为 8840px,略有出入。
无论是 3FR 还是 FFF,都可以转换为 DNG 格式,转换后的 DNG 文件尺寸会裁切到与有效像素区一致,内容上,虽然画面内容能够对齐,但数值上有一些小区别。
所以目前来看,处理哈苏 3FR 文件的最佳实践是直接使用 libraw 读取,提取出有效的图像区域,并利用图像中的光学黑场数据进行精确的黑电平校正。
Fujifilm
测试机型是 X-T5。
富士的 raw 比较特殊,因为其表面的滤色片不是普通的拜尔排列,而是 X-Trans,最小重复单元是 6 行 6 列。好在不影响我们分析 raw 图像本身。
把 RAF 直接输入 rawpy,得到的图像长 7872,高 5196,转换成 DNG 后,长 7728,高 5152。多出来的长 44 个像素,高 144 个像素具体分布是:
- 左侧 12 个有画面的像素,右侧 12 个有画面的像素和 120 个黑。
- 顶部 16 个有画面的像素和 5 个黑,底部 16 画面 7 黑。
重叠部分的像素值是完全一样的。
另外,rawpy 读取 raf 的 raw pattern 有错误,dng 中的 raw pattern 是正确的。
Nikon
待续
发现研究这个收益实在是太低了,还要学习很多东西,等粗浅的搞完 Nikon 就暂停。在实际使用中,推荐直接用 dng convertor 转换成 dng,用 rawpy 读取,可以直接获得图像内容。