aboutsummaryrefslogtreecommitdiff
path: root/dhwt-codec
diff options
context:
space:
mode:
Diffstat (limited to 'dhwt-codec')
-rw-r--r--dhwt-codec/.gitignore2
-rw-r--r--dhwt-codec/Cargo.lock350
-rw-r--r--dhwt-codec/Cargo.toml9
-rwxr-xr-xdhwt-codec/run16
-rw-r--r--dhwt-codec/src/bin/decode.rs54
-rw-r--r--dhwt-codec/src/bin/encode.rs54
-rw-r--r--dhwt-codec/src/bin/export.rs42
-rw-r--r--dhwt-codec/src/bin/import.rs51
-rw-r--r--dhwt-codec/src/io.rs71
-rw-r--r--dhwt-codec/src/lib.rs23
-rw-r--r--dhwt-codec/src/transform.rs42
-rw-r--r--dhwt-codec/src/trim.rs36
-rw-r--r--dhwt-codec/src/view.rs42
13 files changed, 792 insertions, 0 deletions
diff --git a/dhwt-codec/.gitignore b/dhwt-codec/.gitignore
new file mode 100644
index 0000000..495c6ed
--- /dev/null
+++ b/dhwt-codec/.gitignore
@@ -0,0 +1,2 @@
+/target
+/a
diff --git a/dhwt-codec/Cargo.lock b/dhwt-codec/Cargo.lock
new file mode 100644
index 0000000..715ba3e
--- /dev/null
+++ b/dhwt-codec/Cargo.lock
@@ -0,0 +1,350 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "bincode"
+version = "2.0.0-rc.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7bb50c5a2ef4b9b1e7ae73e3a73b52ea24b20312d629f9c4df28260b7ad2c3c4"
+dependencies = [
+ "bincode_derive",
+ "serde",
+]
+
+[[package]]
+name = "bincode_derive"
+version = "2.0.0-rc.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a45a23389446d2dd25dc8e73a7a3b3c43522b630cac068927f0649d43d719d2"
+dependencies = [
+ "virtue",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clap"
+version = "4.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2148adefda54e14492fb9bddcc600b4344c5d1a3123bd666dcb939c6f0e0e57e"
+dependencies = [
+ "atty",
+ "bitflags",
+ "clap_derive",
+ "clap_lex",
+ "once_cell",
+ "strsim",
+ "termcolor",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
+dependencies = [
+ "heck",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
+dependencies = [
+ "os_str_bytes",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96bf8df95e795db1a4aca2957ad884a2df35413b24bbeb3114422f3cc21498e8"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "crossbeam-utils",
+ "memoffset",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "422f23e724af1240ec469ea1e834d87a4b59ce2efe2c6a96256b0c47e2fd86aa"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "dhwt-codec"
+version = "0.1.0"
+dependencies = [
+ "bincode",
+ "clap",
+ "rayon",
+]
+
+[[package]]
+name = "either"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
+
+[[package]]
+name = "heck"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.137"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
+
+[[package]]
+name = "memoffset"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
+
+[[package]]
+name = "os_str_bytes"
+version = "6.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b5bf27447411e9ee3ff51186bf7a08e16c341efdde93f4d823e8844429bed7e"
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.47"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rayon"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b"
+dependencies = [
+ "crossbeam-deque",
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "num_cpus",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "serde"
+version = "1.0.147"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
+
+[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
+[[package]]
+name = "syn"
+version = "1.0.103"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "virtue"
+version = "0.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b60dcd6a64dd45abf9bd426970c9843726da7fc08f44cd6fcebf68c21220a63"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/dhwt-codec/Cargo.toml b/dhwt-codec/Cargo.toml
new file mode 100644
index 0000000..080fe20
--- /dev/null
+++ b/dhwt-codec/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "dhwt-codec"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+bincode = "2.0.0-rc.2"
+clap = { version = "4.0.26", features = ["derive"] }
+rayon = "1.6.0"
diff --git a/dhwt-codec/run b/dhwt-codec/run
new file mode 100755
index 0000000..9f7013e
--- /dev/null
+++ b/dhwt-codec/run
@@ -0,0 +1,16 @@
+#!/bin/fish
+
+set f $argv[1]
+set x $argv[2]
+set y $argv[3]
+set z $argv[4]
+
+# cat /dev/urandom | cargo run --release --bin import -- -x $x -y $y -z $z a/inp
+ffmpeg -i $f -frames:v $z -filter_complex [0]scale={$x}x{$y},format=rgb24 -f rawvideo pipe:1 | cargo run --release --bin import -- -x $x -y $y -z $z a/inp
+
+time cargo run --release --bin encode -- -x $x -y $y -z $z a/inp a/enc
+time cargo run --release --bin decode -- -x $x -y $y -z $z a/enc a/out
+
+cargo run --release --bin export -- -x (math $x / 2) -y (math $y / 2) -z (math $z / 2) a/enc | ffmpeg -y -pixel_format rgb24 -f rawvideo -video_size (math $x / 2)x(math $y / 2) -i pipe:0 a/enc.webm
+cargo run --release --bin export -- -x $x -y $y -z $z a/out | ffmpeg -y -pixel_format rgb24 -f rawvideo -video_size {$x}x{$y} -i pipe:0 a/out.webm
+# cargo run --release --bin export -- -x $x -y $y -z $z a/raw_out | ffplay -pixel_format rgb24 -f rawvideo -video_size {$x}x{$y} pipe:0
diff --git a/dhwt-codec/src/bin/decode.rs b/dhwt-codec/src/bin/decode.rs
new file mode 100644
index 0000000..35881fc
--- /dev/null
+++ b/dhwt-codec/src/bin/decode.rs
@@ -0,0 +1,54 @@
+use clap::Parser;
+use dhwt_codec::{
+ io::{empty_videobuf, infile, outfile, read_videobuf_small, write_videobuf, VideoBuf},
+ transform, trim,
+ view::{BufferView, IndexMode},
+ CommonArgs,
+};
+use rayon::prelude::{IntoParallelIterator, ParallelIterator};
+
+fn main() {
+ let args = CommonArgs::parse();
+
+ let mut inf = infile(&args.infile);
+ let mut of = outfile(&args.outfile);
+
+ for c in 0..args.channels {
+ eprintln!("encoding channel #{c}");
+ let a = empty_videobuf(args.x, args.y, args.z);
+ let b = read_videobuf_small(&mut inf);
+
+ eprintln!("\tdecoding Z");
+ (0..args.x).into_par_iter().for_each(|x| {
+ for y in 0..args.y {
+ run_mode(make_mut(&b), make_mut(&a), IndexMode::XY(x, y), args.z)
+ }
+ });
+ eprintln!("\tdecoding Y");
+ (0..args.x).into_par_iter().for_each(|x| {
+ for z in 0..args.z {
+ run_mode(make_mut(&a), make_mut(&b), IndexMode::XZ(x, z), args.y)
+ }
+ });
+ eprintln!("\tdecoding X");
+ (0..args.y).into_par_iter().for_each(|y| {
+ for z in 0..args.z {
+ run_mode(make_mut(&b), make_mut(&a), IndexMode::YZ(y, z), args.x)
+ }
+ });
+ write_videobuf(&mut of, a);
+ }
+}
+
+fn run_mode(a: &mut VideoBuf, b: &mut VideoBuf, mode: IndexMode, size: usize) {
+ trim::untrim(size, &mut BufferView::new(b, mode));
+ transform::decode(
+ size,
+ &mut BufferView::new(a, mode),
+ &mut BufferView::new(b, mode),
+ );
+}
+
+fn make_mut<T>(r: &T) -> &mut T {
+ unsafe { &mut *((r as *const T) as *mut T) }
+}
diff --git a/dhwt-codec/src/bin/encode.rs b/dhwt-codec/src/bin/encode.rs
new file mode 100644
index 0000000..0e711b0
--- /dev/null
+++ b/dhwt-codec/src/bin/encode.rs
@@ -0,0 +1,54 @@
+use clap::Parser;
+use dhwt_codec::{
+ io::{empty_videobuf, infile, outfile, read_videobuf, write_videobuf_small, VideoBuf},
+ transform, trim,
+ view::{BufferView, IndexMode},
+ CommonArgs,
+};
+use rayon::prelude::{IntoParallelIterator, ParallelIterator};
+
+fn main() {
+ let args = CommonArgs::parse();
+
+ let mut inf = infile(&args.infile);
+ let mut of = outfile(&args.outfile);
+
+ for c in 0..args.channels {
+ eprintln!("encoding channel #{c}");
+ let o = empty_videobuf(args.x, args.y, args.z);
+ let i = read_videobuf(&mut inf);
+
+ eprintln!("\tencoding X");
+ (0..args.y).into_par_iter().for_each(|y| {
+ for z in 0..args.z {
+ run_mode(make_mut(&i), make_mut(&o), IndexMode::YZ(y, z), args.x)
+ }
+ });
+ eprintln!("\tencoding Y");
+ (0..args.x).into_par_iter().for_each(|x| {
+ for z in 0..args.z {
+ run_mode(make_mut(&o), make_mut(&i), IndexMode::XZ(x, z), args.y)
+ }
+ });
+ eprintln!("\tencoding Z");
+ (0..args.x).into_par_iter().for_each(|x| {
+ for y in 0..args.y {
+ run_mode(make_mut(&i), make_mut(&o), IndexMode::XY(x, y), args.z)
+ }
+ });
+ write_videobuf_small(&mut of, o);
+ }
+}
+
+fn run_mode(a: &mut VideoBuf, b: &mut VideoBuf, mode: IndexMode, size: usize) {
+ transform::encode(
+ size,
+ &mut BufferView::new(a, mode),
+ &mut BufferView::new(b, mode),
+ );
+ trim::trim(size, &mut BufferView::new(b, mode));
+}
+
+fn make_mut<T>(r: &T) -> &mut T {
+ unsafe { &mut *((r as *const T) as *mut T) }
+}
diff --git a/dhwt-codec/src/bin/export.rs b/dhwt-codec/src/bin/export.rs
new file mode 100644
index 0000000..73f3067
--- /dev/null
+++ b/dhwt-codec/src/bin/export.rs
@@ -0,0 +1,42 @@
+use clap::Parser;
+use dhwt_codec::io::{infile, read_videobuf};
+use std::io::{stdout, BufWriter, Write};
+
+#[derive(Parser)]
+#[clap(about)]
+struct ExportArgs {
+ #[arg(short)]
+ x: usize,
+ #[arg(short)]
+ y: usize,
+ #[arg(short)]
+ z: usize,
+
+ #[arg(short, long, default_value = "3")]
+ channels: usize,
+
+ infile: String,
+}
+
+fn main() {
+ let args = ExportArgs::parse();
+
+ let mut i = infile(&args.infile);
+ let mut writer = BufWriter::new(stdout());
+
+ let mut channels = vec![];
+ for _ in 0..args.channels {
+ channels.push(read_videobuf(&mut i))
+ }
+
+ for z in 0..args.z {
+ for y in 0..args.y {
+ for x in 0..args.x {
+ for c in 0..args.channels {
+ writer.write_all(&[channels[c][x][y][z] as u8]).unwrap();
+ }
+ }
+ }
+ }
+ writer.flush().unwrap();
+}
diff --git a/dhwt-codec/src/bin/import.rs b/dhwt-codec/src/bin/import.rs
new file mode 100644
index 0000000..cd2a35e
--- /dev/null
+++ b/dhwt-codec/src/bin/import.rs
@@ -0,0 +1,51 @@
+use clap::Parser;
+use dhwt_codec::io::{outfile, write_videobuf, Value};
+use std::io::{stdin, Read};
+
+#[derive(Parser)]
+#[clap(about)]
+struct ImportArgs {
+ #[arg(short)]
+ x: usize,
+ #[arg(short)]
+ y: usize,
+ #[arg(short)]
+ z: usize,
+
+ #[arg(short, long, default_value = "3")]
+ channels: usize,
+
+ outfile: String,
+}
+
+fn main() {
+ let args = ImportArgs::parse();
+
+ let mut rawbuf = (0..(args.x * args.y * args.z * args.channels))
+ .map(|_| 0u8)
+ .collect::<Vec<_>>();
+ stdin().read_exact(&mut rawbuf).unwrap();
+
+ let mut o = outfile(&args.outfile);
+
+ for c in 0..args.channels {
+ let mut cols = vec![];
+ for x in 0..args.x {
+ let mut col = vec![];
+ for y in 0..args.y {
+ let mut span = vec![];
+ for z in 0..args.z {
+ span.push(
+ rawbuf[c
+ + (x * args.channels)
+ + (y * args.channels * args.x)
+ + (z * args.channels * args.x * args.y)] as Value,
+ );
+ }
+ col.push(span);
+ }
+ cols.push(col)
+ }
+ write_videobuf(&mut o, cols)
+ }
+}
diff --git a/dhwt-codec/src/io.rs b/dhwt-codec/src/io.rs
new file mode 100644
index 0000000..c60bc79
--- /dev/null
+++ b/dhwt-codec/src/io.rs
@@ -0,0 +1,71 @@
+use bincode::config;
+use std::{
+ fs::File,
+ io::{BufReader, BufWriter, Read, Write},
+};
+
+pub type Value = f32;
+pub type VideoBuf = Vec<Vec<Vec<Value>>>;
+pub const ZERO: Value = 0 as Value;
+pub const TWO: Value = 2 as Value;
+
+pub fn empty_videobuf(x: usize, y: usize, z: usize) -> VideoBuf {
+ (0..x)
+ .map(|_| (0..y).map(|_| (0..z).map(|_| ZERO).collect()).collect())
+ .collect()
+}
+
+pub fn outfile(p: &str) -> impl Write {
+ BufWriter::new(File::create(p).unwrap())
+}
+pub fn infile(p: &str) -> impl Read {
+ BufReader::new(File::open(p).unwrap())
+}
+
+pub fn read_videobuf(f: &mut impl Read) -> VideoBuf {
+ bincode::decode_from_std_read(f, config::standard()).unwrap()
+}
+pub fn write_videobuf(f: &mut impl Write, i: VideoBuf) {
+ bincode::encode_into_std_write(i, f, config::standard()).unwrap();
+}
+
+pub fn write_videobuf_small(f: &mut impl Write, mut i: VideoBuf) {
+ for _ in 0..(i.len() / 2) {
+ i.pop();
+ }
+ for i in &mut i {
+ for _ in 0..(i.len() / 2) {
+ i.pop();
+ }
+ for i in i {
+ for _ in 0..(i.len() / 2) {
+ i.pop();
+ }
+ }
+ }
+ write_videobuf(f, i);
+}
+pub fn read_videobuf_small(f: &mut impl Read) -> VideoBuf {
+ let mut i = read_videobuf(f);
+
+ for i in &mut i {
+ for i in i {
+ for _ in 0..i.len() {
+ i.push(ZERO);
+ }
+ }
+ }
+ for i in &mut i {
+ for _ in 0..i.len() {
+ i.push((0..i[0].len()).map(|_| ZERO).collect());
+ }
+ }
+ for _ in 0..i.len() {
+ i.push(
+ (0..i[0].len())
+ .map(|_| ((0..i[0][0].len()).map(|_| ZERO)).collect())
+ .collect(),
+ );
+ }
+ i
+}
diff --git a/dhwt-codec/src/lib.rs b/dhwt-codec/src/lib.rs
new file mode 100644
index 0000000..69d6b4c
--- /dev/null
+++ b/dhwt-codec/src/lib.rs
@@ -0,0 +1,23 @@
+use clap::Parser;
+
+pub mod io;
+pub mod transform;
+pub mod trim;
+pub mod view;
+
+#[derive(Parser)]
+#[clap(about)]
+pub struct CommonArgs {
+ #[arg(short)]
+ pub x: usize,
+ #[arg(short)]
+ pub y: usize,
+ #[arg(short)]
+ pub z: usize,
+
+ #[arg(short, long, default_value = "3")]
+ pub channels: usize,
+
+ pub infile: String,
+ pub outfile: String,
+}
diff --git a/dhwt-codec/src/transform.rs b/dhwt-codec/src/transform.rs
new file mode 100644
index 0000000..82bccd1
--- /dev/null
+++ b/dhwt-codec/src/transform.rs
@@ -0,0 +1,42 @@
+use crate::io::{Value, TWO};
+use std::ops::{Index, IndexMut};
+
+pub fn encode<X: Index<usize, Output = Value> + IndexMut<usize, Output = Value>>(
+ size: usize,
+ a: &mut X,
+ b: &mut X,
+) {
+ let mut k = size;
+ while k != 1 {
+ k /= 2;
+ for i in 0..k {
+ let x = a[i * 2];
+ let y = a[i * 2 + 1];
+ b[i] = x + y;
+ b[k + i] = x - y;
+ }
+ for i in 0..k {
+ a[i] = b[i]
+ }
+ }
+}
+
+pub fn decode<X: Index<usize, Output = Value> + IndexMut<usize, Output = Value>>(
+ size: usize,
+ a: &mut X,
+ b: &mut X,
+) {
+ let mut k = 1;
+ while k != size {
+ for i in 0..k {
+ let avr = a[i] / TWO;
+ let spread = a[i + k] / TWO;
+ b[i * 2] = avr + spread;
+ b[i * 2 + 1] = avr - spread;
+ }
+ k *= 2;
+ for i in 0..k {
+ a[i] = b[i]
+ }
+ }
+}
diff --git a/dhwt-codec/src/trim.rs b/dhwt-codec/src/trim.rs
new file mode 100644
index 0000000..85a920a
--- /dev/null
+++ b/dhwt-codec/src/trim.rs
@@ -0,0 +1,36 @@
+use crate::io::{Value, TWO, ZERO};
+use std::ops::{Index, IndexMut};
+
+pub fn trim<X: Index<usize, Output = Value> + IndexMut<usize, Output = Value>>(
+ size: usize,
+ a: &mut X,
+) {
+ let half = size / 2;
+ let quarter = size / 4;
+ for i in 0..(size / 2 / 4) {
+ let hi = half + i * 4;
+ let qi = quarter + i * 2;
+ a[qi] = (a[qi + 0] + a[qi + 1]) / TWO;
+ a[qi + 1] = (a[hi + 0] + a[hi + 1] + a[hi + 2] + a[hi + 3]) / (TWO * TWO);
+ }
+ for i in half..size {
+ a[i] = ZERO;
+ }
+}
+
+pub fn untrim<X: Index<usize, Output = Value> + IndexMut<usize, Output = Value>>(
+ size: usize,
+ a: &mut X,
+) {
+ let half = size / 2;
+ let quarter = size / 4;
+ for i in 0..(size / 2 / 4) {
+ let hi = half + i * 4;
+ let qi = quarter + i * 2;
+ a[hi + 0] = a[qi + 1];
+ a[hi + 1] = a[qi + 1];
+ a[hi + 2] = a[qi + 1];
+ a[hi + 3] = a[qi + 1];
+ a[qi + 1] = a[qi];
+ }
+}
diff --git a/dhwt-codec/src/view.rs b/dhwt-codec/src/view.rs
new file mode 100644
index 0000000..0f2ecf7
--- /dev/null
+++ b/dhwt-codec/src/view.rs
@@ -0,0 +1,42 @@
+use std::ops::{Index, IndexMut};
+
+use crate::io::{VideoBuf, Value};
+
+#[derive(Copy, Clone, Debug)]
+pub enum IndexMode {
+ XY(usize, usize),
+ XZ(usize, usize),
+ YZ(usize, usize),
+}
+
+pub struct BufferView<'a> {
+ mode: IndexMode,
+ buf: &'a mut VideoBuf,
+}
+
+impl<'a> BufferView<'a> {
+ pub fn new(buf: &'a mut VideoBuf, mode: IndexMode) -> Self {
+ BufferView { mode, buf }
+ }
+}
+
+impl Index<usize> for BufferView<'_> {
+ type Output = Value;
+
+ fn index(&self, a: usize) -> &Self::Output {
+ match self.mode {
+ IndexMode::XY(x, y) => &self.buf[x][y][a],
+ IndexMode::XZ(x, z) => &self.buf[x][a][z],
+ IndexMode::YZ(y, z) => &self.buf[a][y][z],
+ }
+ }
+}
+impl IndexMut<usize> for BufferView<'_> {
+ fn index_mut(&mut self, a: usize) -> &mut Self::Output {
+ match self.mode {
+ IndexMode::XY(x, y) => &mut self.buf[x][y][a],
+ IndexMode::XZ(x, z) => &mut self.buf[x][a][z],
+ IndexMode::YZ(y, z) => &mut self.buf[a][y][z],
+ }
+ }
+}