diff options
Diffstat (limited to 'old/difftree')
-rw-r--r-- | old/difftree/Cargo.lock | 156 | ||||
-rw-r--r-- | old/difftree/Cargo.toml | 10 | ||||
-rw-r--r-- | old/difftree/src/main.rs | 206 |
3 files changed, 372 insertions, 0 deletions
diff --git a/old/difftree/Cargo.lock b/old/difftree/Cargo.lock new file mode 100644 index 0000000..6093019 --- /dev/null +++ b/old/difftree/Cargo.lock @@ -0,0 +1,156 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "getrandom" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "tweak" +version = "0.1.0" +dependencies = [ + "rand", + "rayon", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/old/difftree/Cargo.toml b/old/difftree/Cargo.toml new file mode 100644 index 0000000..e6b1ff3 --- /dev/null +++ b/old/difftree/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "difftree" +version = "0.1.0" +edition = "2021" + +[dependencies] +rayon = "1.10.0" +rand = "0.8.5" + +framework = { path = "../framework" } diff --git a/old/difftree/src/main.rs b/old/difftree/src/main.rs new file mode 100644 index 0000000..9b6d35f --- /dev/null +++ b/old/difftree/src/main.rs @@ -0,0 +1,206 @@ +use framework::{ + common::huffman::encode_huff, + vector::{UVec2, Vec2}, + Frame, Framework, Pixel, +}; +use rayon::join; + +fn main() { + let (mut framework, params) = Framework::init(); + let root = Area { + x1: 0, + y1: 0, + x2: params.width, + y2: params.height, + }; + + match params.mode { + framework::CodecMode::Encode => { + let mut oframe = Frame::new(params.width, params.height); + let mut dframe = Frame::new(params.width, params.height); + let mut out = Vec::<u8>::new(); + while let Some(iframe) = framework.next_frame() { + let t = encode(&oframe, &iframe, root); + decode(&mut oframe, root, &t); + write(&mut out, &t); + + if params.debug == 1 { + dframe.pixels.copy_from_slice(&oframe.pixels); + debug(&mut dframe, root, &t); + framework.decode_done(&dframe); + } else if params.debug == 2 { + debug_diff(&mut dframe, root, &t); + framework.decode_done(&dframe); + } else { + framework.decode_done(&oframe) + } + + let huff = encode_huff(&out); + framework.encode_done(&huff); + out.clear(); + } + } + framework::CodecMode::Decode => todo!(), + } +} + +pub fn write(w: &mut Vec<u8>, t: &DiffTree) { + match t { + DiffTree::Split([a, b]) => { + w.push(0); + write(w, a); + write(w, b); + } + DiffTree::Diff(d) => w.extend([1, d.r as u8, d.g as u8, d.b as u8]), + } +} + +pub fn decode(f: &mut Frame, area: Area, tree: &DiffTree) { + match tree { + DiffTree::Split([ta, tb]) => { + let (aa, ab) = area.split(); + decode(f, aa, ta); + decode(f, ab, tb); + } + DiffTree::Diff(diff) => { + apply_area_diff(f, area, *diff); + } + } +} +pub fn debug(f: &mut Frame, area: Area, tree: &DiffTree) { + match tree { + DiffTree::Split([ta, tb]) => { + let (aa, ab) = area.split(); + debug(f, aa, ta); + debug(f, ab, tb); + } + DiffTree::Diff(_diff) => { + let Area { x1, y1, x2, y2 } = area; + for x in x1..x2 { + for y in y1..y2 { + f[(x, y)] = Pixel { r: 0, g: 0, b: 255 } + } + } + } + } +} +pub fn debug_diff(f: &mut Frame, area: Area, tree: &DiffTree) { + match tree { + DiffTree::Split([ta, tb]) => { + let (aa, ab) = area.split(); + debug_diff(f, aa, ta); + debug_diff(f, ab, tb); + } + DiffTree::Diff(diff) => { + let Area { x1, y1, x2, y2 } = area; + for x in x1..x2 { + for y in y1..y2 { + f[(x, y)] = Pixel { + r: 127u8.saturating_add_signed(diff.r), + b: 127u8.saturating_add_signed(diff.b), + g: 127u8.saturating_add_signed(diff.g), + } + } + } + } + } +} + +pub fn encode(a: &Frame, b: &Frame, area: Area) -> DiffTree { + if area.area() == 1 { + DiffTree::Diff(diff_pixel( + a, + b, + Vec2 { + x: area.x1, + y: area.y1, + }, + )) + } else { + let (aa, ba) = area.split(); + let (at, bt) = join(|| encode(a, b, aa), || encode(a, b, ba)); + // let (at, bt) = (encode(a, b, aa), encode(a, b, ba)); + + match (&at, &bt) { + (DiffTree::Diff(ad), DiffTree::Diff(bd)) => { + let d_r = ad.r.abs_diff(bd.r); + let d_g = ad.g.abs_diff(bd.g); + let d_b = ad.b.abs_diff(bd.b); + + let visdiff = (d_r as usize + d_g as usize + d_b as usize) * aa.area(); + if visdiff < 100 { + return DiffTree::Diff(Pixel { + r: ((ad.r as i16 + bd.r as i16) / 2) as i8, + g: ((ad.g as i16 + bd.g as i16) / 2) as i8, + b: ((ad.b as i16 + bd.b as i16) / 2) as i8, + }); + } + } + _ => (), + } + DiffTree::Split([Box::new(at), Box::new(bt)]) + } +} + +pub enum DiffTree { + Split([Box<DiffTree>; 2]), + Diff(Pixel<i8>), +} + +#[derive(Debug, Clone, Copy)] +pub struct Area { + x1: usize, + y1: usize, + x2: usize, + y2: usize, +} + +#[inline] +fn diff_clamp(x: u8, y: u8) -> i8 { + if y >= x { + (y - x).min(127) as i8 + } else { + -((x - y).min(128) as i8) + } +} +pub fn diff_pixel(a: &Frame, b: &Frame, p: UVec2) -> Pixel<i8> { + let (ap, bp) = (a[p], b[p]); + Pixel { + r: diff_clamp(ap.r, bp.r), + g: diff_clamp(ap.g, bp.g), + b: diff_clamp(ap.b, bp.b), + } +} + +pub fn apply_area_diff(frame: &mut Frame, Area { x1, y1, x2, y2 }: Area, diff: Pixel<i8>) { + for x in x1..x2 { + for y in y1..y2 { + let p = &mut frame[(x, y)]; + p.r = p.r.saturating_add_signed(diff.r); + p.g = p.g.saturating_add_signed(diff.g); + p.b = p.b.saturating_add_signed(diff.b); + } + } +} + +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 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 }) + } + } +} |