#[derive(Debug, Clone, Copy, PartialEq)]
pub enum LensProfile {
GoproHero9Wide,
GoproHero11Linear,
Iphone14ProMain,
DjiMini3ProWide,
Custom {
k1: f32,
k2: f32,
scale: f32,
},
}
impl LensProfile {
pub fn coefficients(&self) -> (f32, f32, f32) {
match self {
Self::GoproHero9Wide => (-0.21, 0.05, 1.05),
Self::GoproHero11Linear => (-0.04, 0.01, 1.01),
Self::Iphone14ProMain => (-0.03, 0.00, 1.01),
Self::DjiMini3ProWide => (-0.16, 0.03, 1.03),
Self::Custom { k1, k2, scale } => (*k1, *k2, *scale),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn gopro_hero9_wide_should_have_expected_coefficients() {
let (k1, k2, scale) = LensProfile::GoproHero9Wide.coefficients();
assert!((k1 - (-0.21_f32)).abs() < f32::EPSILON);
assert!((k2 - 0.05_f32).abs() < f32::EPSILON);
assert!((scale - 1.05_f32).abs() < f32::EPSILON);
}
#[test]
fn iphone14_pro_main_should_have_expected_coefficients() {
let (k1, k2, scale) = LensProfile::Iphone14ProMain.coefficients();
assert!((k1 - (-0.03_f32)).abs() < f32::EPSILON);
assert!((k2 - 0.00_f32).abs() < f32::EPSILON);
assert!((scale - 1.01_f32).abs() < f32::EPSILON);
}
#[test]
fn custom_should_return_supplied_values() {
let (k1, k2, scale) = LensProfile::Custom {
k1: -0.1,
k2: 0.02,
scale: 1.02,
}
.coefficients();
assert!((k1 - (-0.1_f32)).abs() < f32::EPSILON);
assert!((k2 - 0.02_f32).abs() < f32::EPSILON);
assert!((scale - 1.02_f32).abs() < f32::EPSILON);
}
#[test]
fn custom_identity_should_return_zero_k1_k2_and_unit_scale() {
let (k1, k2, scale) = LensProfile::Custom {
k1: 0.0,
k2: 0.0,
scale: 1.0,
}
.coefficients();
assert!((k1 - 0.0_f32).abs() < f32::EPSILON);
assert!((k2 - 0.0_f32).abs() < f32::EPSILON);
assert!((scale - 1.0_f32).abs() < f32::EPSILON);
}
}