读取 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 格式。

这个传感器是可考的,大概率是 IMX-461。(并非大概率,3FR 文件里直接能找到传感器型号是 IMX-461BQR)

哈苏有几种文件格式,主要是 3FR 和 fff 文件,可以通过 Phocus 软件从 3FR 转换到 fff。转换的时候需要选择调整和是否使用 3FR 内嵌配置,不影响生成的 fff 文件在其他软件中的结果(比如用 rawpy 读是一样的)。观察文件头可以发现,3FR 是 49 49 2A 00 开头的小端序 TIFF 规范,fff 是 4D 4D 00 2A 开头的大端序 TIFF。

IMX461-BQR 的规格书是公开的,总像素 11760x8896,有效像素 11664x8750,启动像素 11656x8742。

用 dcraw 或 rawpy 读取出的是一个 11904x8842 大小,已经超过了传感器的总像素,边上有一圈噪点样的东西(左 76px,右 68px,上 2px,下没有),再靠内是光学黑场(左右 48px,上 90px,下没有),最内侧是一个 11664x8750 大小的图像。包括黑场在内的图像宽度是 11760(等同于总像素),高度是 8840(这个比较奇怪)

3FR 和 fff 都可以转成 DNG,转出来是内圈图像的尺寸,也是可以和图像对齐的,但亮度不同。

目前来看,哈苏 RAW 的最佳读取方法应该是用 libraw 读取 3FR 后取其中的画面部分,还可以用黑场进行黑电平矫正。

Fuji 和 Nikon

待续

发现研究这个收益实在是太低了,还要学习很多东西,等粗浅的搞完 Fuji 和 Nikon 就暂停。