aboutsummaryrefslogtreecommitdiff
path: root/evc/src/codec/encode/simple.rs
blob: 2a971af2e0ae24c0f471e5a7623b48fd61970d0d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use crate::{block::Block, frame::Frame, helpers::vector::Vec2, view::View};

use super::EncodeConfig;

pub fn exhaustive(
    view: &View<&Frame>,
    prev: &View<&Frame>,
    _config: &EncodeConfig,
    _max_diff: f64,
) -> (f64, Block) {
    let mut diff = f64::INFINITY;
    let mut translation = Vec2::<isize>::ZERO;
    const OFFSETS: &[isize] = &[-64, -32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32, 64];
    for x in OFFSETS {
        for y in OFFSETS {
            let t = Vec2 { x: *x, y: *y };
            let d = View::diff(&view, &prev.offset(t));
            if d < diff {
                translation = t;
                diff = d;
            }
        }
    }
    (diff, Block::Reference { translation })
}

pub fn fast(
    view: &View<&Frame>,
    prev: &View<&Frame>,
    _config: &EncodeConfig,
    max_diff: f64,
) -> (f64, Block) {
    let mut offset = Vec2::<isize>::ZERO;
    let mut diff = View::diff(&view, &prev);
    if diff < max_diff {
        (diff, Block::REFZERO)
    } else {
        loop {
            let (mut d, mut o) = (diff, offset);
            let mut probe = |test_o: Vec2<isize>| {
                let test_d = View::diff(&prev.clone().offset(test_o), &view);
                if test_d < d {
                    d = test_d;
                    o = test_o;
                }
            };

            probe(offset + Vec2 { x: 8, y: 0 });
            probe(offset + Vec2 { x: -8, y: 0 });
            probe(offset + Vec2 { x: 0, y: 8 });
            probe(offset + Vec2 { x: 0, y: -8 });

            probe(offset + Vec2 { x: 1, y: 0 });
            probe(offset + Vec2 { x: -1, y: 0 });
            probe(offset + Vec2 { x: 0, y: 1 });
            probe(offset + Vec2 { x: 0, y: -1 });

            if d >= diff {
                break (diff, Block::Reference { translation: o });
            }
            diff = d;
            offset = o;
        }
    }
}