Skip to main content

lookup/
lookup.rs

1//! Query a correspondence field at individual points, with no image codecs involved.
2//!
3//! ```sh
4//! cargo run --release --example lookup
5//! ```
6//!
7//! Builds two synthetic photos related by a known shift, maps them, and prints what the
8//! algorithm recovered — a self-contained tour of the API that needs no input files.
9
10use pixelmap::{correspond, Photo};
11
12const WIDTH: usize = 240;
13const HEIGHT: usize = 180;
14const SHIFT: usize = 5;
15
16fn main() -> Result<(), pixelmap::Error> {
17    let (photo1, photo2) = shifted_pair();
18
19    let mapping = correspond(photo1, photo2)?;
20    println!(
21        "mapped {:.1}% of the image in {} comparisons",
22        mapping.coverage() * 100.0,
23        mapping.comparisons()
24    );
25    println!("working scale: {:.3}", mapping.working_scale());
26    println!("\n  point        maps to        (expected)");
27
28    for (x, y) in [(40.0, 40.0), (120.0, 90.0), (200.0, 140.0)] {
29        match mapping.lookup(x, y) {
30            Some((mx, my)) => println!(
31                "  ({x:5.0},{y:5.0}) -> ({mx:6.1},{my:6.1})   ({:6.1},{:6.1})",
32                x - SHIFT as f32,
33                y - SHIFT as f32
34            ),
35            None => println!("  ({x:5.0},{y:5.0}) -> unmapped"),
36        }
37    }
38
39    Ok(())
40}
41
42/// Two windows onto one texture, offset by `SHIFT` in both axes.
43fn shifted_pair() -> (Photo, Photo) {
44    let (bw, bh) = (WIDTH + SHIFT, HEIGHT + SHIFT);
45    let mut state = 0x2545_F491_4F6C_DD1Du64;
46    let mut base = Vec::with_capacity(bw * bh * 4);
47    for y in 0..bh {
48        for x in 0..bw {
49            state ^= state << 13;
50            state ^= state >> 7;
51            state ^= state << 17;
52            let noise = (state >> 56) as f32 / 255.0 * 70.0 - 35.0;
53            let wave = 127.0 + 100.0 * (x as f32 / 9.0).sin() * (y as f32 / 11.0).cos() + noise;
54            let v = wave.clamp(0.0, 255.0) as u8;
55            base.extend_from_slice(&[v, (v / 2).wrapping_add(40), 255 - v, 255]);
56        }
57    }
58
59    let window = |ox: usize, oy: usize| {
60        let mut data = Vec::with_capacity(WIDTH * HEIGHT * 4);
61        for y in 0..HEIGHT {
62            let row = (y + oy) * bw + ox;
63            data.extend_from_slice(&base[row * 4..(row + WIDTH) * 4]);
64        }
65        Photo::from_rgba(WIDTH, HEIGHT, data).expect("buffer matches the dimensions")
66    };
67
68    (window(0, 0), window(SHIFT, SHIFT))
69}