fix(raw): resolve RAW green-yellow color cast via cam_xyz prioritization, daylight WB fallback, and fitMatch sanity checks
This commit is contained in:
@@ -169,6 +169,10 @@ export function fitMatch(dev: Uint8Array, ref: Uint8Array, n = MATCH_GRID): Matc
|
||||
// and -1.67), and refusing those refused the whole fit — those bodies opened
|
||||
// byte-identical to an unfitted develop.
|
||||
for (const v of m) if (!Number.isFinite(v) || Math.abs(v) > 4) return null;
|
||||
// Sanity check: diagonal elements should be positive and reasonable
|
||||
if (m[0] < 0.1 || m[4] < 0.1 || m[8] < 0.1 || m[0] > 3.0 || m[4] > 3.0 || m[8] > 3.0) return null;
|
||||
// Reject fitted matrix if green channel is unnaturally boosted over red and blue (prevents yellow-green cast)
|
||||
if (m[4] > m[0] * 2.5 || m[4] > m[8] * 2.5) return null;
|
||||
// The 3x3 alone cannot bend a channel — it can only scale it — and what is left
|
||||
// between the two frames is mostly exactly that bend. So the residual after the
|
||||
// 3x3 is fitted a cubic a channel, on the value the 3x3 leaves.
|
||||
|
||||
@@ -145,7 +145,7 @@ half4 main(float2 pos) {
|
||||
// The matrix was fitted luma-preserving, so mx is the value to hold.
|
||||
float hi = max(max(n.r, n.g), n.b);
|
||||
hi = max(hi, max(max(lin.r, lin.g), lin.b));
|
||||
rgb = mix(rgb, float3(mx), smoothstep(0.92, 1.0, hi));
|
||||
rgb = mix(rgb, float3(mx), smoothstep(0.99, 1.02, hi));
|
||||
// The overflow used to fade towards white — mix(rgb / mx, 1, 1 - 1 / mx) —
|
||||
// which put every pixel of a blown sky on exactly 1.0 and threw the two stops
|
||||
// the sensor held above white away with it: LIGHT's HIGHLIGHT row then had a
|
||||
@@ -440,14 +440,6 @@ function invert3x3(m: number[][]): number[][] | null {
|
||||
}
|
||||
|
||||
function getCamToSrgbMatrix(cd: any): number[][] {
|
||||
if (cd?.rgb_cam && Array.isArray(cd.rgb_cam) && cd.rgb_cam.length >= 3) {
|
||||
return [
|
||||
[cd.rgb_cam[0][0] || 0, cd.rgb_cam[0][1] || 0, cd.rgb_cam[0][2] || 0],
|
||||
[cd.rgb_cam[1][0] || 0, cd.rgb_cam[1][1] || 0, cd.rgb_cam[1][2] || 0],
|
||||
[cd.rgb_cam[2][0] || 0, cd.rgb_cam[2][1] || 0, cd.rgb_cam[2][2] || 0],
|
||||
];
|
||||
}
|
||||
|
||||
if (cd?.cam_xyz && Array.isArray(cd.cam_xyz) && cd.cam_xyz.length >= 3) {
|
||||
const cx = cd.cam_xyz;
|
||||
const scale = (Math.abs(cx[0][0]) > 100) ? 10000.0 : 1.0;
|
||||
@@ -470,6 +462,14 @@ function getCamToSrgbMatrix(cd: any): number[][] {
|
||||
return [[m00, m01, m02], [m10, m11, m12], [m20, m21, m22]];
|
||||
}
|
||||
|
||||
if (cd?.rgb_cam && Array.isArray(cd.rgb_cam) && cd.rgb_cam.length >= 3) {
|
||||
return [
|
||||
[cd.rgb_cam[0][0] || 0, cd.rgb_cam[0][1] || 0, cd.rgb_cam[0][2] || 0],
|
||||
[cd.rgb_cam[1][0] || 0, cd.rgb_cam[1][1] || 0, cd.rgb_cam[1][2] || 0],
|
||||
[cd.rgb_cam[2][0] || 0, cd.rgb_cam[2][1] || 0, cd.rgb_cam[2][2] || 0],
|
||||
];
|
||||
}
|
||||
|
||||
return [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
|
||||
}
|
||||
|
||||
@@ -483,7 +483,7 @@ export async function developRaw(bytes: Uint8Array): Promise<Uint8Array> {
|
||||
const meta = await raw.metadata(true);
|
||||
const img = await raw.imageData();
|
||||
const cd = meta?.color_data;
|
||||
if (!img || !cd?.cam_mul || (!cd.rgb_cam && !cd.cam_xyz)) throw new Error('RAW has no colour data');
|
||||
if (!img || (!cd?.cam_mul && !cd?.pre_mul) || (!cd.rgb_cam && !cd.cam_xyz)) throw new Error('RAW has no colour data');
|
||||
|
||||
const { width: w, height: h } = img;
|
||||
const data = img.data as Uint16Array;
|
||||
@@ -494,9 +494,9 @@ export async function developRaw(bytes: Uint8Array): Promise<Uint8Array> {
|
||||
|
||||
const rawMul = (cd?.cam_mul && cd.cam_mul.some((v: number) => v > 0 && v !== 1))
|
||||
? cd.cam_mul
|
||||
: (cd?.pre_mul && cd.pre_mul.some((v: number) => v > 0))
|
||||
: (cd?.pre_mul && cd.pre_mul.some((v: number) => v > 0 && v !== 1))
|
||||
? cd.pre_mul
|
||||
: [1, 1, 1, 1];
|
||||
: [2.0, 1.0, 1.5, 1.0];
|
||||
const green = rawMul[1] || rawMul[3] || 1;
|
||||
const mul = rawMul.map((v: number) => v / green);
|
||||
const [r0, r1, r2] = getCamToSrgbMatrix(cd);
|
||||
|
||||
Reference in New Issue
Block a user