aboutsummaryrefslogtreecommitdiff
path: root/evc/src
diff options
context:
space:
mode:
Diffstat (limited to 'evc/src')
-rw-r--r--evc/src/bin/decode.rs63
-rw-r--r--evc/src/bin/encode.rs111
-rw-r--r--evc/src/bin/info.rs10
-rw-r--r--evc/src/block.rs123
-rw-r--r--evc/src/codec/compress.rs155
-rw-r--r--evc/src/codec/decode.rs34
-rw-r--r--evc/src/codec/encode/advanced.rs115
-rw-r--r--evc/src/codec/encode/mod.rs112
-rw-r--r--evc/src/codec/encode/simple.rs65
-rw-r--r--evc/src/codec/mod.rs3
-rw-r--r--evc/src/debug.rs103
-rw-r--r--evc/src/format/header.rs29
-rw-r--r--evc/src/format/mod.rs2
-rw-r--r--evc/src/format/ser.rs335
-rw-r--r--evc/src/frame.rs109
-rw-r--r--evc/src/helpers/matrix.rs33
-rw-r--r--evc/src/helpers/mod.rs4
-rw-r--r--evc/src/helpers/pixel.rs81
-rw-r--r--evc/src/helpers/threading.rs26
-rw-r--r--evc/src/helpers/vector.rs126
-rw-r--r--evc/src/lib.rs13
-rw-r--r--evc/src/refsampler.rs51
-rw-r--r--evc/src/view.rs241
23 files changed, 0 insertions, 1944 deletions
diff --git a/evc/src/bin/decode.rs b/evc/src/bin/decode.rs
deleted file mode 100644
index fbf5624..0000000
--- a/evc/src/bin/decode.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-#![feature(box_patterns)]
-use anyhow::Context;
-use clap::Parser;
-use indicatif::ProgressBar;
-use libreschmux::{
- block::Block,
- codec::decode::{decode_block, DecodeConfig},
- debug::draw_debug,
- format::{header::Header, ser::Source},
- frame::Frame,
-};
-use log::{info, warn};
-use std::io::{BufReader, BufWriter};
-
-#[derive(Parser)]
-#[clap(about, version)]
-pub struct DecodeArgs {
- #[arg(long)]
- debug: bool,
-}
-
-fn main() -> anyhow::Result<()> {
- env_logger::init_from_env("LOG");
- let args = DecodeArgs::parse();
-
- let mut input = BufReader::new(std::io::stdin());
- let mut output = BufWriter::new(std::io::stdout());
-
- let header = input.get::<Header>().context("reading header")?;
- info!("{header:?}");
- if header.resolution.x * header.resolution.y > 100_000_000 {
- warn!("resolution is quite big. video is likely corrupt.");
- }
- let size = header.resolution;
-
- let config = DecodeConfig {};
-
- let progress_bar = ProgressBar::new(header.frame_count as u64);
-
- let mut prev = Frame::new(size);
- for i in 0..header.frame_count {
- info!("decode frame {i}");
-
- let block = Block::read(&mut input, size).context("reading encoded frame")?;
- let mut frame = Frame::new(size);
-
- decode_block(&block, frame.view_mut(), prev.view(), &config);
-
- progress_bar.inc(1);
-
- if args.debug {
- let mut f2 = frame.clone();
- draw_debug(&block, f2.view_mut());
- f2.write(&mut output).context("writing raw frame")?;
- } else {
- frame.write(&mut output).context("writing raw frame")?;
- }
-
- prev = frame;
- }
- drop(input);
- Ok(())
-}
diff --git a/evc/src/bin/encode.rs b/evc/src/bin/encode.rs
deleted file mode 100644
index 43f2c57..0000000
--- a/evc/src/bin/encode.rs
+++ /dev/null
@@ -1,111 +0,0 @@
-use anyhow::Context;
-use clap::Parser;
-use indicatif::ProgressBar;
-use libreschmux::{
- codec::{
- decode::{decode_block, DecodeConfig},
- encode::{encode_block, EncodeConfig, EncodeMode},
- },
- format::{header::Header, ser::Sink},
- frame::Frame,
- helpers::vector::Vec2,
-};
-use log::info;
-use std::io::{BufReader, BufWriter};
-
-#[derive(Parser)]
-#[clap(about, version)]
-pub struct EncodeArgs {
- #[arg(short = 'W', long)]
- width: usize,
- #[arg(short = 'H', long)]
- height: usize,
-
- #[arg(short, long)]
- mode: EncodeMode,
-
- #[arg(long)]
- no_linear_transform: bool,
- #[arg(long)]
- no_value_scale: bool,
- #[arg(long)]
- no_translate: bool,
-
- #[arg[short = 'L', long]]
- length: Option<usize>,
-
- #[arg(short, long, default_value = "8")]
- min_block_size: isize,
-
- #[arg(short = 't', long, default_value = "200")]
- ref_thres: f64,
-}
-
-fn main() -> anyhow::Result<()> {
- env_logger::init_from_env("LOG");
- let args = EncodeArgs::parse();
-
- let mut input = BufReader::new(std::io::stdin());
- let mut output = BufWriter::new(std::io::stdout());
-
- let config = EncodeConfig {
- mode: args.mode,
- ref_thres: args.ref_thres,
- weight_factor: 50.0,
- max_diff_area: 10_000,
- min_block_size: args.min_block_size,
- do_translate: !args.no_translate,
- do_linear_transform: !args.no_linear_transform,
- do_value_scale: !args.no_value_scale,
- };
-
- let size = Vec2 {
- x: args.width as isize,
- y: args.height as isize,
- };
- output
- .put(Header {
- resolution: size,
- frame_count: args.length.unwrap_or(usize::MAX),
- })
- .context("writing header")?;
-
- let progress_bar = args.length.map(|len| ProgressBar::new(len as u64));
- let mut prev_frame = Frame::new(size);
-
- for i in 0.. {
- info!("encode frame {i}");
- let mut frame = Frame::read(&mut input, size).context("reading raw frame")?;
-
- let v1 = frame.view();
- let v2 = prev_frame.view();
-
- let (error, root) = encode_block(v1, v2, &config);
-
- // compress_block(
- // &mut root,
- // Vec2 {
- // x: size.x as usize,
- // y: size.y as usize,
- // },
- // );
-
- root.write(&mut output, size)
- .context("writing encoded frame")?;
-
- info!(
- "cumulative error: {error} ({} per pixel)",
- error / frame.view().area() as f64
- );
-
- if let Some(progress_bar) = &progress_bar {
- progress_bar.inc(1);
- }
-
- decode_block(&root, frame.view_mut(), prev_frame.view(), &DecodeConfig {});
-
- prev_frame = frame;
- }
-
- Ok(())
-}
diff --git a/evc/src/bin/info.rs b/evc/src/bin/info.rs
deleted file mode 100644
index ebd8442..0000000
--- a/evc/src/bin/info.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-use anyhow::Context;
-use libreschmux::format::{header::Header, ser::Source};
-use std::io::BufReader;
-
-fn main() {
- env_logger::init_from_env("LOG");
- let mut input = BufReader::new(std::io::stdin());
- let header = input.get::<Header>().context("reading header").unwrap();
- eprintln!("{header:#?}")
-}
diff --git a/evc/src/block.rs b/evc/src/block.rs
deleted file mode 100644
index d0f940b..0000000
--- a/evc/src/block.rs
+++ /dev/null
@@ -1,123 +0,0 @@
-use crate::{
- format::ser::{ConstSizeSerExt, Ser, Sink, Small, Source},
- helpers::vector::Vec2,
- helpers::{matrix::Mat2, pixel::Pixel},
-};
-use anyhow::bail;
-
-#[derive(Clone, Debug, PartialEq)]
-pub enum Block {
- Literal(Vec<Pixel>),
- CompressedLiteral(Vec<u8>),
- Split(Box<[Block; 2]>),
- Reference { translation: Vec2<isize> },
- AdvancedReference(AdvancedReference),
-}
-
-#[derive(Clone, Debug, PartialEq)]
-pub struct AdvancedReference {
- pub translation: Vec2<i8>,
- pub transform: Mat2<i8>,
- pub value_scale: i8,
-}
-
-impl Block {
- pub const REFZERO: Block = Block::Reference {
- translation: Vec2::<isize>::ZERO,
- };
-
- pub fn write(&self, sink: &mut impl std::io::Write, size: Vec2<isize>) -> anyhow::Result<()> {
- match &self {
- Block::Literal(pixels) => {
- sink.put(0u8)?;
- pixels.write_const_size(sink, size.area() as usize)?;
- }
- Block::CompressedLiteral(data) => {
- sink.put(1u8)?;
- data.write(sink)?;
- }
- Block::Split(box [a, b]) => {
- sink.put(2u8)?;
- let [asize, bsize] = split_size(size);
- a.write(sink, asize)?;
- b.write(sink, bsize)?;
- }
- Block::Reference { translation } => {
- sink.put(3u8)?;
- sink.put(Small(*translation))?;
- }
- Block::AdvancedReference(AdvancedReference {
- translation,
- transform,
- value_scale,
- }) => {
- sink.put(4u8)?;
- sink.put((*translation, *transform, *value_scale))?;
- }
- }
- Ok(())
- }
-
- pub fn read(source: &mut impl std::io::Read, size: Vec2<isize>) -> anyhow::Result<Self> {
- let variant = source.get::<u8>()?;
- Ok(match variant {
- 0 => Block::Literal(Vec::read_const_size(source, size.area() as usize)?),
- 1 => Block::CompressedLiteral(Vec::read(source)?),
- 2 => Block::Split(Box::new({
- let [asize, bsize] = split_size(size);
- let a = Block::read(source, asize)?;
- let b = Block::read(source, bsize)?;
- [a, b]
- })),
- 3 => Block::Reference {
- translation: source.get::<Small<Vec2<isize>>>()?.0,
- },
- 4 => Block::AdvancedReference(AdvancedReference {
- translation: source.get()?,
- transform: source.get()?,
- value_scale: source.get()?,
- }),
- x => bail!("corrupt block type ({})", x),
- })
- }
-}
-
-pub fn split_size(size: Vec2<isize>) -> [Vec2<isize>; 2] {
- let vert = size.x > size.y;
- [
- if vert {
- (size.x / 2, size.y).into()
- } else {
- (size.x, size.y / 2).into()
- },
- if vert {
- (size.x - size.x / 2, size.y).into()
- } else {
- (size.x, size.y - size.y / 2).into()
- },
- ]
-}
-
-impl Block {
- pub fn is_literal(&self) -> bool {
- matches!(self, Block::Literal(..))
- }
- pub fn identical_ref(a: &Self, b: &Self) -> bool {
- matches!(a, Block::Reference { .. }) && a == b
- }
-}
-
-impl Default for AdvancedReference {
- fn default() -> Self {
- Self {
- translation: Vec2 { x: 0, y: 0 },
- transform: Mat2 {
- a: 4,
- b: 0,
- c: 0,
- d: 4,
- },
- value_scale: 0,
- }
- }
-}
diff --git a/evc/src/codec/compress.rs b/evc/src/codec/compress.rs
deleted file mode 100644
index 09d1f29..0000000
--- a/evc/src/codec/compress.rs
+++ /dev/null
@@ -1,155 +0,0 @@
-use crate::{
- block::Block,
- frame::Frame,
- helpers::{pixel::Pixel, vector::Vec2},
- view::View,
-};
-use rustdct::DctPlanner;
-
-pub fn compress_block(block: &mut Block, size: Vec2<usize>) {
- match block {
- Block::Literal(p) => {
- let comp = lit_compress(size.x, size.y, &p);
- *block = Block::CompressedLiteral(comp)
- }
- Block::Split(box [a, b]) => {
- let vert = size.x > size.y;
- compress_block(
- a,
- if vert {
- Vec2 {
- x: size.x / 2,
- y: size.y,
- }
- } else {
- Vec2 {
- x: size.x,
- y: size.y / 2,
- }
- },
- );
- compress_block(
- b,
- if vert {
- Vec2 {
- x: size.x - size.x / 2,
- y: size.y,
- }
- } else {
- Vec2 {
- x: size.x,
- y: size.y - size.y / 2,
- }
- },
- );
- }
- _ => (),
- }
-}
-
-pub fn lit_compress(w: usize, h: usize, pixels: &[Pixel]) -> Vec<u8> {
- let mut out = vec![];
- for ci in 0..3 {
- let mut ch = vec![0.; w * h];
- for y in 0..h {
- for x in 0..w {
- let p = pixels[x + y * w];
- ch[x + y * w] = match ci {
- 0 => p.r,
- 1 => p.g,
- 2 => p.b,
- _ => unreachable!(),
- } as f32
- }
- }
-
- norm_dct_channel(w, h, &mut ch);
- for i in 0..w * h {
- out.extend(unsafe { std::mem::transmute::<_, [u8; 4]>(ch[i]) });
- }
- }
- out
-}
-
-pub fn lit_decompress(compressed: &[u8], mut target: View<&mut Frame>) {
- let (w, h) = (target.size.x as usize, target.size.y as usize);
- for ci in 0..3 {
- let mut ch = compressed[ci * w * h..(ci + 1) * w * h]
- .chunks_exact(4)
- .map(|v| unsafe {
- std::mem::transmute::<_, f32>(TryInto::<[u8; 4]>::try_into(v).unwrap())
- })
- .collect::<Vec<_>>();
- norm_idct_channel(w, h, &mut ch);
- for y in 0..h {
- for x in 0..w {
- let p = &mut target[Vec2 {
- x: x as isize,
- y: y as isize,
- }];
- *(match ci {
- 0 => &mut p.r,
- 1 => &mut p.g,
- 2 => &mut p.b,
- _ => unreachable!(),
- }) = ch[x + y * w] as u8
- }
- }
- }
-}
-
-fn norm_dct_channel(w: usize, h: usize, values: &mut [f32]) {
- let d = DctPlanner::new().plan_dct2(w);
- let mut temp = vec![0.; d.get_scratch_len()];
- for c in values.chunks_exact_mut(w) {
- d.process_dct2_with_scratch(c, &mut temp)
- }
-
- let mut values_trans = transpose(w, h, values);
- let d = DctPlanner::new().plan_dct2(h);
- let mut temp = vec![0.; d.get_scratch_len()];
- for c in values_trans.chunks_exact_mut(h) {
- d.process_dct2_with_scratch(c, &mut temp)
- }
-
- let scale = 2. / (w as f32 * h as f32).sqrt();
- for (i, v) in values_trans.iter().enumerate() {
- values[i] = *v * scale * 127.0
- }
-}
-
-fn norm_idct_channel(h: usize, w: usize, values: &mut [f32]) {
- let scale = 2. / (w as f32 * h as f32).sqrt();
- for v in values.iter_mut() {
- *v /= scale * 127.0
- }
-
- let d = DctPlanner::new().plan_dct2(w);
- let mut temp = vec![0.; d.get_scratch_len()];
- for c in values.chunks_exact_mut(w) {
- d.process_dct3_with_scratch(c, &mut temp)
- }
-
- let mut values_trans = transpose(w, h, values);
- let d = DctPlanner::new().plan_dct2(h);
- let mut temp = vec![0.; d.get_scratch_len()];
- for c in values_trans.chunks_exact_mut(h) {
- d.process_dct3_with_scratch(c, &mut temp)
- }
- values.copy_from_slice(&values_trans)
-}
-
-fn transpose(w: usize, h: usize, values: &[f32]) -> Vec<f32> {
- let mut io = 0;
- let mut it;
- let mut transposed = vec![0.; values.len()];
- for row in 0..h {
- it = row;
- for _ in 0..w {
- transposed[it] = values[io];
- io += 1;
- it += h;
- }
- }
- transposed
-}
diff --git a/evc/src/codec/decode.rs b/evc/src/codec/decode.rs
deleted file mode 100644
index c042278..0000000
--- a/evc/src/codec/decode.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-use super::compress::lit_decompress;
-use crate::{block::Block, frame::Frame, refsampler::Sampler, view::View};
-
-pub struct DecodeConfig {}
-
-pub fn decode_block(
- block: &Block,
- mut target: View<&mut Frame>,
- prev: View<&Frame>,
- config: &DecodeConfig,
-) {
- match &block {
- Block::Literal(pixels) => target.set_pixels(pixels),
- Block::Split(box [a, b]) => {
- let [a, b] = unsafe { std::mem::transmute::<_, [&'static Block; 2]>([a, b]) };
- let [at, bt] = unsafe {
- std::mem::transmute::<_, [View<&'static mut Frame>; 2]>(target.split_mut_unsafe())
- };
- let [ap, bp] =
- unsafe { std::mem::transmute::<_, [View<&'static Frame>; 2]>(prev.split()) };
- let config = unsafe { std::mem::transmute::<_, &'static DecodeConfig>(config) };
-
- rayon::join(
- move || decode_block(a, at, ap, config),
- move || decode_block(b, bt, bp, config),
- );
- }
- Block::CompressedLiteral(data) => {
- lit_decompress(&data, target);
- }
- Block::Reference { translation } => target.copy_from(&prev.offset(*translation)),
- Block::AdvancedReference(r) => target.copy_from_sampler(&Sampler::from_refblock(prev, r)),
- }
-}
diff --git a/evc/src/codec/encode/advanced.rs b/evc/src/codec/encode/advanced.rs
deleted file mode 100644
index 0e45176..0000000
--- a/evc/src/codec/encode/advanced.rs
+++ /dev/null
@@ -1,115 +0,0 @@
-use super::EncodeConfig;
-use crate::{
- block::{AdvancedReference, Block},
- frame::Frame,
- refsampler::Sampler,
- view::View,
-};
-
-pub fn default(
- view: &View<&Frame>,
- prev: &View<&Frame>,
- config: &EncodeConfig,
- max_diff: f64,
-) -> (f64, Block) {
- let mut pm = AdvancedReference::default();
- let sampler = Sampler::from_refblock(prev.clone(), &pm);
- let mut diff = View::diff_sampler(&view, &sampler);
- if diff < max_diff {
- (diff, Block::REFZERO)
- } else {
- loop {
- let (mut d, mut p) = (diff, pm.clone());
-
- if config.do_translate {
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x += 4);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x -= 4);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y += 4);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y -= 4);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x += 2);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x -= 2);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y += 2);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y -= 2);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x += 1);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x -= 1);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y += 1);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y -= 1);
- }
- if config.do_value_scale {
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.value_scale += 1);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.value_scale -= 1);
- }
- if config.do_linear_transform {
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.transform.a -= 1);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.transform.a += 1);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.transform.b -= 1);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.transform.b += 1);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.transform.c -= 1);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.transform.c += 1);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.transform.d -= 1);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.transform.d += 1);
- }
-
- if d >= diff {
- break (diff, Block::AdvancedReference(pm));
- }
-
- diff = d;
- pm = p;
- }
- }
-}
-
-pub fn partial(
- view: &View<&Frame>,
- prev: &View<&Frame>,
- _config: &EncodeConfig,
- max_diff: f64,
-) -> (f64, Block) {
- let mut pm = AdvancedReference::default();
- let sampler = Sampler::from_refblock(prev.clone(), &pm);
- let mut diff = View::diff_sampler(&view, &sampler);
- if diff < max_diff {
- (diff, Block::REFZERO)
- } else {
- loop {
- let (mut d, mut p) = (diff, pm.clone());
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x += 2);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x -= 2);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y += 2);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y -= 2);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x += 1);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x -= 1);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y += 1);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y -= 1);
-
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.value_scale += 1);
- pk(&view, &prev, &mut d, &mut p, &pm, |p| p.value_scale -= 1);
-
- if d >= diff {
- break (diff, Block::AdvancedReference(pm));
- }
- diff = d;
- pm = p;
- }
- }
-}
-
-#[inline]
-fn pk<F: FnMut(&mut AdvancedReference) -> ()>(
- view: &View<&Frame>,
- prev: &View<&Frame>,
- diff: &mut f64,
- params: &mut AdvancedReference,
- initial_params: &AdvancedReference,
- mut f: F,
-) {
- let mut p = initial_params.clone();
- f(&mut p);
- let sampler = Sampler::from_refblock(prev.clone(), &p);
- let d = View::diff_sampler(view, &sampler);
- if d < *diff {
- *diff = d;
- *params = p;
- }
-}
diff --git a/evc/src/codec/encode/mod.rs b/evc/src/codec/encode/mod.rs
deleted file mode 100644
index 30342f0..0000000
--- a/evc/src/codec/encode/mod.rs
+++ /dev/null
@@ -1,112 +0,0 @@
-pub mod advanced;
-pub mod simple;
-
-use crate::{
- block::Block,
- frame::Frame,
- helpers::{pixel::Pixel, vector::Vec2},
- view::View,
-};
-use clap::ValueEnum;
-
-#[derive(Debug, Clone)]
-pub struct EncodeConfig {
- pub mode: EncodeMode,
- pub ref_thres: f64,
- pub max_diff_area: isize,
- pub min_block_size: isize,
- pub weight_factor: f64,
-
- pub do_translate: bool,
- pub do_value_scale: bool,
- pub do_linear_transform: bool,
-}
-
-#[derive(Debug, Clone, ValueEnum)]
-pub enum EncodeMode {
- Trivial,
- SimpleFast,
- SimpleExhaustive,
- Advanced,
- AdvancedPartial,
-}
-
-pub fn encode_block(view: View<&Frame>, prev: View<&Frame>, config: &EncodeConfig) -> (f64, Block) {
- let (diff, refblock) = if view.area() > config.max_diff_area {
- (
- f64::INFINITY,
- Block::Reference {
- translation: Vec2::<isize>::ZERO,
- },
- )
- } else {
- let weight = importance(&view).max(0.5);
- let irrelevance = config.weight_factor / weight;
- let max_diff = config.ref_thres - irrelevance;
- let (diff, refblock) = match config.mode {
- EncodeMode::Trivial => (
- View::diff(&view, &prev),
- Block::Reference {
- translation: Vec2::<isize>::ZERO,
- },
- ),
- EncodeMode::SimpleExhaustive => simple::exhaustive(&view, &prev, config, max_diff),
- EncodeMode::SimpleFast => simple::fast(&view, &prev, config, max_diff),
- EncodeMode::Advanced => advanced::default(&view, &prev, config, max_diff),
- EncodeMode::AdvancedPartial => advanced::partial(&view, &prev, config, max_diff),
- };
- (diff - irrelevance, refblock)
- };
- if diff < config.ref_thres {
- (diff, refblock)
- } else {
- if view.size.x < config.min_block_size || view.size.y < config.min_block_size {
- (0.0, Block::Literal(view.pixels()))
- } else {
- let [av, bv] =
- unsafe { std::mem::transmute::<_, [View<&'static Frame>; 2]>(view.split()) };
- let [ap, bp] =
- unsafe { std::mem::transmute::<_, [View<&'static Frame>; 2]>(prev.split()) };
- let config = unsafe { std::mem::transmute::<_, &'static EncodeConfig>(config) };
-
- // only bother to do multithreading, when the block is big.
- let ((ad, a), (bd, b)) = if view.area() > 100 {
- rayon::join(
- || encode_block(av, ap, config),
- || encode_block(bv, bp, config),
- )
- } else {
- (encode_block(av, ap, config), encode_block(bv, bp, config))
- };
-
- (
- ad + bd,
- if a.is_literal() && b.is_literal() {
- Block::Literal(view.pixels())
- } else if Block::identical_ref(&a, &b) {
- Block::Reference {
- translation: Vec2::<isize>::ZERO,
- }
- } else {
- Block::Split(Box::new([a, b]))
- },
- )
- }
- }
-}
-
-pub fn importance(view: &View<&Frame>) -> f64 {
- let mut acc = 0;
- for x in 0..view.size.x {
- for y in 0..view.size.y {
- let p = Vec2 { x, y };
- if x > 0 {
- acc += Pixel::distance(view[p], view[p + Vec2::<isize>::LEFT]);
- }
- if y > 0 {
- acc += Pixel::distance(view[p], view[p + Vec2::<isize>::UP]);
- }
- }
- }
- (acc / view.area() as usize) as f64
-}
diff --git a/evc/src/codec/encode/simple.rs b/evc/src/codec/encode/simple.rs
deleted file mode 100644
index 2a971af..0000000
--- a/evc/src/codec/encode/simple.rs
+++ /dev/null
@@ -1,65 +0,0 @@
-use crate::{block::Block, frame::Frame, helpers::vector::Vec2, view::View};
-
-use super::EncodeConfig;
-
-pub fn exhaustive(
- view: &View<&Frame>,
- prev: &View<&Frame>,
- _config: &EncodeConfig,
- _max_diff: f64,
-) -> (f64, Block) {
- let mut diff = f64::INFINITY;
- let mut translation = Vec2::<isize>::ZERO;
- const OFFSETS: &[isize] = &[-64, -32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32, 64];
- for x in OFFSETS {
- for y in OFFSETS {
- let t = Vec2 { x: *x, y: *y };
- let d = View::diff(&view, &prev.offset(t));
- if d < diff {
- translation = t;
- diff = d;
- }
- }
- }
- (diff, Block::Reference { translation })
-}
-
-pub fn fast(
- view: &View<&Frame>,
- prev: &View<&Frame>,
- _config: &EncodeConfig,
- max_diff: f64,
-) -> (f64, Block) {
- let mut offset = Vec2::<isize>::ZERO;
- let mut diff = View::diff(&view, &prev);
- if diff < max_diff {
- (diff, Block::REFZERO)
- } else {
- loop {
- let (mut d, mut o) = (diff, offset);
- let mut probe = |test_o: Vec2<isize>| {
- let test_d = View::diff(&prev.clone().offset(test_o), &view);
- if test_d < d {
- d = test_d;
- o = test_o;
- }
- };
-
- probe(offset + Vec2 { x: 8, y: 0 });
- probe(offset + Vec2 { x: -8, y: 0 });
- probe(offset + Vec2 { x: 0, y: 8 });
- probe(offset + Vec2 { x: 0, y: -8 });
-
- probe(offset + Vec2 { x: 1, y: 0 });
- probe(offset + Vec2 { x: -1, y: 0 });
- probe(offset + Vec2 { x: 0, y: 1 });
- probe(offset + Vec2 { x: 0, y: -1 });
-
- if d >= diff {
- break (diff, Block::Reference { translation: o });
- }
- diff = d;
- offset = o;
- }
- }
-}
diff --git a/evc/src/codec/mod.rs b/evc/src/codec/mod.rs
deleted file mode 100644
index 3203e6e..0000000
--- a/evc/src/codec/mod.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub mod decode;
-pub mod encode;
-pub mod compress;
diff --git a/evc/src/debug.rs b/evc/src/debug.rs
deleted file mode 100644
index a7a9545..0000000
--- a/evc/src/debug.rs
+++ /dev/null
@@ -1,103 +0,0 @@
-use crate::{
- block::Block,
- format::ser::map_scalar8,
- frame::Frame,
- helpers::vector::Vec2,
- helpers::{matrix::Mat2, pixel::Pixel},
- view::View,
-};
-
-impl View<&mut Frame> {
- pub fn draw_box(&mut self, color: Pixel) {
- let w = self.size.x;
- let h = self.size.y;
- for x in 0..w {
- self[(x, 0)] = color;
- self[(x, h - 1)] = color;
- }
- for y in 0..h {
- self[(0, y)] = color;
- self[(w - 1, y)] = color;
- }
- }
-}
-
-impl Frame {
- pub fn draw_line(&mut self, start: Vec2<f32>, end: Vec2<f32>, color: Pixel) {
- let diff = end - start;
- let len = (diff.x * diff.x + diff.y * diff.y).sqrt();
- let normal = Vec2 {
- x: diff.x / len,
- y: diff.y / len,
- };
- let mut cursor = start.clone();
- let mut lc = 0.0;
- while lc < len {
- self.set(cursor.into(), color);
- lc += 0.5;
- cursor = cursor + normal.scale(0.5);
- }
- }
-}
-
-impl Pixel {
- pub const RED: Pixel = Pixel { r: 255, g: 0, b: 0 };
- pub const GREEN: Pixel = Pixel { r: 0, g: 255, b: 0 };
- pub const BLUE: Pixel = Pixel { r: 0, g: 0, b: 255 };
- pub const MAGENTA: Pixel = Pixel {
- r: 255,
- g: 0,
- b: 255,
- };
- pub const CYAN: Pixel = Pixel {
- r: 0,
- g: 255,
- b: 255,
- };
-}
-
-pub fn draw_debug(block: &Block, mut target: View<&mut Frame>) {
- match &block {
- Block::Literal(_) | Block::CompressedLiteral(_) => {
- target.draw_box(Pixel::GREEN);
- }
- Block::Split(box [a, b]) => {
- let [at, bt] = target.split_mut_unsafe();
- draw_debug(a, at);
- draw_debug(b, bt);
- }
- Block::Reference { translation } => {
- target.draw_box(Pixel::BLUE);
- target.frame.draw_line(
- target.center().into(),
- (target.center() + *translation).into(),
- Pixel::RED,
- )
- }
- Block::AdvancedReference(r) => {
- let mat = Mat2 {
- a: map_scalar8(r.transform.a),
- b: map_scalar8(r.transform.b),
- c: map_scalar8(r.transform.c),
- d: map_scalar8(r.transform.d),
- };
- let translation = Vec2 {
- x: map_scalar8(r.translation.x),
- y: map_scalar8(r.translation.y),
- };
- let halfsize = Into::<Vec2<f32>>::into(target.size).scale(0.5);
- let transform = |p| translation + mat.transform(p - halfsize) + halfsize;
- let (tl, tr, bl, br) = (
- transform(Vec2::<f32>::ZERO) + target.offset.into(),
- transform(target.size.x_only().into()) + target.offset.into(),
- transform(target.size.y_only().into()) + target.offset.into(),
- transform(target.size.into()) + target.offset.into(),
- );
- target.draw_box(Pixel::CYAN);
- target.frame.draw_line(tl, tr, Pixel::MAGENTA);
- target.frame.draw_line(tr, br, Pixel::MAGENTA);
- target.frame.draw_line(bl, br, Pixel::MAGENTA);
- target.frame.draw_line(tl, bl, Pixel::MAGENTA);
- }
- };
-}
diff --git a/evc/src/format/header.rs b/evc/src/format/header.rs
deleted file mode 100644
index ecbae89..0000000
--- a/evc/src/format/header.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-use crate::{
- format::ser::{Ser, Sink, Source},
- helpers::vector::Vec2,
-};
-
-#[derive(Debug, Clone, PartialEq, Copy)]
-pub struct Header {
- pub resolution: Vec2<isize>,
- pub frame_count: usize,
-}
-
-pub const MAGIC: [u8; 4] = [0x5eu8, 0xb1u8, 0xc3u8, 0x08u8];
-
-impl Ser for Header {
- fn write(&self, sink: &mut impl std::io::Write) -> anyhow::Result<()> {
- sink.put(MAGIC)?;
- sink.put((Into::<Vec2<u16>>::into(self.resolution), self.frame_count))?;
- Ok(())
- }
-
- fn read(source: &mut impl std::io::Read) -> anyhow::Result<Self> {
- assert_eq!(source.get::<[u8; 4]>()?, MAGIC);
- let (resolution, frame_count): (Vec2<u16>, usize) = source.get()?;
- Ok(Self {
- resolution: resolution.into(),
- frame_count,
- })
- }
-}
diff --git a/evc/src/format/mod.rs b/evc/src/format/mod.rs
deleted file mode 100644
index d4fb18c..0000000
--- a/evc/src/format/mod.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-pub mod header;
-pub mod ser; \ No newline at end of file
diff --git a/evc/src/format/ser.rs b/evc/src/format/ser.rs
deleted file mode 100644
index f063377..0000000
--- a/evc/src/format/ser.rs
+++ /dev/null
@@ -1,335 +0,0 @@
-use anyhow::Context;
-use std::io::{Read, Write};
-
-use crate::helpers::{matrix::Mat2, vector::Vec2};
-
-pub trait Sink {
- fn put<V: Ser>(&mut self, value: V) -> anyhow::Result<()>;
-}
-pub trait Source {
- fn get<V: Ser>(&mut self) -> anyhow::Result<V>;
-}
-
-impl<T: Write> Sink for T {
- fn put<V: Ser>(&mut self, value: V) -> anyhow::Result<()> {
- value.write(self)
- }
-}
-impl<T: Read> Source for T {
- fn get<V: Ser>(&mut self) -> anyhow::Result<V> {
- V::read(self)
- }
-}
-
-pub trait Ser: Sized {
- fn write(&self, sink: &mut impl Write) -> anyhow::Result<()>;
- fn read(source: &mut impl Read) -> anyhow::Result<Self>;
-}
-
-impl<A: Ser, B: Ser> Ser for (A, B) {
- fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
- self.0.write(sink).context("first tuple field")?;
- self.1.write(sink).context("second tuple field")?;
- Ok(())
- }
-
- fn read(source: &mut impl Read) -> anyhow::Result<Self> {
- Ok((A::read(source)?, B::read(source)?))
- }
-}
-impl<A: Ser, B: Ser, C: Ser> Ser for (A, B, C) {
- fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
- self.0.write(sink).context("first tuple field")?;
- self.1.write(sink).context("second tuple field")?;
- self.2.write(sink).context("third tuple field")?;
- Ok(())
- }
-
- fn read(source: &mut impl Read) -> anyhow::Result<Self> {
- Ok((A::read(source)?, B::read(source)?, C::read(source)?))
- }
-}
-impl<A: Ser, B: Ser, C: Ser, D: Ser> Ser for (A, B, C, D) {
- fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
- self.0.write(sink).context("first tuple field")?;
- self.1.write(sink).context("second tuple field")?;
- self.2.write(sink).context("third tuple field")?;
- self.3.write(sink).context("fourth tuple field")?;
- Ok(())
- }
-
- fn read(source: &mut impl Read) -> anyhow::Result<Self> {
- Ok((
- A::read(source)?,
- B::read(source)?,
- C::read(source)?,
- D::read(source)?,
- ))
- }
-}
-
-impl<A: Ser, const N: usize> Ser for [A; N] {
- fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
- for e in self {
- e.write(sink).context("some array")?;
- }
- Ok(())
- }
-
- fn read(source: &mut impl Read) -> anyhow::Result<Self> {
- let mut k: [A; N] = unsafe { std::mem::zeroed() };
- for i in 0..N {
- k[i] = A::read(source)?;
- }
- Ok(k)
- }
-}
-
-impl<T: Ser> Ser for Vec<T> {
- fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
- self.len().write(sink)?;
- for e in self {
- e.write(sink).context("some vec")?;
- }
- Ok(())
- }
-
- fn read(source: &mut impl Read) -> anyhow::Result<Self> {
- let mut v = vec![];
- for _ in 0..usize::read(source)? {
- v.push(T::read(source)?)
- }
- Ok(v)
- }
-}
-
-pub trait ConstSizeSerExt: Sized {
- fn write_const_size(&self, sink: &mut impl Write, size: usize) -> anyhow::Result<()>;
- fn read_const_size(source: &mut impl Read, size: usize) -> anyhow::Result<Self>;
-}
-impl<T: Ser> ConstSizeSerExt for Vec<T> {
- fn write_const_size(&self, sink: &mut impl Write, size: usize) -> anyhow::Result<()> {
- assert_eq!(self.len(), size);
- for e in self {
- e.write(sink).context("some const-size vec")?;
- }
- Ok(())
- }
-
- fn read_const_size(source: &mut impl Read, size: usize) -> anyhow::Result<Self> {
- let mut v = vec![];
- for _ in 0..size {
- v.push(T::read(source)?)
- }
- Ok(v)
- }
-}
-
-impl Ser for u8 {
- fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
- Ok(sink.write_all(&[*self]).context("write u8")?)
- }
- fn read(source: &mut impl Read) -> anyhow::Result<Self> {
- let mut buf = [0u8; 1];
- source.read_exact(&mut buf)?;
- Ok(buf[0])
- }
-}
-impl Ser for i8 {
- fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
- Ok(sink
- .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 1]>(self) })
- .context("write i8")?)
- }
- fn read(source: &mut impl Read) -> anyhow::Result<Self> {
- let mut buf = [0u8; 1];
- source.read_exact(&mut buf)?;
- Ok(unsafe { std::mem::transmute_copy(&buf) })
- }
-}
-impl Ser for u16 {
- fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
- Ok(sink
- .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 2]>(self) })
- .context("write u16")?)
- }
- fn read(source: &mut impl Read) -> anyhow::Result<Self> {
- let mut buf = [0u8; 2];
- source.read_exact(&mut buf)?;
- Ok(unsafe { std::mem::transmute_copy(&buf) })
- }
-}
-impl Ser for u32 {
- fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
- Ok(sink
- .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 4]>(self) })
- .context("write u32")?)
- }
- fn read(source: &mut impl Read) -> anyhow::Result<Self> {
- let mut buf = [0u8; 4];
- source.read_exact(&mut buf)?;
- Ok(unsafe { std::mem::transmute_copy(&buf) })
- }
-}
-impl Ser for u64 {
- fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
- Ok(sink
- .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) })
- .context("write u64")?)
- }
- fn read(source: &mut impl Read) -> anyhow::Result<Self> {
- let mut buf = [0u8; 8];
- source.read_exact(&mut buf)?;
- Ok(unsafe { std::mem::transmute_copy(&buf) })
- }
-}
-impl Ser for usize {
- fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
- Ok(sink
- .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) })
- .context("write usize")?)
- }
- fn read(source: &mut impl Read) -> anyhow::Result<Self> {
- let mut buf = [0u8; 8];
- source.read_exact(&mut buf)?;
- Ok(unsafe { std::mem::transmute_copy(&buf) })
- }
-}
-impl Ser for isize {
- fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
- Ok(sink
- .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) })
- .context("write isize")?)
- }
- fn read(source: &mut impl Read) -> anyhow::Result<Self> {
- let mut buf = [0u8; 8];
- source.read_exact(&mut buf)?;
- Ok(unsafe { std::mem::transmute_copy(&buf) })
- }
-}
-impl Ser for f32 {
- fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
- Ok(sink
- .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 4]>(self) })
- .context("write f32")?)
- }
- fn read(source: &mut impl Read) -> anyhow::Result<Self> {
- let mut buf = [0u8; 4];
- source.read_exact(&mut buf)?;
- Ok(unsafe { std::mem::transmute_copy(&buf) })
- }
-}
-impl Ser for f64 {
- fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
- Ok(sink
- .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) })
- .context("write f64")?)
- }
- fn read(source: &mut impl Read) -> anyhow::Result<Self> {
- let mut buf = [0u8; 8];
- source.read_exact(&mut buf)?;
- Ok(unsafe { std::mem::transmute_copy(&buf) })
- }
-}
-
-impl<T: Ser + Copy> Ser for Vec2<T> {
- fn write(&self, sink: &mut impl std::io::Write) -> anyhow::Result<()> {
- sink.put((self.x, self.y))
- }
-
- fn read(source: &mut impl std::io::Read) -> anyhow::Result<Self> {
- let (x, y) = source.get()?;
- Ok(Vec2 { x, y })
- }
-}
-impl<T: Ser + Copy> Ser for Mat2<T> {
- fn write(&self, sink: &mut impl std::io::Write) -> anyhow::Result<()> {
- sink.put((self.a, self.b, self.c, self.d))
- }
-
- fn read(source: &mut impl std::io::Read) -> anyhow::Result<Self> {
- let (a, b, c, d) = source.get()?;
- Ok(Mat2 { a, b, c, d })
- }
-}
-
-pub struct Small<T>(pub T);
-impl Ser for Small<Vec2<isize>> {
- fn write(&self, sink: &mut impl std::io::Write) -> anyhow::Result<()> {
- sink.put((self.0.x as i8, self.0.y as i8))
- }
-
- fn read(source: &mut impl std::io::Read) -> anyhow::Result<Self> {
- let (x, y): (i8, i8) = source.get()?;
- Ok(Small(Vec2 {
- x: x as isize,
- y: y as isize,
- }))
- }
-}
-
-pub fn map_scalar8(v: i8) -> f32 {
- match v {
- 0 => 0.0,
- x if x > 0 => 2f32.powf((x as f32).abs() / 2.0 - 2.0),
- x => -2f32.powf((-x as f32).abs() / 2.0 - 2.0),
- }
-}
-// const SCALAR8: [f32; 256] = gen_scalar8_lookup();
-// const fn gen_scalar8_lookup() -> [f32; 256] {
-// let mut a = [0.0; 256];
-// let mut i = 0usize;
-// while i < 256 {
-// a[i as usize] = if i == 0 {
-// 0.0
-// } else {
-// let x = i as i8 as f32;
-// x.signum() * 2f32.powf(x.abs() / 2.0 - 2.0)
-// };
-// i += 1;
-// }
-// a
-// }
-
-#[cfg(test)]
-mod test {
- use super::{Ser, Sink};
- use crate::format::header::Header;
- use crate::{format::ser::Source, helpers::vector::Vec2};
- use std::fmt::Debug;
- use std::io::Cursor;
-
- fn test_ser<T: PartialEq + Ser + Debug + Clone>(value: T) {
- let mut buf = vec![];
- Cursor::new(&mut buf).put(value.clone()).unwrap();
- assert_eq!(value, Cursor::new(&mut buf).get().unwrap());
- }
-
- #[test]
- fn simple() {
- let mut buf = vec![];
- Cursor::new(&mut buf).put(10usize).unwrap();
- assert_eq!(10usize, Cursor::new(&mut buf).get().unwrap());
- }
- #[test]
- fn tuple() {
- let mut buf = vec![];
- Cursor::new(&mut buf).put((10usize, 5u8, 3u16)).unwrap();
- assert_eq!((10usize, 5u8, 3u16), Cursor::new(&mut buf).get().unwrap());
- }
- #[test]
- fn header() {
- test_ser(Header {
- frame_count: 123,
- resolution: Vec2 { x: 13, y: 37 },
- });
- }
- #[test]
- fn vec() {
- test_ser(vec![1u16, 2, 3, 4]);
- }
- #[test]
- fn array() {
- test_ser([1u16, 2, 3, 4]);
- }
-}
diff --git a/evc/src/frame.rs b/evc/src/frame.rs
deleted file mode 100644
index 78d0e73..0000000
--- a/evc/src/frame.rs
+++ /dev/null
@@ -1,109 +0,0 @@
-use crate::{
- format::ser::{Sink, Source},
- helpers::{pixel::Pixel, vector::Vec2},
- view::View,
-};
-use std::ops::{Index, IndexMut};
-
-#[derive(Debug, Clone)]
-pub struct Frame {
- pub size: Vec2<isize>,
- buffer: Vec<Pixel>,
-}
-
-impl Frame {
- pub fn new(size: Vec2<isize>) -> Self {
- Self {
- size,
- buffer: (0..size.x * size.y).map(|_| Pixel::default()).collect(),
- }
- }
- pub fn read(source: &mut impl Source, size: Vec2<isize>) -> anyhow::Result<Self> {
- let mut frame = Frame::new(size);
- for y in 0..size.y {
- for x in 0..size.x {
- let pixel = source.get::<Pixel>()?;
- frame[(x, y)] = pixel;
- }
- }
- Ok(frame)
- }
- pub fn write(&self, sink: &mut impl Sink) -> anyhow::Result<()> {
- for y in 0..self.size.y {
- for x in 0..self.size.x {
- sink.put(self[(x, y)])?;
- }
- }
- Ok(())
- }
- pub fn view<'a>(&'a self) -> View<&'a Frame> {
- View::new(self, Vec2::<isize>::ZERO, self.size)
- }
- pub fn view_mut<'a>(&'a mut self) -> View<&'a mut Frame> {
- View::new(self, Vec2::<isize>::ZERO, self.size)
- }
- pub fn view_area<'a>(&'a self, offset: Vec2<isize>, size: Vec2<isize>) -> View<&'a Frame> {
- View::new(self, offset, size)
- }
- pub fn view_area_mut<'a>(
- &'a mut self,
- offset: Vec2<isize>,
- size: Vec2<isize>,
- ) -> View<&'a mut Frame> {
- View::new(self, offset, size)
- }
- pub fn set(&mut self, pos: Vec2<isize>, color: Pixel) {
- if pos.x >= 0 && pos.y >= 0 && pos.x < self.size.x && pos.y < self.size.y {
- self[pos] = color
- }
- }
-}
-
-impl Index<Vec2<isize>> for Frame {
- type Output = Pixel;
- #[inline]
- fn index(&self, Vec2 { x, y }: Vec2<isize>) -> &Self::Output {
- &self.buffer
- [(x.clamp(0, self.size.x - 1) + y.clamp(0, self.size.y - 1) * self.size.x) as usize]
- }
-}
-impl IndexMut<Vec2<isize>> for Frame {
- #[inline]
- fn index_mut(&mut self, Vec2 { x, y }: Vec2<isize>) -> &mut Self::Output {
- &mut self.buffer[(x + y * self.size.x) as usize]
- }
-}
-
-impl Frame {
- #[inline]
- pub fn sample(&self, p: Vec2<f32>) -> Pixel {
- self[Vec2 {
- x: p.x as isize,
- y: p.y as isize,
- }]
- // let fx = p.x.floor() as isize;
- // let fy = p.y.floor() as isize;
- // let cx = p.x.ceil() as isize;
- // let cy = p.y.ceil() as isize;
-
- // // TODO dont loose accuracy here
- // Pixel::average(
- // Pixel::average(self[Vec2 { x: fx, y: fy }], self[Vec2 { x: fx, y: cy }]),
- // Pixel::average(self[Vec2 { x: cx, y: fx }], self[Vec2 { x: cx, y: fy }]),
- // )
- }
-}
-
-impl Index<(isize, isize)> for Frame {
- type Output = Pixel;
- #[inline]
- fn index(&self, (x, y): (isize, isize)) -> &Self::Output {
- &self[Vec2 { x, y }]
- }
-}
-impl IndexMut<(isize, isize)> for Frame {
- #[inline]
- fn index_mut(&mut self, (x, y): (isize, isize)) -> &mut Self::Output {
- &mut self[Vec2 { x, y }]
- }
-}
diff --git a/evc/src/helpers/matrix.rs b/evc/src/helpers/matrix.rs
deleted file mode 100644
index 0007440..0000000
--- a/evc/src/helpers/matrix.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-use crate::helpers::vector::Vec2;
-
-#[derive(Debug, Clone, Copy, PartialEq)]
-pub struct Mat2<T> {
- pub a: T,
- pub b: T,
- pub c: T,
- pub d: T,
-}
-
-impl<T: std::ops::Mul<Output = T> + std::ops::Add<Output = T> + Copy> Mat2<T> {
- #[inline]
- pub fn transform(&self, v: Vec2<T>) -> Vec2<T> {
- Vec2 {
- x: self.a * v.x + self.b * v.y,
- y: self.c * v.x + self.d * v.y,
- }
- }
-}
-
-impl<T: std::ops::Mul<Output = T> + std::ops::Add<Output = T> + Copy> std::ops::Mul for Mat2<T> {
- type Output = Mat2<T>;
- #[inline]
- fn mul(self, rhs: Mat2<T>) -> Mat2<T> {
- let (x, y) = (self, rhs);
- Mat2 {
- a: x.a * y.a + x.b * y.c,
- b: x.a * y.b + x.b * y.d,
- c: x.c * y.a + x.d * y.c,
- d: x.c * y.b + x.d * y.d,
- }
- }
-}
diff --git a/evc/src/helpers/mod.rs b/evc/src/helpers/mod.rs
deleted file mode 100644
index d3aa3d2..0000000
--- a/evc/src/helpers/mod.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-pub mod vector;
-pub mod threading;
-pub mod matrix;
-pub mod pixel;
diff --git a/evc/src/helpers/pixel.rs b/evc/src/helpers/pixel.rs
deleted file mode 100644
index 39fe98c..0000000
--- a/evc/src/helpers/pixel.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-use crate::format::ser::{Ser, Sink, Source};
-
-#[derive(Copy, Clone, Debug, Default, PartialEq)]
-pub struct Pixel {
- pub r: u8,
- pub g: u8,
- pub b: u8,
-}
-
-impl Ser for Pixel {
- fn write(&self, sink: &mut impl std::io::Write) -> anyhow::Result<()> {
- sink.put((self.r, self.g, self.b))
- }
-
- fn read(source: &mut impl std::io::Read) -> anyhow::Result<Self> {
- let (r, g, b) = source.get()?;
- Ok(Self { r, g, b })
- }
-}
-
-impl Pixel {
- pub const BLACK: Pixel = Pixel { r: 0, g: 0, b: 0 };
- #[inline]
- pub fn distance(a: Pixel, b: Pixel) -> usize {
- let (rd, gd, bd) = (
- a.r.abs_diff(b.r) as usize,
- a.g.abs_diff(b.g) as usize,
- a.b.abs_diff(b.b) as usize,
- );
- // fast_sqrt(rd * rd + gd * gd + bd * bd)
- // SQRT[rd + gd + bd]
- rd + gd + bd
- }
-
- #[inline]
- pub fn average(a: Pixel, b: Pixel) -> Pixel {
- Pixel {
- r: ((a.r as u16 + b.r as u16) >> 1) as u8,
- g: ((a.g as u16 + b.g as u16) >> 1) as u8,
- b: ((a.b as u16 + b.b as u16) >> 1) as u8,
- }
- }
-
- #[inline]
- pub fn scale(&self, factor: f32) -> Pixel {
- Pixel {
- r: ((self.r as f32) * factor).clamp(0.0, 255.0) as u8,
- g: ((self.g as f32) * factor).clamp(0.0, 255.0) as u8,
- b: ((self.b as f32) * factor).clamp(0.0, 255.0) as u8,
- }
- }
-}
-
-pub const SQRT: [usize; 256 * 3] = gen_sqrt_lookup();
-
-const fn gen_sqrt_lookup<const N: usize>() -> [usize; N] {
- let mut arr = [0; N];
- let mut i = 0;
- while i < N {
- arr[i] = sqrt(i as f32) as usize;
- i += 1;
- }
- arr
-}
-
-const fn sqrt(x: f32) -> f32 {
- let a = 1.0;
- let a = (a + x / a) * 0.5;
- let a = (a + x / a) * 0.5;
- let a = (a + x / a) * 0.5;
- a
-}
-
-pub fn fast_sqrt(x: usize) -> usize {
- let a = 1;
- let a = (a + x / (a + 1)) / 2;
- let a = (a + x / (a + 1)) / 2;
- // let a = (a + x / (a + 1)) / 2;
- // let a = (a + x / (a + 1)) / 2;
- a
-}
diff --git a/evc/src/helpers/threading.rs b/evc/src/helpers/threading.rs
deleted file mode 100644
index 3291172..0000000
--- a/evc/src/helpers/threading.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-use std::{
- sync::atomic::{AtomicUsize, Ordering},
- thread,
-};
-
-static THREADS_RUNNING: AtomicUsize = AtomicUsize::new(0);
-
-pub fn both_par<F1, F2, O1, O2>(f1: F1, f2: F2, max_threads: usize) -> (O1, O2)
-where
- F1: FnOnce() -> O1 + Send + 'static,
- O1: Send + 'static,
- F2: FnOnce() -> O2,
-{
- if THREADS_RUNNING.load(Ordering::Relaxed) < max_threads {
- THREADS_RUNNING.fetch_add(1, Ordering::Relaxed);
-
- let o1h = thread::spawn(move || f1());
- let o2 = f2();
- let o1 = o1h.join().unwrap();
-
- THREADS_RUNNING.fetch_sub(1, Ordering::Relaxed);
- (o1, o2)
- } else {
- (f1(), f2())
- }
-}
diff --git a/evc/src/helpers/vector.rs b/evc/src/helpers/vector.rs
deleted file mode 100644
index a4766d1..0000000
--- a/evc/src/helpers/vector.rs
+++ /dev/null
@@ -1,126 +0,0 @@
-#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Vec2<T> {
- pub x: T,
- pub y: T,
-}
-
-impl From<Vec2<isize>> for Vec2<u16> {
- fn from(value: Vec2<isize>) -> Self {
- Self {
- x: value.x as u16,
- y: value.y as u16,
- }
- }
-}
-impl From<Vec2<u16>> for Vec2<isize> {
- fn from(value: Vec2<u16>) -> Self {
- Self {
- x: value.x as isize,
- y: value.y as isize,
- }
- }
-}
-impl From<Vec2<f32>> for Vec2<isize> {
- fn from(value: Vec2<f32>) -> Self {
- Self {
- x: value.x as isize,
- y: value.y as isize,
- }
- }
-}
-
-impl Vec2<isize> {
- pub const ZERO: Vec2<isize> = Vec2 { x: 0, y: 0 };
- pub const UP: Vec2<isize> = Vec2 { x: 0, y: -1 };
- pub const LEFT: Vec2<isize> = Vec2 { x: -1, y: 0 };
-}
-impl Vec2<f32> {
- pub const ZERO: Vec2<f32> = Vec2 { x: 0.0, y: 0.0 };
- pub const UP: Vec2<f32> = Vec2 { x: 0.0, y: -1.0 };
- pub const LEFT: Vec2<f32> = Vec2 { x: -1.0, y: 0.0 };
-}
-
-impl<T: std::ops::Div<Output = T> + Copy> Vec2<T> {
- pub fn downscale(&self, f: T) -> Self {
- Self {
- x: self.x / f,
- y: self.y / f,
- }
- }
-}
-
-impl<T: std::ops::Mul<Output = T> + Copy> Vec2<T> {
- pub fn scale(&self, f: T) -> Self {
- Self {
- x: self.x * f,
- y: self.y * f,
- }
- }
- pub fn area(&self) -> T {
- self.x * self.y
- }
-}
-
-impl Vec2<isize> {
- pub fn x_only(&self) -> Self {
- Self { x: self.x, y: 0 }
- }
- pub fn y_only(&self) -> Self {
- Self { x: 0, y: self.y }
- }
-}
-
-impl Into<Vec2<f32>> for Vec2<isize> {
- fn into(self) -> Vec2<f32> {
- Vec2 {
- x: self.x as f32,
- y: self.y as f32,
- }
- }
-}
-impl From<(isize, isize)> for Vec2<f32> {
- fn from((x, y): (isize, isize)) -> Self {
- Vec2 {
- x: x as f32,
- y: y as f32,
- }
- }
-}
-
-impl<T: std::ops::Add> std::ops::Add for Vec2<T> {
- type Output = Vec2<T::Output>;
- #[inline]
- fn add(self, rhs: Self) -> Self::Output {
- Vec2 {
- x: self.x + rhs.x,
- y: self.y + rhs.y,
- }
- }
-}
-impl<T: std::ops::Sub> std::ops::Sub for Vec2<T> {
- type Output = Vec2<T::Output>;
- #[inline]
- fn sub(self, rhs: Self) -> Self::Output {
- Vec2 {
- x: self.x - rhs.x,
- y: self.y - rhs.y,
- }
- }
-}
-impl<T: std::ops::Mul> std::ops::Mul for Vec2<T> {
- type Output = Vec2<T::Output>;
- #[inline]
- fn mul(self, rhs: Self) -> Self::Output {
- Vec2 {
- x: self.x * rhs.x,
- y: self.y * rhs.y,
- }
- }
-}
-
-impl<T> From<(T, T)> for Vec2<T> {
- #[inline]
- fn from((x, y): (T, T)) -> Self {
- Vec2 { x, y }
- }
-}
diff --git a/evc/src/lib.rs b/evc/src/lib.rs
deleted file mode 100644
index d269471..0000000
--- a/evc/src/lib.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-#![feature(box_patterns)]
-#![feature(const_fn_floating_point_arithmetic)]
-// #![feature(const_for)]
-// #![feature(const_mut_refs)]
-
-pub mod block;
-pub mod codec;
-pub mod debug;
-pub mod frame;
-pub mod view;
-pub mod refsampler;
-pub mod helpers;
-pub mod format;
diff --git a/evc/src/refsampler.rs b/evc/src/refsampler.rs
deleted file mode 100644
index 8a8f44f..0000000
--- a/evc/src/refsampler.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-use crate::{
- block::AdvancedReference,
- format::ser::map_scalar8,
- frame::Frame,
- helpers::{matrix::Mat2, pixel::Pixel, vector::Vec2},
- view::View,
-};
-
-#[derive(Debug, Clone)]
-pub struct Sampler<'a> {
- pub view: View<&'a Frame>,
- pub halfsize: Vec2<f32>,
-
- pub translation: Vec2<f32>,
- pub transform: Mat2<f32>,
-
- pub value_scale: f32,
-}
-
-impl<'a> Sampler<'a> {
- #[inline]
- pub fn sample(&self, p: Vec2<f32>) -> Pixel {
- self.view
- .sample(self.translation + self.transform.transform(p - self.halfsize) + self.halfsize)
- .scale(self.value_scale)
- }
- pub fn from_refblock(
- view: View<&'a Frame>,
- AdvancedReference {
- translation,
- transform,
- value_scale,
- }: &AdvancedReference,
- ) -> Self {
- Self {
- transform: Mat2 {
- a: map_scalar8(transform.a),
- b: map_scalar8(transform.b),
- c: map_scalar8(transform.c),
- d: map_scalar8(transform.d),
- },
- halfsize: Into::<Vec2<f32>>::into(view.size).scale(0.5),
- translation: Vec2 {
- x: map_scalar8(translation.x),
- y: map_scalar8(translation.y),
- },
- value_scale: 1.05f32.powf(*value_scale as f32),
- view,
- }
- }
-}
diff --git a/evc/src/view.rs b/evc/src/view.rs
deleted file mode 100644
index 6f34965..0000000
--- a/evc/src/view.rs
+++ /dev/null
@@ -1,241 +0,0 @@
-use crate::{
- frame::Frame,
- helpers::{pixel::Pixel, vector::Vec2},
- refsampler::Sampler,
-};
-use std::ops::{Index, IndexMut};
-
-#[derive(Debug, Clone)]
-pub struct View<T> {
- pub frame: T,
- pub offset: Vec2<isize>,
- pub size: Vec2<isize>,
-}
-
-impl<T> View<T> {
- pub fn new(frame: T, offset: Vec2<isize>, size: Vec2<isize>) -> Self {
- Self {
- frame,
- offset,
- size,
- }
- }
- pub fn area(&self) -> isize {
- self.size.x * self.size.y
- }
- pub fn center(&self) -> Vec2<isize> {
- self.offset + self.size.downscale(2)
- }
-}
-
-impl<T> View<&mut T> {
- pub fn split_mut_unsafe(&mut self) -> [Self; 2] {
- let vert = self.size.x > self.size.y;
- [
- Self {
- frame: unsafe { std::mem::transmute::<&mut T, &mut T>(&mut self.frame) },
- offset: self.offset,
- size: if vert {
- Vec2 {
- x: self.size.x / 2,
- y: self.size.y,
- }
- } else {
- Vec2 {
- x: self.size.x,
- y: self.size.y / 2,
- }
- },
- },
- Self {
- frame: unsafe { std::mem::transmute::<&mut T, &mut T>(&mut self.frame) },
- offset: if vert {
- Vec2 {
- x: self.offset.x + self.size.x / 2,
- y: self.offset.y,
- }
- } else {
- Vec2 {
- x: self.offset.x,
- y: self.offset.y + self.size.y / 2,
- }
- },
- size: if vert {
- Vec2 {
- x: self.size.x - self.size.x / 2,
- y: self.size.y,
- }
- } else {
- Vec2 {
- x: self.size.x,
- y: self.size.y - self.size.y / 2,
- }
- },
- },
- ]
- }
-}
-impl<T: Copy> View<T> {
- pub fn offset(&self, offset: Vec2<isize>) -> Self {
- Self {
- frame: self.frame,
- offset: self.offset + offset,
- size: self.size,
- }
- }
- pub fn split(&self) -> [Self; 2] {
- let vert = self.size.x > self.size.y;
- [
- Self {
- frame: self.frame,
- offset: self.offset,
- size: if vert {
- Vec2 {
- x: self.size.x / 2,
- y: self.size.y,
- }
- } else {
- Vec2 {
- x: self.size.x,
- y: self.size.y / 2,
- }
- },
- },
- Self {
- frame: self.frame,
- offset: if vert {
- Vec2 {
- x: self.offset.x + self.size.x / 2,
- y: self.offset.y,
- }
- } else {
- Vec2 {
- x: self.offset.x,
- y: self.offset.y + self.size.y / 2,
- }
- },
- size: if vert {
- Vec2 {
- x: self.size.x - self.size.x / 2,
- y: self.size.y,
- }
- } else {
- Vec2 {
- x: self.size.x,
- y: self.size.y - self.size.y / 2,
- }
- },
- },
- ]
- }
-}
-impl<T: Index<Vec2<isize>, Output = Pixel>> View<&T> {
- pub fn diff(va: &Self, vb: &Self) -> f64 {
- assert_eq!(va.size, vb.size);
- let mut acc = 0;
- for x in 0..va.size.x {
- for y in 0..va.size.y {
- let a = va[(x, y)];
- let b = vb[(x, y)];
- acc += Pixel::distance(a, b);
- }
- }
- acc as f64
- }
- pub fn diff_sampler(va: &Self, vb: &Sampler<'_>) -> f64 {
- assert_eq!(va.size, vb.view.size);
- let mut acc = 0;
- for x in 0..va.size.x {
- for y in 0..va.size.y {
- let a = va[(x, y)];
- let b = vb.sample(Vec2 {
- x: x as f32,
- y: y as f32,
- });
- acc += Pixel::distance(a, b);
- }
- }
- acc as f64
- }
-
- pub fn pixels(&self) -> Vec<Pixel> {
- let mut v = vec![];
- for y in 0..self.size.y {
- for x in 0..self.size.x {
- v.push(self[(x, y)]);
- }
- }
- v
- }
-}
-impl View<&mut Frame> {
- pub fn copy_from(&mut self, other: &View<&Frame>) {
- for x in 0..self.size.x {
- for y in 0..self.size.y {
- self[(x, y)] = other[(x, y)];
- }
- }
- }
- pub fn copy_from_sampler(&mut self, other: &Sampler) {
- for x in 0..self.size.x {
- for y in 0..self.size.y {
- self[(x, y)] = other.sample((x, y).into());
- }
- }
- }
-
- pub fn set_pixels(&mut self, pixels: &Vec<Pixel>) {
- for y in 0..self.size.y {
- for x in 0..self.size.x {
- self[(x, y)] = pixels[(y * self.size.x + x) as usize]
- }
- }
- }
-}
-impl View<&Frame> {
- pub fn sample(&self, p: Vec2<f32>) -> Pixel {
- self.frame.sample(p + self.offset.into())
- }
-}
-
-impl<T: Index<Vec2<isize>, Output = Pixel>> Index<Vec2<isize>> for View<&T> {
- type Output = Pixel;
- #[inline]
- fn index(&self, p: Vec2<isize>) -> &Self::Output {
- &self.frame[self.offset + p]
- }
-}
-impl<T: Index<Vec2<isize>, Output = Pixel>> Index<Vec2<isize>> for View<&mut T> {
- type Output = Pixel;
- #[inline]
- fn index(&self, p: Vec2<isize>) -> &Self::Output {
- &self.frame[self.offset + p]
- }
-}
-impl<T: IndexMut<Vec2<isize>, Output = Pixel>> IndexMut<Vec2<isize>> for View<&mut T> {
- #[inline]
- fn index_mut(&mut self, p: Vec2<isize>) -> &mut Self::Output {
- &mut self.frame[self.offset + p]
- }
-}
-
-impl<T: Index<Vec2<isize>, Output = Pixel>> Index<(isize, isize)> for View<&T> {
- type Output = Pixel;
- #[inline]
- fn index(&self, (x, y): (isize, isize)) -> &Self::Output {
- &self[Vec2 { x, y }]
- }
-}
-impl<T: Index<Vec2<isize>, Output = Pixel>> Index<(isize, isize)> for View<&mut T> {
- type Output = Pixel;
- #[inline]
- fn index(&self, (x, y): (isize, isize)) -> &Self::Output {
- &self[Vec2 { x, y }]
- }
-}
-impl<T: IndexMut<Vec2<isize>, Output = Pixel>> IndexMut<(isize, isize)> for View<&mut T> {
- #[inline]
- fn index_mut(&mut self, (x, y): (isize, isize)) -> &mut Self::Output {
- &mut self[Vec2 { x, y }]
- }
-}