mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-25 02:30:15 -06:00
Cause: a floating-point CFA DNG is read as stored (no check of its float samples). AHD and PPG clamp each green estimate between its two neighbouring greens with `est.clamp(a.min(b), a.max(b))`; when both greens are NaN the bounds are NaN and `f32::clamp` panics (ppg.rs:45, ahd.rs green pass). Any float DNG with two adjacent NaN greens crashed decode + develop. Infinities alone did not panic but turned into NaN in the demosaic arithmetic. Fix, at two layers: - demosaic: a `clamp_between` helper replaces the three clamps. With finite or infinite bounds it is the same `f32::clamp` call (bit-identical results); with NaN bounds it returns the estimate unclamped, so the panic is gone whatever puts NaN into the mosaic. - DNG decode: non-finite float samples are replaced where the white level is known. NaN and -inf read as black (0), +inf as the white level (a clipped highlight). No sensor records NaN or infinity, so a valid file is never touched; finite samples, negative or above white included, stay as stored. Tests: `demosaic::tests::non_finite_samples_do_not_panic` (NaN block, +/-inf and an all-NaN mosaic through Bilinear, PPG and AHD; plus `clamp_between` equal to the old clamp bit for bit over finite, signed-zero and infinite values) and `non_finite_float_samples_decode_and_develop` (a float CFA DNG, uncompressed and Deflate, with NaN and +/-inf samples: decoded values checked, develop with all three methods gives a finite image). Both panicked before the fix at ppg.rs:45 / ahd.rs. Co-Authored-By: Claude <noreply@anthropic.com>