Pure-Rust port of LensFun β camera lens correction without C dependencies.
Verified equivalent to upstream LensFun. Across 1,640 A/B test cases (6 lenses Γ 4-5 focal lengths Γ 30 coordinates Γ forward/reverse), the Rust port matches the C++ original within a max delta of 4.9 Γ 10β»β΄ pixels β about 2,000Γ under the 1 Γ 10β»Β³ tolerance the upstream regression suite uses. On the production-shape benchmark (per-row
apply_*calls, Apple Silicon, both sides scalar) the Rust port runs faster than upstream on every kernel β distortion 1.18Γ, TCA 1.12Γ, vignetting 1.47Γ. Seedocs/comparison-with-c-library.mdfor the methodology, results, and how to reproduce the comparison locally.
Given a camera body, lens model, and shooting parameters (focal length, aperture, distance), return correction profiles for:
- Distortion β radial barrel/pincushion (
ptlens,poly3,poly5models). - Transverse chromatic aberration (TCA) β per-channel radial shift (
linear,poly3). - Vignetting β radial brightness falloff (
pamodel). - Geometry β convert between rectilinear, fisheye, equirectangular, panoramic.
- Perspective correction β port of
mod-pc.cppwith hand-rolled Jacobi SVD.
The pixel passes are scalar Rust β no SIMD yet (planned post-1.0).
- No
-syscrates, no system libraries, no C toolchain for cross-compilation. - Clean static-linking under LGPL-3.0 with public source.
- Same correction math as upstream LensFun, verified by an automated A/B harness.
use lensfun::{Database, Modifier};
let db = Database::load_bundled()?;
let cameras = db.find_cameras(Some("Canon"), "EOS R5");
let camera = cameras.first().expect("camera in bundled DB");
let lenses = db.find_lenses(Some(camera), "Canon EF 24-70mm f/2.8L II USM");
let lens = lenses.first().expect("lens in bundled DB");
let (width, height) = (6720_u32, 4480_u32);
let mut modifier = Modifier::new(lens, 35.0, camera.crop_factor, width, height, true);
modifier.enable_distortion_correction(lens);
modifier.enable_tca_correction(lens);
modifier.enable_vignetting_correction(lens, 4.0, 5.0);
// Per-row coordinate transform (one row of `width` pixels).
let mut coords = vec![0.0_f32; (width as usize) * 2];
modifier.apply_geometry_distortion(0.0, 0.0, width as usize, 1, &mut coords);
# Ok::<(), lensfun::Error>(())The lens calibration database is bundled (~574 KB gzipped, ~5 MB after decompression). For consumers who want to load from disk instead, use Database::load_dir(path).
Beta. 1,640 A/B test cases pass against upstream LensFun C++ within 4.88 Γ 10β»β΄ pixels β about 2,000Γ under the upstream regression tolerance. The kernel APIs and Modifier surface are stable; minor refinements may land before 1.0.
See CHANGELOG.md for the release history and docs/notes/lensfun-rs.md for the porting plan.
- Code: LGPL-3.0-or-later (derivative of upstream LensFun). See
LICENSE-LGPL-3.0andLICENSE-GPL-3.0(which the LGPL incorporates by reference). - Bundled XML database: CC-BY-SA 3.0 from upstream LensFun contributors.
- See
NOTICEfor full attribution.
This crate is a port of LensFun by Andrew Zabolotny and the LensFun contributors. All correction algorithms, calibration data, and the XML schema are theirs. The Rust port is by @vdavid.