lensfun
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.
What it does
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).
Why pure Rust
- 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.
Quick start
use ;
let db = load_bundled?;
let cameras = db.find_cameras;
let camera = cameras.first.expect;
let lenses = db.find_lenses;
let lens = lenses.first.expect;
let = ;
let mut modifier = new;
modifier.enable_distortion_correction;
modifier.enable_tca_correction;
modifier.enable_vignetting_correction;
// Per-row coordinate transform (one row of `width` pixels).
let mut coords = vec!;
modifier.apply_geometry_distortion;
# Ok::
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).
Status
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.
License
- 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.
Acknowledgements
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.