use crate::{debug::draw_debug, huff::read_huff, split::split, Block, Frame, Pixel, View, P2}; use rayon::join; use std::io::{BufReader, BufWriter, Read, Result, Write}; pub fn decode(size: P2, debug: bool, input: impl Read, output: impl Write) -> Result<()> { let mut input = BufReader::new(input); let mut output = BufWriter::new(output); let mut frame = Frame::new(size); let mut last_frame = Frame::new(size); let mut debug_frame = if debug { Some(Frame::new(size)) } else { None }; let huff = true; loop { let b = if huff { let mut buf = vec![]; read_huff(&mut input, &mut buf)?; let mut buf = std::io::Cursor::new(&mut buf); Block::read(&mut buf, View::all(size))? } else { Block::read(&mut input, View::all(size))? }; decode_block(&last_frame, &mut frame, View::all(size), &b); if let Some(debug_frame) = &mut debug_frame { debug_frame.pixels.copy_from_slice(&frame.pixels); draw_debug(debug_frame, View::all(size), &b); Frame::write(&mut output, &debug_frame)?; } else { Frame::write(&mut output, &frame)?; } last_frame.pixels.copy_from_slice(&frame.pixels); // TODO use mem::swap frame.pixels.iter_mut().for_each(|e| *e = Pixel::BLACK); } } pub fn decode_block(last_frame: &Frame, frame: &mut Frame, view: View, block: &Block) { match block { Block::Lit(pxs) => frame.import(view, &pxs), Block::Split(a, b) => { let [av, bv] = split(view); let (frame1, frame2) = unsafe { (&mut *(frame as *mut Frame), &mut *(frame as *mut Frame)) }; join( || decode_block(last_frame, frame1, av, &a), || decode_block(last_frame, frame2, bv, &b), ); } Block::Ref(r) => { for y in view.a.y..view.b.y { for x in view.a.x..view.b.x { let p = P2 { x, y }; frame[p] = last_frame[p + r.pos_off] + r.color_off } } } } }