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() }