use std::{ io::{stdin, stdout, Read, Write}, ops::Index, }; const WIDTH: usize = 1920; const HEIGHT: usize = 1080; fn main() { let mut oframe = Frame::new(); loop { let iframe = Frame::read(stdin()); // let diff = oframe.average_area_diff(&iframe, Area::root()); // eprintln!("{diff:?}"); oframe.apply_area_diff(Area::root(), diff); oframe.write(stdout()); // oframe = iframe; } } pub fn decode(f: &mut Frame, area: Area, tree: DiffTree) { oframe.apply_area_diff(Area::root(), diff); } pub enum DiffTree { Split([Box; 2]), Diff(PixelDiff), } pub fn stuff(a: &Frame, b: &Frame, area: Area) -> DiffTree { if area.area() == 1 { DiffTree::Diff(Frame::diff_pixel(a, b, area.x1, area.y1)) } else { let (aa, ba) = area.split(); let (at, bt) = (stuff(a, b, aa), stuff(a, b, ba)); DiffTree::Split([Box::new(at), Box::new(bt)]) } } #[derive(Debug)] pub struct Frame(Vec); #[derive(Debug)] pub struct PixelDiff([i8; 3]); #[derive(Debug, Clone, Copy)] pub struct Area { x1: usize, y1: usize, x2: usize, y2: usize, } impl Frame { pub fn new() -> Self { Self(vec![0u8; WIDTH * HEIGHT * 3]) } pub fn read(mut r: impl Read) -> Self { let mut f = Frame::new(); r.read_exact(&mut f.0).unwrap(); f } pub fn write(&self, mut w: impl Write) { w.write_all(&self.0).unwrap() } pub fn diff_pixel(a: &Frame, b: &Frame, x: usize, y: usize) -> PixelDiff { let o = (x + y * WIDTH) * 3; PixelDiff([ (a.0[o + 0] as i16 - b.0[o + 0] as i16).clamp(i8::MIN as i16, i8::MAX as i16) as i8, (a.0[o + 1] as i16 - b.0[o + 1] as i16).clamp(i8::MIN as i16, i8::MAX as i16) as i8, (a.0[o + 2] as i16 - b.0[o + 2] as i16).clamp(i8::MIN as i16, i8::MAX as i16) as i8, ]) } pub fn apply_area_diff(&mut self, Area { x1, y1, x2, y2 }: Area, p: PixelDiff) { for x in x1..x2 { for y in y1..y2 { let o = (x + y * WIDTH) * 3; self.0[o + 0] = self.0[o + 0].saturating_add_signed(p.0[0]); self.0[o + 1] = self.0[o + 1].saturating_add_signed(p.0[1]); self.0[o + 2] = self.0[o + 2].saturating_add_signed(p.0[2]); } } } pub fn average_area_diff( &self, other: &Frame, area @ Area { x1, y1, x2, y2 }: Area, ) -> PixelDiff { let (mut r, mut g, mut b) = (0i32, 0i32, 0i32); for x in x1..x2 { for y in y1..y2 { let o = (x + y * WIDTH) * 3; r += other.0[o + 0] as i32 - self.0[o + 0] as i32; g += other.0[o + 1] as i32 - self.0[o + 1] as i32; b += other.0[o + 2] as i32 - self.0[o + 2] as i32; } } let a = area.area() as i32; PixelDiff([ (r / a).clamp(i8::MIN as i32, i8::MAX as i32) as i8, (g / a).clamp(i8::MIN as i32, i8::MAX as i32) as i8, (b / a).clamp(i8::MIN as i32, i8::MAX as i32) as i8, ]) } } impl Area { pub fn area(&self) -> usize { self.width() as usize * self.height() as usize } pub fn width(&self) -> usize { self.x2 - self.x1 } pub fn height(&self) -> usize { self.y2 - self.y1 } pub fn root() -> Self { Area { x1: 0, y1: 0, x2: WIDTH, y2: HEIGHT, } } pub fn split(&self) -> (Self, Self) { let Area { x1, y1, x2, y2 } = *self; if self.width() > self.height() { let xm = (self.x1 + self.x2) / 2; (Self { x1, x2: xm, y1, y2 }, Self { x1: xm, x2, y1, y2 }) } else { let ym = (self.y1 + self.y2) / 2; (Self { x1, x2, y1, y2: ym }, Self { x1, x2, y1: ym, y2 }) } } }