use anyhow::Context; use clap::Parser; use evc::{ block::{Block, BlockInner}, frame::Frame, header::Header, ser::Sink, view::View, }; use std::io::{BufReader, BufWriter}; #[derive(Parser)] #[clap(about, version)] pub struct EncodeArgs { #[arg(short = 'W', long)] width: usize, #[arg(short = 'H', long)] height: usize, } fn main() -> anyhow::Result<()> { let args = EncodeArgs::parse(); let mut input = BufReader::new(std::io::stdin()); let mut output = BufWriter::new(std::io::stdout()); let size = (args.width, args.height); output .put(Header { resolution: size, frame_count: 0, }) .context("writing header")?; let mut prev_frame = Frame::new(size); for i in 0.. { eprintln!("encode frame {i}"); let frame = Frame::read(&mut input, size) .context("reading raw frame") .unwrap(); let v1 = frame.view((0, 0), size); let v2 = prev_frame.view((0, 0), size); let root = encode_block(v1, v2); root.write(&mut output).context("writing encoded frame")?; prev_frame = frame; } Ok(()) } fn encode_block(view: View<&Frame>, prev: View<&Frame>) -> Block { let diff = View::diff(&view, &prev) / view.area() as f64; // eprintln!("{:?} {diff}", view.size); let inner = if diff < 0.9 { BlockInner::Reference { translation: (0, 0), } } else { if view.size.0 < 32 { BlockInner::Literal(view.pixels()) } else { let [av, bv] = view.split(); let [ap, bp] = prev.split(); let a = encode_block(av, ap); let b = encode_block(bv, bp); if a.is_literal() && b.is_literal() { BlockInner::Literal(view.pixels()) } else { BlockInner::Split(Box::new([a, b])) } } }; Block { size: view.size, inner, } }