aboutsummaryrefslogtreecommitdiff
path: root/old/difftree
diff options
context:
space:
mode:
Diffstat (limited to 'old/difftree')
-rw-r--r--old/difftree/Cargo.lock156
-rw-r--r--old/difftree/Cargo.toml10
-rw-r--r--old/difftree/src/main.rs206
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 })
+ }
+ }
+}