diff options
Diffstat (limited to 'evc')
-rw-r--r-- | evc/src/bin/encode.rs | 6 | ||||
-rw-r--r-- | evc/src/block.rs | 17 | ||||
-rw-r--r-- | evc/src/codec/encode.rs | 16 | ||||
-rw-r--r-- | evc/src/debug.rs | 4 | ||||
-rw-r--r-- | evc/src/frame.rs | 67 | ||||
-rw-r--r-- | evc/src/header.rs | 7 | ||||
-rw-r--r-- | evc/src/lib.rs | 1 | ||||
-rw-r--r-- | evc/src/pixel.rs | 1 | ||||
-rw-r--r-- | evc/src/ser.rs | 15 | ||||
-rw-r--r-- | evc/src/vec2.rs | 59 | ||||
-rw-r--r-- | evc/src/view.rs | 142 |
11 files changed, 249 insertions, 86 deletions
diff --git a/evc/src/bin/encode.rs b/evc/src/bin/encode.rs index acd6e92..05ebd24 100644 --- a/evc/src/bin/encode.rs +++ b/evc/src/bin/encode.rs @@ -5,6 +5,7 @@ use evc::{ frame::Frame, header::Header, ser::Sink, + vec2::Vec2, }; use log::info; use std::io::{BufReader, BufWriter}; @@ -25,7 +26,10 @@ fn main() -> anyhow::Result<()> { let mut input = BufReader::new(std::io::stdin()); let mut output = BufWriter::new(std::io::stdout()); - let size = (args.width, args.height); + let size = Vec2 { + x: args.width as isize, + y: args.height as isize, + }; output .put(Header { resolution: size, diff --git a/evc/src/block.rs b/evc/src/block.rs index 8daba5c..d0dd4d5 100644 --- a/evc/src/block.rs +++ b/evc/src/block.rs @@ -3,13 +3,14 @@ use anyhow::bail; use crate::{ pixel::Pixel, ser::{Ser, Sink, Source}, + vec2::Vec2, }; #[derive(Clone, Debug)] pub enum Block { Literal(Vec<Pixel>), Split(Box<[Block; 2]>), - Reference { translation: (usize, usize) }, + Reference { translation: Vec2 }, } impl Block { @@ -32,20 +33,20 @@ impl Block { Ok(()) } - pub fn read(source: &mut impl std::io::Read, size: (usize, usize)) -> anyhow::Result<Self> { + pub fn read(source: &mut impl std::io::Read, size: Vec2) -> anyhow::Result<Self> { Ok(match source.get::<u8>()? { 0 => Block::Literal(source.get()?), 1 => Block::Split(Box::new({ - let vert = size.0 > size.1; + let vert = size.x > size.y; let asize = if vert { - (size.0 / 2, size.1) + (size.x / 2, size.y).into() } else { - (size.0, size.1 / 2) + (size.x, size.y / 2).into() }; let bsize = if vert { - (size.0 - size.0 / 2, size.1) + (size.x - size.x / 2, size.y).into() } else { - (size.0, size.1 - size.1 / 2) + (size.x, size.y - size.y / 2).into() }; let a = Block::read(source, asize)?; @@ -53,7 +54,7 @@ impl Block { [a, b] })), 2 => Block::Reference { - translation: (0, 0), //source.get()?, + translation: Vec2::ZERO, //source.get()?, }, x => bail!("corrupt block type ({})", x), }) diff --git a/evc/src/codec/encode.rs b/evc/src/codec/encode.rs index 43a2783..7256265 100644 --- a/evc/src/codec/encode.rs +++ b/evc/src/codec/encode.rs @@ -1,14 +1,22 @@ -use crate::{block::Block, frame::Frame, view::View}; +use crate::{block::Block, frame::Frame, view::View, vec2::Vec2}; pub fn encode_block(view: View<&Frame>, prev: View<&Frame>) -> Block { + // let mut best_diff = f64::INFINITY; + // for x in [-32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32] { + // for y in [-32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32] { + // let diff = View::diff(&view, &prev) / view.area() as f64; + // if diff < best_diff { + // } + // } + // } let diff = View::diff(&view, &prev) / view.area() as f64; - // eprintln!("{:?} {diff}", view.size); + // if best_diff < 0.9 { if diff < 0.9 { Block::Reference { - translation: (0, 0), + translation: Vec2::ZERO, } } else { - if view.size.0 < 16 { + if view.size.x < 16 { Block::Literal(view.pixels()) } else { let [av, bv] = view.split(); diff --git a/evc/src/debug.rs b/evc/src/debug.rs index 44b51cf..7b27b83 100644 --- a/evc/src/debug.rs +++ b/evc/src/debug.rs @@ -2,8 +2,8 @@ use crate::{frame::Frame, pixel::Pixel, view::View}; impl View<&mut Frame> { pub fn draw_box(&mut self, color: Pixel) { - let w = self.size.0; - let h = self.size.1; + let w = self.size.x; + let h = self.size.y; for x in 0..w { self[(x, 0)] = color; self[(x, h - 1)] = color; diff --git a/evc/src/frame.rs b/evc/src/frame.rs index 666dc00..81390a2 100644 --- a/evc/src/frame.rs +++ b/evc/src/frame.rs @@ -1,29 +1,28 @@ use crate::{ pixel::Pixel, ser::{Sink, Source}, + vec2::Vec2, view::View, }; use std::ops::{Index, IndexMut}; #[derive(Debug, Clone)] pub struct Frame { - pub size: (usize, usize), - buffer: Vec<Vec<Pixel>>, + pub size: Vec2, + buffer: Vec<Pixel>, } impl Frame { - pub fn new(size: (usize, usize)) -> Self { + pub fn new(size: Vec2) -> Self { Self { size, - buffer: (0..size.0) - .map(|_| (0..size.1).map(|_| Pixel::default()).collect()) - .collect(), + buffer: (0..size.x * size.y).map(|_| Pixel::default()).collect(), } } - pub fn read(source: &mut impl Source, size: (usize, usize)) -> anyhow::Result<Self> { + pub fn read(source: &mut impl Source, size: Vec2) -> anyhow::Result<Self> { let mut frame = Frame::new(size); - for y in 0..size.1 { - for x in 0..size.0 { + for y in 0..size.y { + for x in 0..size.x { let pixel = source.get::<Pixel>()?; frame[(x, y)] = pixel; } @@ -31,45 +30,55 @@ impl Frame { Ok(frame) } pub fn write(&self, sink: &mut impl Sink) -> anyhow::Result<()> { - for y in 0..self.size.1 { - for x in 0..self.size.0 { + 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, (0, 0), self.size) + View::new(self, Vec2::ZERO, self.size) } pub fn view_mut<'a>(&'a mut self) -> View<&'a mut Frame> { - View::new(self, (0, 0), self.size) + View::new(self, Vec2::ZERO, self.size) } - pub fn view_area<'a>( - &'a self, - offset: (usize, usize), - size: (usize, usize), - ) -> View<&'a Frame> { + pub fn view_area<'a>(&'a self, offset: Vec2, size: Vec2) -> View<&'a Frame> { View::new(self, offset, size) } - pub fn view_area_mut<'a>( - &'a mut self, - offset: (usize, usize), - size: (usize, usize), - ) -> View<&'a mut Frame> { + pub fn view_area_mut<'a>(&'a mut self, offset: Vec2, size: Vec2) -> View<&'a mut Frame> { View::new(self, offset, size) } } -impl Index<(usize, usize)> for Frame { +impl Index<Vec2> for Frame { type Output = Pixel; #[inline] - fn index(&self, (x, y): (usize, usize)) -> &Self::Output { - &self.buffer[x][y] + fn index(&self, Vec2 { x, y }: Vec2) -> &Self::Output { + if x >= 0 && y >= 0 && x < self.size.x && y < self.size.y { + &self.buffer[(x + y * self.size.x) as usize] + } else { + &Pixel::BLACK + } + } +} +impl IndexMut<Vec2> for Frame { + #[inline] + fn index_mut(&mut self, Vec2 { x, y }: Vec2) -> &mut Self::Output { + &mut self.buffer[(x + y * self.size.x) as usize] + } +} + +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<(usize, usize)> for Frame { +impl IndexMut<(isize, isize)> for Frame { #[inline] - fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Self::Output { - &mut self.buffer[x][y] + fn index_mut(&mut self, (x, y): (isize, isize)) -> &mut Self::Output { + &mut self[Vec2 { x, y }] } } diff --git a/evc/src/header.rs b/evc/src/header.rs index 5244ce5..a613627 100644 --- a/evc/src/header.rs +++ b/evc/src/header.rs @@ -1,8 +1,11 @@ -use crate::ser::{Ser, Sink, Source}; +use crate::{ + ser::{Ser, Sink, Source}, + vec2::Vec2, +}; #[derive(Debug, Clone, PartialEq, Copy)] pub struct Header { - pub resolution: (usize, usize), + pub resolution: Vec2, pub frame_count: usize, } diff --git a/evc/src/lib.rs b/evc/src/lib.rs index a513116..ee242e6 100644 --- a/evc/src/lib.rs +++ b/evc/src/lib.rs @@ -8,3 +8,4 @@ pub mod header; pub mod pixel; pub mod ser; pub mod view; +pub mod vec2; diff --git a/evc/src/pixel.rs b/evc/src/pixel.rs index aaf8d83..b3ef841 100644 --- a/evc/src/pixel.rs +++ b/evc/src/pixel.rs @@ -19,6 +19,7 @@ impl Ser for Pixel { } impl Pixel { + pub const BLACK: Pixel = Pixel { r: 0, g: 0, b: 0 }; #[inline] pub fn distance(a: Pixel, b: Pixel) -> f64 { let (rd, gd, bd) = ( diff --git a/evc/src/ser.rs b/evc/src/ser.rs index 3b7814f..61ca684 100644 --- a/evc/src/ser.rs +++ b/evc/src/ser.rs @@ -141,6 +141,18 @@ impl Ser for usize { 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 @@ -171,6 +183,7 @@ mod test { use super::{Ser, Sink}; use crate::header::Header; use crate::ser::Source; + use crate::vec2::Vec2; use std::fmt::Debug; use std::io::Cursor; @@ -196,7 +209,7 @@ mod test { fn header() { test_ser(Header { frame_count: 123, - resolution: (13, 37), + resolution: Vec2 { x: 13, y: 37 }, }); } #[test] diff --git a/evc/src/vec2.rs b/evc/src/vec2.rs new file mode 100644 index 0000000..ffee124 --- /dev/null +++ b/evc/src/vec2.rs @@ -0,0 +1,59 @@ +use crate::ser::{Ser, Sink, Source}; + +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Vec2 { + pub x: isize, + pub y: isize, +} +impl Vec2 { + pub const ZERO: Vec2 = Vec2 { x: 0, y: 0 }; +} + +impl Ser for Vec2 { + 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 std::ops::Add for Vec2 { + type Output = Vec2; + #[inline] + fn add(self, rhs: Self) -> Self::Output { + Vec2 { + x: self.x + rhs.x, + y: self.y + rhs.y, + } + } +} +impl std::ops::Sub for Vec2 { + type Output = Vec2; + #[inline] + fn sub(self, rhs: Self) -> Self::Output { + Vec2 { + x: self.x - rhs.x, + y: self.y - rhs.y, + } + } +} +impl std::ops::Mul for Vec2 { + type Output = Vec2; + #[inline] + fn mul(self, rhs: Self) -> Self::Output { + Vec2 { + x: self.x * rhs.x, + y: self.y * rhs.y, + } + } +} + +impl From<(isize, isize)> for Vec2 { + #[inline] + fn from((x, y): (isize, isize)) -> Self { + Vec2 { x, y } + } +} diff --git a/evc/src/view.rs b/evc/src/view.rs index 9c4778b..4cd4a45 100644 --- a/evc/src/view.rs +++ b/evc/src/view.rs @@ -1,89 +1,132 @@ -use crate::{frame::Frame, pixel::Pixel}; +use crate::{frame::Frame, pixel::Pixel, vec2::Vec2}; use std::ops::{Index, IndexMut}; pub struct View<T> { pub frame: T, - pub offset: (usize, usize), - pub size: (usize, usize), + pub offset: Vec2, + pub size: Vec2, } impl<T> View<T> { - pub fn new(frame: T, offset: (usize, usize), size: (usize, usize)) -> Self { + pub fn new(frame: T, offset: Vec2, size: Vec2) -> Self { Self { frame, offset, size, } } - pub fn area(&self) -> usize { - self.size.0 * self.size.1 + pub fn area(&self) -> isize { + self.size.x * self.size.y } } impl<T> View<&mut T> { pub fn split_mut_unsafe(&mut self) -> [Self; 2] { - let vert = self.size.0 > self.size.1; + 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 { - (self.size.0 / 2, self.size.1) + Vec2 { + x: self.size.x / 2, + y: self.size.y, + } } else { - (self.size.0, self.size.1 / 2) + 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 { - (self.offset.0 + self.size.0 / 2, self.offset.1) + Vec2 { + x: self.offset.x + self.size.x / 2, + y: self.offset.y, + } } else { - (self.offset.0, self.offset.1 + self.size.1 / 2) + Vec2 { + x: self.offset.x, + y: self.offset.y + self.size.y / 2, + } }, size: if vert { - (self.size.0 - self.size.0 / 2, self.size.1) + Vec2 { + x: self.size.x - self.size.x / 2, + y: self.size.y, + } } else { - (self.size.0, self.size.1 - self.size.1 / 2) + Vec2 { + x: self.size.x, + y: self.size.y - self.size.y / 2, + } }, }, ] } } impl<T: Copy> View<T> { + pub fn offset(&self, offset: Vec2) -> Self { + Self { + frame: self.frame, + offset: self.offset + offset, + size: self.size, + } + } pub fn split(&self) -> [Self; 2] { - let vert = self.size.0 > self.size.1; + let vert = self.size.x > self.size.y; [ Self { frame: self.frame, offset: self.offset, size: if vert { - (self.size.0 / 2, self.size.1) + Vec2 { + x: self.size.x / 2, + y: self.size.y, + } } else { - (self.size.0, self.size.1 / 2) + Vec2 { + x: self.size.x, + y: self.size.y / 2, + } }, }, Self { frame: self.frame, offset: if vert { - (self.offset.0 + self.size.0 / 2, self.offset.1) + Vec2 { + x: self.offset.x + self.size.x / 2, + y: self.offset.y, + } } else { - (self.offset.0, self.offset.1 + self.size.1 / 2) + Vec2 { + x: self.offset.x, + y: self.offset.y + self.size.y / 2, + } }, size: if vert { - (self.size.0 - self.size.0 / 2, self.size.1) + Vec2 { + x: self.size.x - self.size.x / 2, + y: self.size.y, + } } else { - (self.size.0, self.size.1 - self.size.1 / 2) + Vec2 { + x: self.size.x, + y: self.size.y - self.size.y / 2, + } }, }, ] } } -impl<T: Index<(usize, usize), Output = Pixel>> View<&T> { +impl<T: Index<Vec2, Output = Pixel>> View<&T> { pub fn diff(va: &Self, vb: &Self) -> f64 { assert_eq!(va.size, vb.size); let mut acc = 0.0; - for x in 0..va.size.0 { - for y in 0..va.size.1 { + 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); @@ -93,8 +136,8 @@ impl<T: Index<(usize, usize), Output = Pixel>> View<&T> { } pub fn pixels(&self) -> Vec<Pixel> { let mut v = vec![]; - for x in 0..self.size.0 { - for y in 0..self.size.1 { + for x in 0..self.size.x { + for y in 0..self.size.y { v.push(self[(x, y)]); } } @@ -103,38 +146,59 @@ impl<T: Index<(usize, usize), Output = Pixel>> View<&T> { } impl View<&mut Frame> { pub fn copy_from(&mut self, other: &View<&Frame>) { - for x in 0..self.size.0 { - for y in 0..self.size.1 { + for x in 0..self.size.x { + for y in 0..self.size.y { self[(x, y)] = other[(x, y)]; } } } pub fn set_pixels(&mut self, pixels: &Vec<Pixel>) { - for x in 0..self.size.0 { - for y in 0..self.size.1 { - self[(x, y)] = pixels[x * self.size.1 + y] + for x in 0..self.size.x { + for y in 0..self.size.y { + self[(x, y)] = pixels[(x * self.size.y + y) as usize] } } } } -impl<T: Index<(usize, usize), Output = Pixel>> Index<(usize, usize)> for View<&T> { +impl<T: Index<Vec2, Output = Pixel>> Index<Vec2> for View<&T> { + type Output = Pixel; + #[inline] + fn index(&self, p: Vec2) -> &Self::Output { + &self.frame[self.offset + p] + } +} +impl<T: Index<Vec2, Output = Pixel>> Index<Vec2> for View<&mut T> { + type Output = Pixel; + #[inline] + fn index(&self, p: Vec2) -> &Self::Output { + &self.frame[self.offset + p] + } +} +impl<T: IndexMut<Vec2, Output = Pixel>> IndexMut<Vec2> for View<&mut T> { + #[inline] + fn index_mut(&mut self, p: Vec2) -> &mut Self::Output { + &mut self.frame[self.offset + p] + } +} + +impl<T: Index<Vec2, Output = Pixel>> Index<(isize, isize)> for View<&T> { type Output = Pixel; #[inline] - fn index(&self, (x, y): (usize, usize)) -> &Self::Output { - &self.frame[(x + self.offset.0, y + self.offset.1)] + fn index(&self, (x, y): (isize, isize)) -> &Self::Output { + &self[Vec2 { x, y }] } } -impl<T: Index<(usize, usize), Output = Pixel>> Index<(usize, usize)> for View<&mut T> { +impl<T: Index<Vec2, Output = Pixel>> Index<(isize, isize)> for View<&mut T> { type Output = Pixel; #[inline] - fn index(&self, (x, y): (usize, usize)) -> &Self::Output { - &self.frame[(x + self.offset.0, y + self.offset.1)] + fn index(&self, (x, y): (isize, isize)) -> &Self::Output { + &self[Vec2 { x, y }] } } -impl<T: IndexMut<(usize, usize), Output = Pixel>> IndexMut<(usize, usize)> for View<&mut T> { +impl<T: IndexMut<Vec2, Output = Pixel>> IndexMut<(isize, isize)> for View<&mut T> { #[inline] - fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Self::Output { - &mut self.frame[(x + self.offset.0, y + self.offset.1)] + fn index_mut(&mut self, (x, y): (isize, isize)) -> &mut Self::Output { + &mut self[Vec2 { x, y }] } } |