I’ve been investigating the following caveat in darktable’s documentation for the Color Calibration module:
“Some cameras, most notably those from Olympus and Sony, have unexpected white balance coefficients that will always make the detected CCT invalid even for legitimate daylight scene illuminants. This error most likely comes from issues with the standard input matrix, which is taken from the Adobe DNG Converter.”
I wanted to understand exactly what Adobe DNG Converter does differently for Sony cameras that makes the coefficients “unexpected”.
My understanding is that darktable’s standard input matrix is derived from the DNG ColorMatrix, specifically the matrix associated with the D65 reference illuminant. These matrices are stored in RawSpeed’s camera database.
However, the DNG documentation states that the XYZtoCamera matrix is the product of the AnalogBalance matrix (AB), the CameraCalibration matrix (CC) and the ColorMatrix (CM):
XYZtoCamera = AB*CC*CM
Thus, CM is only approximately equal to XYZtoCamera when AB and CC are close to the identity matrix (note that they are both diagonal). In most cases I found, this is true for AB, but not for CC (for Sony models at least). Furthermore, it can change between pictures from the same camera.
For example, two a6100 files produce:
Camera Calibration: 0.888 0 0 0 1 0 0 0 0.9827
and:
Camera Calibration: 0.9091 0 0 0 1 0 0 0 0.9742
I expected the camera calibration to be static for a given camera, so I initially wondered what was causing the calibration coefficients to change.
Reverse engineering
Looking at the corresponding Sony RAW metadata revealed that the values are closely related to the WB RGB Levels Daylight values.
For example:
WB RGB Levels Daylight: 2928 1024 1848
Camera Calibration: 0.888 1 0.9827
and:
WB RGB Levels Daylight: 2860 1024 1864
Camera Calibration: 0.9091 1 0.9742
It turns out that the red (CC_R) and blue (CC_B) components of the CC matrix are inversely proportional to WB daylight levels (D):
CC_R = c_R / D_R
CC_G = 1
CC_B = c_B / D_B
where c_R and c_B are constants (for the a6100, c_R=2600 and c_B=1816).
I verified this by reverse engineering Adobe DNG Converter using Ghidra. I found that an internal camera identifier is mapped to two constants k_R and k_B, which are the numerators of a division. I have not yet identified the code that supplies the denominator. However, comparing them against the ARW metadata suggests that the denominators are D_R / 1024 and D_B / 1024.
CC_R = k_R / (D_R / 1024)
CC_B = k_B / (D_B / 1024)
For the a6100, the static constants are
k_R = 2.5390625 = 2600 / 1024 = c_R / 1024
k_B = 1.7734375 = 1816 / 1024 = c_B / 1024
Thus, CC_R = 2600 / D_R and CC_B = 1816 / D_B.
Experimentation
I tested additional Sony cameras using ARWs from raw.pixls.us and corresponding DNGs generated with Adobe DNG Converter.
Here are the extracted constants from Adobe DNG converter:
| Model | Internal ID | k_R | k_B | 1024*k_R | 1024*k_B |
|---|---|---|---|---|---|
| ILCE-6100 | 0x2b0 | 2.5390625 | 1.7734375 | 2600 | 1816 |
| ILCE-6400 | 0x2b3 | 2.5390625 | 1.7734375 | 2600 | 1816 |
| ILCE-6600 | 0x2b6 | 2.5390625 | 1.7734375 | 2600 | 1816 |
| ILCE-6700 | 0x2b7 | 2.641601563 | 1.705078125 | 2705 | 1746 |
| ILCE-7M3 | 0x2bd | 2.40625 | 1.47265625 | 2464 | 1508 |
| ILCE-7M4 | 0x2be | 2.354492188 | 1.599609375 | 2411 | 1638 |
And here is the relevant metadata extracted from each RAW, along with the resulting CameraCalibration coefficients:
| Model | D_R | D_G | D_B | AB_R | AB_G | AB_B | AsShotNeutral (R) | AsShotNeutral (G) | AsShotNeutral (B) | CC_R | CC_G | CC_B | CC_R * D_R | CC_B * D_B | File |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ILCE-6100 | 2760 | 1024 | 1884 | 1 | 1 | 1 | 0.372093 | 1 | 0.543524 | 0.9420 | 1 | 0.9639 | 2599.92 | 1815.99 | DSC00033.ARW |
| ILCE-6400 | 2616 | 1024 | 1900 | 1 | 1 | 1 | 0.363636 | 1 | 0.589862 | 0.9939 | 1 | 0.9558 | 2600.04 | 1816.02 | DSC00087.ARW |
| ILCE-6400 | 2524 | 1024 | 1880 | 1 | 1 | 1 | 0.383234 | 1 | 0.584475 | 1.0301 | 1 | 0.9660 | 2599.97 | 1816.08 | DSC00475.ARW |
| ILCE-6600 | 2760 | 1024 | 1908 | 1 | 1 | 1 | 0.364154 | 1 | 0.550538 | 0.9420 | 1 | 0.9518 | 2599.92 | 1816.03 | DSC0268.ARW |
| ILCE-6700 | 2579 | 1024 | 1705 | 1 | 1 | 1 | 0.408456 | 1 | 0.585143 | 1.0489 | 1 | 1.0240 | 2705.11 | 1745.92 | DSC00001.ARW |
| ILCE-6700 | 2579 | 1024 | 1705 | 1 | 1 | 1 | 0.409764 | 1 | 0.583144 | 1.0489 | 1 | 1.0240 | 2705.11 | 1745.92 | DSC00002.ARW |
| ILCE-7M3 | 2352 | 1024 | 1656 | 1 | 1 | 1 | 0.450704 | 1 | 0.568889 | 1.0476 | 1 | 0.9106 | 2463.96 | 1507.95 | DSC0009.ARW |
| ILCE-7M3 | 2352 | 1024 | 1656 | 1 | 1 | 1 | 0.456328 | 1 | 0.561404 | 1.0476 | 1 | 0.9106 | 2463.96 | 1507.95 | DSC0010.ARW |
| ILCE-7M4 | 2456 | 1024 | 1691 | 2.366211 | 1 | 1.757813 | 1 | 1 | 1 | 0.9817 | 1 | 0.9687 | 2411.06 | 1638.07 | ILCE-7M4_DSC06676_FullFrame-LossLess-Compressed-Small.ARW |
| ILCE-7M4 | 2456 | 1024 | 1691 | 1 | 1 | 1 | 0.421573 | 1 | 0.574313 | 0.9817 | 1 | 0.9687 | 2411.06 | 1638.07 | ILCE-7M4_DSC06677_FullFrame-Raw-Compressed.ARW |
In each case, the relationship holds. All camera models tested went through the same code path for the CC calculation.
The ILCE-7M4 is interesting because the two RAWs have different AnalogBalance values, despite producing the same CameraCalibration coefficients. The files also use different compression modes. I don’t know yet whether the two are related.
I initially suspected that CameraCalibration might be derived from AsShotNeutral, since the first few cameras appeared to show a relationship between the two. However, the ILCE-7M4 disproves this: one of the files has AsShotNeutral = [1,1,1] while the CameraCalibration is still [0.9817,1,0.9687]. The relationship with WB RGB Levels Daylight, on the other hand, continues to hold.
Remaining questions
I’m not sure where the constants come from, what effect they have on the white balance and whether they are unique to Sony. I also don’t know what the mystery IDs I found in the switch case stand for (the camera model?). The fact that different internal IDs can map to the same constants is also interesting.
I’d be particularly interested to know whether anyone recognizes these constants or the purpose of the internal camera identifier.
The remaining question is whether this explains the darktable caveat. I don’t have a definitive answer yet. However, when I apply CC * CM before using the resulting matrix as the input matrix, I obtain correct CCT detection for some of the images where the original matrix produces an invalid result. This suggests that the CameraCalibration values may indeed be related to the issue described in the darktable documentation.
I’m currently doing this manually, but I’m planning to write something that does this automatically using the right constants for my own camera.
Finally, I’m not sure whether AnalogBalance also needs to be incorporated, or exactly how (or whether) darktable should account for these matrices.








