mirror of
https://github.com/storytold/lightcraft.git
synced 2026-11-13 17:31:09 -06:00
Merge remote-tracking branch 'origin/main' into pr-2676
This commit is contained in:
@@ -328,7 +328,9 @@ fn maker_matches(a: &[String], b: &[String]) -> bool {
|
||||
}
|
||||
|
||||
/// How well a database name matches the EXIF name, 0..1. Every number in the database name (focal lengths,
|
||||
/// apertures) must appear in the EXIF name; the maker's words are ignored on both sides (EXIF often omits them).
|
||||
/// apertures) must appear in the EXIF name and vice versa; the maker's words are ignored on both sides (EXIF
|
||||
/// often omits them). Extra EXIF words only lower the score; they name a different lens only when they mark
|
||||
/// a teleconverter, a different optical system than the bare lens.
|
||||
fn name_score(db: &[String], exif: &[String], maker: &[String]) -> f64 {
|
||||
let db: Vec<&String> = db.iter().filter(|t| !maker.contains(t)).collect();
|
||||
let exif: Vec<&String> = exif.iter().filter(|t| !maker.contains(t)).collect();
|
||||
@@ -338,10 +340,27 @@ fn name_score(db: &[String], exif: &[String], maker: &[String]) -> f64 {
|
||||
if db.iter().any(|t| is_number(t) && !exif.contains(t)) || exif.iter().any(|t| is_number(t) && !db.contains(t)) {
|
||||
return 0.0;
|
||||
}
|
||||
// A teleconverter combo is a different optical system from the bare lens:
|
||||
// reject it whichever side carries the marker, independent of which tokens
|
||||
// the names drop or add.
|
||||
let db_tc = db.iter().any(|t| is_teleconverter_marker(t.as_str()));
|
||||
let exif_tc = exif.iter().any(|t| is_teleconverter_marker(t.as_str()));
|
||||
if db_tc != exif_tc {
|
||||
return 0.0;
|
||||
}
|
||||
let common = db.iter().filter(|t| exif.contains(t)).count() as f64;
|
||||
common / db.len().max(exif.len()) as f64
|
||||
}
|
||||
|
||||
/// Teleconverter markers in a lens name. A name carrying one names a different
|
||||
/// optical system than the bare lens, so a match whose sides disagree on the
|
||||
/// marker is rejected before scoring. Converter factors such as `1.4x`
|
||||
/// tokenise into a number the base profile lacks, so the numeric check above
|
||||
/// already rejects them.
|
||||
fn is_teleconverter_marker(t: &str) -> bool {
|
||||
t == "tc" || t == "teleconverter"
|
||||
}
|
||||
|
||||
fn camera(n: &xml::Node) -> Option<Camera> {
|
||||
Some(Camera {
|
||||
maker: n.kid_text("maker")?.to_string(),
|
||||
|
||||
@@ -543,3 +543,32 @@ fn hostile_numbers_give_finite_corrections_or_none() {
|
||||
assert!(db.find_camera("", "").is_none());
|
||||
assert!(db.find_lens(None, " ", None).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn teleconverter_combo_does_not_inherit_base_profile() {
|
||||
// The database has only the bare 400 mm profile. A teleconverter combo is a
|
||||
// different optical system, so find_lens must not return the base profile --
|
||||
// not even when the converter is a digit-free suffix such as "Z TC".
|
||||
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
|
||||
<lensdatabase version="2">
|
||||
<lens>
|
||||
<maker>Nikon</maker>
|
||||
<model>NIKKOR Z 400mm f/4.5 VR S</model>
|
||||
<mount>Z</mount>
|
||||
<calibration>
|
||||
<distortion model="poly3" focal="400" k1="0.001" />
|
||||
</calibration>
|
||||
</lens>
|
||||
</lensdatabase>"#;
|
||||
let db = LensDb::parse(xml).unwrap();
|
||||
assert!(db.find_lens(Some("Nikon"), "NIKKOR Z 400mm f/4.5 VR S", None).is_some(), "the base profile matches its own name");
|
||||
// A digit-free teleconverter suffix must not inherit the 400 mm profile:
|
||||
// name_score finds every base-profile number token present and would score 0.78.
|
||||
assert!(db.find_lens(Some("Nikon"), "NIKKOR Z 400mm f/4.5 VR S Z TC", None).is_none(), "teleconverter combos do not inherit the base profile");
|
||||
// A converter factor ("1.4") is a numeric token the base profile lacks, so the
|
||||
// combo matches nothing either.
|
||||
assert!(
|
||||
db.find_lens(Some("Nikon"), "NIKKOR Z 400mm f/4.5 VR S Z TC-1.4x", None).is_none(),
|
||||
"teleconverter combos do not inherit the base profile",
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user