Skip to content

vdavid/lensfun-rs

lensfun

CI

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Γ—. See docs/comparison-with-c-library.md for 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, poly5 models).
  • Transverse chromatic aberration (TCA) β€” per-channel radial shift (linear, poly3).
  • Vignetting β€” radial brightness falloff (pa model).
  • Geometry β€” convert between rectilinear, fisheye, equirectangular, panoramic.
  • Perspective correction β€” port of mod-pc.cpp with hand-rolled Jacobi SVD.

The pixel passes are scalar Rust β€” no SIMD yet (planned post-1.0).

Why pure Rust

  • No -sys crates, 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 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).

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.0 and LICENSE-GPL-3.0 (which the LGPL incorporates by reference).
  • Bundled XML database: CC-BY-SA 3.0 from upstream LensFun contributors.
  • See NOTICE for 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.

About

Pure-Rust port of LensFun: camera lens correction (distortion, TCA, vignetting) without C dependencies

Topics

Resources

License

GPL-3.0, LGPL-3.0 licenses found

Licenses found

GPL-3.0
LICENSE-GPL-3.0
LGPL-3.0
LICENSE-LGPL-3.0

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors