1. RAW格式解析:从传感器到数字负片
RAW文件是什么?说白了,它就是相机传感器最原始的“电子底片”。JPEG是厨师做好的菜,RAW则是菜市场买回来的新鲜食材——所有后期处理的决定权都在你手里。我做了十几年影像工程,每次拿到一个新机型的RAW文件,都像拆开一份礼物。
这一节,我们拆开RAW文件的外壳,看看里面到底藏着什么。
1.1 RAW文件结构:TIFF的变种与私有魔改
大多数RAW格式都脱胎于TIFF规范。TIFF是一种标签化文件格式,你可以把它想象成一个带目录的文件夹——每个数据块都有对应的标签(Tag)告诉你“这是什么、在哪里、有多大”。
但相机厂商不会老老实实只用标准TIFF。他们会在文件头里塞私有魔改,比如佳能的.CR2、尼康的.NEF、索尼的.ARW。我当年第一次解析.CR2时,对着十六进制看了三个小时才找到图像数据的偏移量——嗯,那感觉就像在迷宫里找出口。
| 文件格式 | 基础规范 | 厂商私有扩展 | 典型后缀 |
|---|---|---|---|
| CR2 | TIFF v6 | CR2私有IFD、传感器校准表 | .CR2, .CR3 |
| NEF | TIFF v6 | 尼康Makernotes、镜头数据 | .NEF, .NRW |
| ARW | TIFF v6 + Sony私有 | Sony Makernotes、压缩表 | .ARW, .SRF |
| DNG | TIFF v6 + Adobe扩展 | 公开规范,无私有魔改 | .DNG |
1.2 拜耳阵列原理:为什么每个像素只有一种颜色?
相机传感器是色盲的——它只能感知光的强度,分不清红绿蓝。那彩色照片怎么来的?靠的是拜耳阵列(Bayer Array)。
拜耳阵列在传感器表面覆盖了一层彩色滤光片,每个像素只允许一种颜色的光通过。最常见的模式是RGGB:一个红色、两个绿色、一个蓝色。为什么绿色有两个?因为人眼对绿色最敏感,多给绿色一些采样,视觉上更自然。
你想想看,一个2400万像素的传感器,实际只记录了600万个红色、1200万个绿色、600万个蓝色信息。剩下的颜色去哪了?靠算法“猜”出来的。这个过程叫去马赛克(Demosaicing),我们后面会专门讲。
1.3 元数据解读:EXIF与Makernotes
RAW文件里除了图像数据,还塞了一大堆元数据。这些数据分成两类:EXIF(可交换图像文件格式)和Makernotes(厂商私有数据)。
EXIF:标准化的相机信息
EXIF是国际标准,所有相机厂商都得遵守。它记录了拍摄时的参数:快门速度、光圈、ISO、焦距、白平衡、时间戳、GPS坐标等等。你可以在任何看图软件里看到这些信息。
但EXIF有个问题——它只记录“用户设置”层面的参数。比如白平衡是“日光”还是“自动”,但不会告诉你传感器具体的色彩校准矩阵。这些更底层的数据,藏在Makernotes里。
Makernotes:厂商的“黑匣子”
Makernotes是相机厂商自己定义的数据区,没有统一标准。每个厂商、甚至每个机型,Makernotes的结构都不一样。这里面藏着什么?
- 传感器校准数据:黑电平、白电平、色彩矩阵、镜头畸变校正参数
- 镜头信息:镜头型号、焦距范围、光圈范围、防抖状态
- 处理参数:降噪强度、锐化设置、色调曲线
- 私有算法数据:佳能的Picture Style、尼康的Picture Control、索尼的Creative Style
1.4 实战:用Python读取RAW元数据
光说不练假把式。我们写几行代码,看看RAW文件里到底有什么。
import rawpy
import exifread
# 读取RAW文件
raw = rawpy.imread('sample.CR2')
# 获取图像数据(拜耳阵列原始值)
bayer = raw.raw_image
print(f"传感器尺寸: {bayer.shape}")
print(f"像素位深: {raw.raw_image.dtype}")
# 读取EXIF元数据
with open('sample.CR2', 'rb') as f:
tags = exifread.process_file(f)
# 打印关键EXIF标签
for tag in ('Image Make', 'Image Model',
'EXIF ExposureTime', 'EXIF ISOSpeedRatings',
'EXIF FocalLength', 'EXIF WhiteBalance'):
if tag in tags:
print(f"{tag}: {tags[tag]}")
# 获取相机白平衡乘数(来自Makernotes)
wb = raw.camera_whitebalance
print(f"相机白平衡乘数 (R/G/B/G2): {wb}")
# 获取黑电平
black_level = raw.black_level_per_channel
print(f"黑电平 (R/G1/G2/B): {black_level}")
# 获取白电平(饱和值)
white_level = raw.white_level
print(f"白电平: {white_level}")
raw.close()
这段代码会输出什么?你会看到传感器尺寸、位深、拍摄参数,还有最重要的——黑电平和白电平。这两个值决定了RAW数据的动态范围边界。我建议你拿到一个新机型的RAW文件后,第一件事就是打印黑电平和白电平,看看它的底子到底有多宽。
1.5 知识结构总览
这一节的内容,可以用下面这张图串起来: