aboutsummaryrefslogtreecommitdiff
path: root/lvc/src/encode.rs
blob: d85ac30c8eb75f47721210c954e94ca2e6b576a6 (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
use crate::diff::diff;
use crate::split::split;
use crate::{Block, Frame, Ref, View};

pub fn encode(last_frame: &Frame, frame: &Frame, view: View) -> Block {
    if view.size().area() > 1024 {
        let [av, bv] = split(view);
        return Block::Split([
            Box::new(encode(last_frame, frame, av)),
            Box::new(encode(last_frame, frame, bv)),
        ]);
    }

    let mut rp = Ref::default();
    let mut d = diff([last_frame, frame], view, rp);

    for _ in 0..500 {
        let (nd, nrp) = optimize_ref(last_frame, frame, view, rp);
        if nd < d {
            rp = nrp;
            d = nd;
        } else {
            break;
        }
    }

    if d < 10000 {
        return Block::Ref(rp);
    } else {
        Block::Lit(frame.export(view))
    }
}

pub fn optimize_ref(last_frame: &Frame, frame: &Frame, view: View, rp: Ref) -> (u32, Ref) {
    [
        rp.apply(|r| r.pos_off.x += 1),
        rp.apply(|r| r.pos_off.x -= 1),
        rp.apply(|r| r.pos_off.y += 1),
        rp.apply(|r| r.pos_off.y -= 1),
        rp.apply(|r| r.color_off.r += 10),
        rp.apply(|r| r.color_off.r -= 10),
        rp.apply(|r| r.color_off.g += 10),
        rp.apply(|r| r.color_off.g -= 10),
        rp.apply(|r| r.color_off.b += 10),
        rp.apply(|r| r.color_off.b -= 10),
    ]
    .map(|p| (diff([last_frame, frame], view, p), p))
    .into_iter()
    .min_by_key(|x| x.0)
    .unwrap()
}