diff options
Diffstat (limited to 'evc')
-rw-r--r-- | evc/Cargo.toml | 2 | ||||
-rw-r--r-- | evc/src/bin/decode.rs | 5 | ||||
-rw-r--r-- | evc/src/bin/encode.rs | 14 | ||||
-rw-r--r-- | evc/src/block.rs | 26 | ||||
-rw-r--r-- | evc/src/codec/decode.rs | 5 | ||||
-rw-r--r-- | evc/src/codec/encode.rs | 80 | ||||
-rw-r--r-- | evc/src/format/ser.rs | 34 | ||||
-rw-r--r-- | evc/src/helpers/matrix.rs | 9 | ||||
-rw-r--r-- | evc/src/refsampler.rs | 1 |
9 files changed, 131 insertions, 45 deletions
diff --git a/evc/Cargo.toml b/evc/Cargo.toml index b5e9ee9..f88e947 100644 --- a/evc/Cargo.toml +++ b/evc/Cargo.toml @@ -2,7 +2,7 @@ name = "evc" version = "0.1.0" edition = "2021" - + [dependencies] clap = { version = "*", features = ["derive"] } anyhow = "1.0.66" diff --git a/evc/src/bin/decode.rs b/evc/src/bin/decode.rs index b7dd4e1..36b1f80 100644 --- a/evc/src/bin/decode.rs +++ b/evc/src/bin/decode.rs @@ -68,5 +68,10 @@ fn draw_debug(block: &Block, mut target: View<&mut Frame>) { .frame .draw_line(target.center(), target.center() + *translation, Pixel::RED) } + Block::AdvancedReference { + translation: _, + transform: _, + value_scale: _, + } => (), // TODO } } diff --git a/evc/src/bin/encode.rs b/evc/src/bin/encode.rs index f81bb5e..e5ffa41 100644 --- a/evc/src/bin/encode.rs +++ b/evc/src/bin/encode.rs @@ -3,7 +3,7 @@ use clap::Parser; use evc::{ codec::{ decode::decode_block, - encode::{encode_block, EncodeConfig}, + encode::{encode_block, EncodeConfig, EncodeMode}, }, format::{header::Header, ser::Sink}, frame::Frame, @@ -20,6 +20,12 @@ pub struct EncodeArgs { #[arg(short = 'H', long)] height: usize, + #[arg(short, long)] + mode: EncodeMode, + + #[arg(short, long, default_value = "8")] + jobs: usize, + #[arg(short = 't', long, default_value = "1.5")] ref_thres: f64, #[arg(short = 'T', long)] @@ -34,11 +40,11 @@ fn main() -> anyhow::Result<()> { let mut output = BufWriter::new(std::io::stdout()); let config = EncodeConfig { - translate: !args.no_translation, + mode: evc::codec::encode::EncodeMode::Advanced, ref_thres: 50.0, - max_diff_size: 10_000, + max_diff_area: 10_000, min_block_size: 8, - max_threads: 12, + max_threads: args.jobs, }; let size = Vec2 { diff --git a/evc/src/block.rs b/evc/src/block.rs index 3a37820..0a7ace3 100644 --- a/evc/src/block.rs +++ b/evc/src/block.rs @@ -1,16 +1,23 @@ use anyhow::bail; use crate::{ - format::ser::{Ser, Sink, Source, Small}, - helpers::pixel::Pixel, + format::ser::{Ser, Sink, Small, Source}, helpers::vector::Vec2, + helpers::{matrix::Mat2, pixel::Pixel}, }; #[derive(Clone, Debug)] pub enum Block { Literal(Vec<Pixel>), Split(Box<[Block; 2]>), - Reference { translation: Vec2<isize> }, + Reference { + translation: Vec2<isize>, + }, + AdvancedReference { + translation: Vec2<i8>, + transform: Mat2<i8>, + value_scale: i8, + }, } impl Block { @@ -29,6 +36,14 @@ impl Block { sink.put(2u8)?; sink.put(Small(*translation))?; } + Block::AdvancedReference { + translation, + transform, + value_scale, + } => { + sink.put(3u8)?; + sink.put((*translation, *transform, *value_scale))?; + } } Ok(()) } @@ -56,6 +71,11 @@ impl Block { 2 => Block::Reference { translation: source.get::<Small<Vec2<isize>>>()?.0, }, + 3 => Block::AdvancedReference { + translation: source.get()?, + transform: source.get()?, + value_scale: source.get()?, + }, x => bail!("corrupt block type ({})", x), }) } diff --git a/evc/src/codec/decode.rs b/evc/src/codec/decode.rs index e6fa918..2da320f 100644 --- a/evc/src/codec/decode.rs +++ b/evc/src/codec/decode.rs @@ -10,5 +10,10 @@ pub fn decode_block(block: &Block, mut target: View<&mut Frame>, prev: View<&Fra decode_block(b, bt, bp); } Block::Reference { translation } => target.copy_from(&prev.offset(*translation)), + Block::AdvancedReference { + translation: _, + transform: _, + value_scale: _, + } => todo!(), } } diff --git a/evc/src/codec/encode.rs b/evc/src/codec/encode.rs index b11bbc0..5ce0b16 100644 --- a/evc/src/codec/encode.rs +++ b/evc/src/codec/encode.rs @@ -4,48 +4,70 @@ use crate::{ helpers::{pixel::Pixel, threading::both_par, vector::Vec2}, view::View, }; +use clap::ValueEnum; #[derive(Debug, Clone)] pub struct EncodeConfig { - pub translate: bool, + pub mode: EncodeMode, pub ref_thres: f64, - pub max_diff_size: isize, + pub max_diff_area: isize, pub min_block_size: isize, pub max_threads: usize, - // pub importance_k: f64, - // pub importance_scale: f64, } -pub fn encode_block(view: View<&Frame>, prev: View<&Frame>, config: &EncodeConfig) -> Block { - // let importance = importance(&view); +#[derive(Debug, Clone, ValueEnum)] +pub enum EncodeMode { + Trivial, + Default, + Advanced, +} + - let (diff, translation) = if view.area() > config.max_diff_size { - (f64::INFINITY, Vec2::<isize>::ZERO) - } else if config.translate { - let mut best_diff = f64::INFINITY; - let mut best_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 translation = Vec2 { x: *x, y: *y }; - let diff = View::diff(&view, &prev.offset(translation)); // / view.area() as f64; - if diff < best_diff { - best_translation = translation; - best_diff = diff; +pub fn encode_block(view: View<&Frame>, prev: View<&Frame>, config: &EncodeConfig) -> Block { + let (diff, refblock) = if view.area() > config.max_diff_area { + ( + f64::INFINITY, + Block::Reference { + translation: Vec2::<isize>::ZERO, + }, + ) + } else { + match config.mode { + EncodeMode::Trivial => ( + View::diff(&view, &prev) / view.area() as f64, + Block::Reference { + translation: Vec2::<isize>::ZERO, + }, + ), + EncodeMode::Default => { + let mut best_diff = f64::INFINITY; + let mut best_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 translation = Vec2 { x: *x, y: *y }; + let diff = View::diff(&view, &prev.offset(translation)); // / view.area() as f64; + if diff < best_diff { + best_translation = translation; + best_diff = diff; + } + } } + ( + best_diff, + Block::Reference { + translation: best_translation, + }, + ) + } + EncodeMode::Advanced => { + todo!() } } - (best_diff, best_translation) - } else { - ( - View::diff(&view, &prev) / view.area() as f64, - Vec2::<isize>::ZERO, - ) }; - // config.importance_k) - // / (config.importance_k + importance * config.importance_scale) - if diff < (config.ref_thres) { - Block::Reference { translation } + if diff < config.ref_thres { + refblock } else { if view.size.x < config.min_block_size || view.size.y < config.min_block_size { Block::Literal(view.pixels()) diff --git a/evc/src/format/ser.rs b/evc/src/format/ser.rs index 65d5e26..731a7a3 100644 --- a/evc/src/format/ser.rs +++ b/evc/src/format/ser.rs @@ -1,7 +1,7 @@ use anyhow::Context; use std::io::{Read, Write}; -use crate::helpers::vector::Vec2; +use crate::helpers::{matrix::Mat2, vector::Vec2}; pub trait Sink { fn put<V: Ser>(&mut self, value: V) -> anyhow::Result<()>; @@ -49,6 +49,24 @@ impl<A: Ser, B: Ser, C: Ser> Ser for (A, B, C) { 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<()> { @@ -192,8 +210,7 @@ impl Ser for f64 { } } - -impl Ser for Vec2<isize> { +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)) } @@ -203,6 +220,16 @@ impl Ser for Vec2<isize> { 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>> { @@ -219,7 +246,6 @@ impl Ser for Small<Vec2<isize>> { } } - #[cfg(test)] mod test { use super::{Ser, Sink}; diff --git a/evc/src/helpers/matrix.rs b/evc/src/helpers/matrix.rs index 74d2ae4..92f46b2 100644 --- a/evc/src/helpers/matrix.rs +++ b/evc/src/helpers/matrix.rs @@ -1,10 +1,11 @@ use crate::helpers::vector::Vec2; +#[derive(Debug, Clone, Copy)] pub struct Mat2<T> { - a: T, - b: T, - c: T, - d: 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> { diff --git a/evc/src/refsampler.rs b/evc/src/refsampler.rs index db0ab6f..b27ceae 100644 --- a/evc/src/refsampler.rs +++ b/evc/src/refsampler.rs @@ -13,6 +13,7 @@ pub struct Sampler<'a> { } impl Sampler<'_> { + #[inline] pub fn sample(&self, p: Vec2<f32>) -> Pixel { self.frame .sample(self.translation + self.transform.transform(p)) |