mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-29 04:27:30 -06:00
LR-EDIT-OPTICS-PROFILE: find the profile named by a lens specification behind a tie
Another maker's lens with the same specification ("Otherco 18-55mm f/3.5-5.6")
scores as high as the profile aliased "18-55mm f/3.5-5.6"; when it came first,
find_lens kept it and the exact-name check then refused it, so the alias was
never used. LensDb::find_lens_named ranks only the profiles named exactly so,
with the same maker and mount preferences (review on #2217).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
067f4fdf1e
commit
cb61588e7d
@@ -46,7 +46,7 @@ pub fn lookup(db: &LensDb, m: &lightcraft_meta::Metadata, w: f64, h: f64, orient
|
||||
// (a user's alias), since the specification fits other makers' lenses too
|
||||
None => {
|
||||
let name = lightcraft_lensdb::spec_name(m.lens_spec?);
|
||||
db.find_lens(m.lens_make.as_deref(), &name, camera).filter(|l| l.names_exactly(&name))?
|
||||
db.find_lens_named(m.lens_make.as_deref(), &name, camera)?
|
||||
}
|
||||
};
|
||||
let crop = frame_crop_factor(camera.map(|c| c.crop_factor), focal, m.focal_length_35mm);
|
||||
|
||||
@@ -169,13 +169,24 @@ impl LensDb {
|
||||
/// The best profile for an EXIF lens model (and lens make, when the file has one), preferring lenses for the
|
||||
/// camera's mount. `None` when no name is a convincing match.
|
||||
pub fn find_lens(&self, lens_make: Option<&str>, lens_model: &str, camera: Option<&Camera>) -> Option<&Profile> {
|
||||
self.best_lens(lens_make, lens_model, camera, |_| true)
|
||||
}
|
||||
|
||||
/// [`find_lens`](Self::find_lens) among the profiles one of whose names is exactly `name`
|
||||
/// ([`Profile::names_exactly`]), for names that carry no maker, such as [`spec_name`]s: another maker's lens with
|
||||
/// the same specification scores as high, and must neither win nor, by coming first, hide the profile named so.
|
||||
pub fn find_lens_named(&self, lens_make: Option<&str>, name: &str, camera: Option<&Camera>) -> Option<&Profile> {
|
||||
self.best_lens(lens_make, name, camera, |l| l.names_exactly(name))
|
||||
}
|
||||
|
||||
fn best_lens(&self, lens_make: Option<&str>, lens_model: &str, camera: Option<&Camera>, eligible: impl Fn(&Profile) -> bool) -> Option<&Profile> {
|
||||
let exif = tokens(lens_model);
|
||||
if exif.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let make = lens_make.map(tokens).unwrap_or_default();
|
||||
let mut best: Option<(f64, &Profile)> = None;
|
||||
for lens in &self.lenses {
|
||||
for lens in self.lenses.iter().filter(|l| eligible(l)) {
|
||||
let maker = tokens(&lens.maker);
|
||||
if !make.is_empty() && !maker.is_empty() && !maker_matches(&maker, &make) {
|
||||
continue;
|
||||
|
||||
@@ -265,3 +265,25 @@ fn spec_names_need_an_exact_profile_name() {
|
||||
assert!(aliased.names_exactly(&spec_name([24.0, 70.0, 2.8, 2.8])));
|
||||
assert!(!aliased.names_exactly("24-105mm f/4"));
|
||||
}
|
||||
|
||||
/// Another maker's lens with the same specification scores as high as the aliased one; coming first in the
|
||||
/// database it must not hide the profile named for the specification.
|
||||
#[test]
|
||||
fn a_named_profile_is_found_behind_a_tie() {
|
||||
let lens = |maker: &str, models: &str| {
|
||||
format!(
|
||||
r#"<lens><maker>{maker}</maker>{models}<mount>Test Mount</mount><cropfactor>1</cropfactor>
|
||||
<calibration><distortion model="poly3" focal="18" k1="-0.01" /></calibration></lens>"#
|
||||
)
|
||||
};
|
||||
let xml = format!(
|
||||
r#"<lensdatabase version="2">{}{}</lensdatabase>"#,
|
||||
lens("Otherco", "<model>Otherco 18-55mm f/3.5-5.6</model>"),
|
||||
lens("Testcam", "<model>Testcam 18-55mm f/3.5-5.6 VR</model><model>18-55mm f/3.5-5.6</model>"),
|
||||
);
|
||||
let db = LensDb::parse(&xml).unwrap();
|
||||
let name = spec_name([18.0, 55.0, 3.5, 5.6]);
|
||||
assert_eq!(db.find_lens(None, &name, None).unwrap().maker, "Otherco", "a plain lookup keeps the first of a tie");
|
||||
assert_eq!(db.find_lens_named(None, &name, None).unwrap().maker, "Testcam");
|
||||
assert!(db.find_lens_named(None, "70-200mm f/4", None).is_none());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user