From 7904f28f4ce37f2bc6758a86bf790369c730670c Mon Sep 17 00:00:00 2001 From: metamuffin Date: Wed, 15 Nov 2023 13:31:47 +0100 Subject: a --- tweak/src/main.rs | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 tweak/src/main.rs (limited to 'tweak/src/main.rs') diff --git a/tweak/src/main.rs b/tweak/src/main.rs new file mode 100644 index 0000000..a46d561 --- /dev/null +++ b/tweak/src/main.rs @@ -0,0 +1,138 @@ +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 }) + } + } +} -- cgit v1.2.3-70-g09d2