use crate::{block::Block, frame::Frame, vec2::Vec2, view::View}; #[derive(Debug, Clone)] pub struct EncodeConfig { pub translate: bool, pub ref_thres: f64, } pub fn encode_block(view: View<&Frame>, prev: View<&Frame>, config: &EncodeConfig) -> Block { let (diff, translation) = if view.area() > 10_000 { (f64::INFINITY, Vec2::ZERO) } else if config.translate { let mut best_diff = f64::INFINITY; let mut best_translation = Vec2::ZERO; for x in [-32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32] { for y in [-32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32] { let diff = View::diff(&view, &prev) / view.area() as f64; if diff < best_diff { best_translation = Vec2 { x, y }; best_diff = diff; } } } (best_diff, best_translation) } else { (View::diff(&view, &prev) / view.area() as f64, Vec2::ZERO) }; if diff < config.ref_thres { Block::Reference { translation } } else { if view.size.x < 16 { Block::Literal(view.pixels()) } else { let [av, bv] = view.split(); let [ap, bp] = prev.split(); let a = encode_block(av, ap, config); let b = encode_block(bv, bp, config); if a.is_literal() && b.is_literal() { Block::Literal(view.pixels()) } else { Block::Split(Box::new([a, b])) } } } }