aboutsummaryrefslogtreecommitdiff
path: root/lvc/codec
diff options
context:
space:
mode:
Diffstat (limited to 'lvc/codec')
-rw-r--r--lvc/codec/Cargo.toml12
-rw-r--r--lvc/codec/src/debug.rs42
-rw-r--r--lvc/codec/src/decode.rs76
-rw-r--r--lvc/codec/src/diff.rs131
-rw-r--r--lvc/codec/src/encode.rs190
-rw-r--r--lvc/codec/src/frameio.rs35
-rw-r--r--lvc/codec/src/huff.rs190
-rw-r--r--lvc/codec/src/impls.rs165
-rw-r--r--lvc/codec/src/lib.rs55
-rw-r--r--lvc/codec/src/serialize.rs116
-rw-r--r--lvc/codec/src/split.rs42
11 files changed, 0 insertions, 1054 deletions
diff --git a/lvc/codec/Cargo.toml b/lvc/codec/Cargo.toml
deleted file mode 100644
index 0c52ad2..0000000
--- a/lvc/codec/Cargo.toml
+++ /dev/null
@@ -1,12 +0,0 @@
-[package]
-name = "bv1"
-version = "0.1.0"
-edition = "2021"
-
-[dependencies]
-rayon = {version="1.7.0",optional = true}
-
-[features]
-default = ["parallel"]
-parallel = ["dep:rayon"]
-
diff --git a/lvc/codec/src/debug.rs b/lvc/codec/src/debug.rs
deleted file mode 100644
index d6c37c2..0000000
--- a/lvc/codec/src/debug.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-use crate::{split::split, Block, Frame, Pixel, View, P2};
-
-pub fn draw_debug(frame: &mut Frame, view: View, block: &Block) {
- match block {
- Block::Lit(_) => rect(frame, view, Pixel::GREEN),
- Block::Split(a, b) => {
- let [av, bv] = split(view);
- draw_debug(frame, av, &a);
- draw_debug(frame, bv, &b);
- }
- Block::Ref(r) => {
- let v = View {
- a: view.a,
- b: view.a + P2 { x: 2, y: 2 },
- };
- if r.pos_off != P2::ZERO {
- fill_rect(frame, v + P2 { x: 0, y: 0 }, Pixel::BLUE)
- }
- if r.color_off != Pixel::BLACK {
- fill_rect(frame, v + P2 { x: 2, y: 0 }, Pixel::RED)
- }
- }
- }
-}
-
-fn rect(frame: &mut Frame, view: View, color: Pixel) {
- for x in view.a.x..view.b.x {
- frame[P2 { x, y: view.a.y }] = color;
- frame[P2 { x, y: view.b.y - 1 }] = color;
- }
- for y in view.a.y..view.b.y {
- frame[P2 { y, x: view.a.x }] = color;
- frame[P2 { y, x: view.b.x - 1 }] = color;
- }
-}
-fn fill_rect(frame: &mut Frame, view: View, color: Pixel) {
- for y in view.a.y..view.b.y {
- for x in view.a.x..view.b.x {
- frame[P2 { x, y }] = color;
- }
- }
-}
diff --git a/lvc/codec/src/decode.rs b/lvc/codec/src/decode.rs
deleted file mode 100644
index 616b7af..0000000
--- a/lvc/codec/src/decode.rs
+++ /dev/null
@@ -1,76 +0,0 @@
-use crate::{
- debug::draw_debug, huff::read_huff, impls::join, split::split, Block, Frame, View, P2,
-};
-use std::io::{BufReader, BufWriter, Read, Result, Write};
-
-pub fn decode(size: P2, debug: bool, input: impl Read, output: impl Write) -> Result<()> {
- let mut input = BufReader::new(input);
- let mut output = BufWriter::new(output);
- let mut d = Decoder::new(size);
- let mut f = Frame::new(size);
- loop {
- d.decode_frame(&mut input, &mut f, debug)?;
- Frame::write(&mut output, &f)?;
- }
-}
-
-pub struct Decoder {
- last_frame: Frame,
- size: P2,
-}
-
-impl Decoder {
- pub fn new(size: P2) -> Self {
- Self {
- size,
- last_frame: Frame::new(size),
- }
- }
- pub fn decode_frame(
- &mut self,
- mut input: impl Read,
- output: &mut Frame,
- debug: bool,
- ) -> Result<()> {
- let huff = true;
- let b = if huff {
- let mut buf = vec![];
- read_huff(&mut input, &mut buf)?;
- eprintln!("{}", buf.len());
- let mut buf = std::io::Cursor::new(&mut buf);
- Block::read(&mut buf, View::all(self.size))?
- } else {
- Block::read(&mut input, View::all(self.size))?
- };
-
- decode_block(&self.last_frame, output, View::all(self.size), &b);
- self.last_frame.pixels.copy_from_slice(&output.pixels); // TODO use mem::swap
- if debug {
- draw_debug(output, View::all(self.size), &b);
- }
- Ok(())
- }
-}
-
-pub fn decode_block(last_frame: &Frame, frame: &mut Frame, view: View, block: &Block) {
- match block {
- Block::Lit(pxs) => frame.import(view, &pxs),
- Block::Split(a, b) => {
- let [av, bv] = split(view);
- let (frame1, frame2) =
- unsafe { (&mut *(frame as *mut Frame), &mut *(frame as *mut Frame)) };
- join(
- || decode_block(last_frame, frame1, av, &a),
- || decode_block(last_frame, frame2, bv, &b),
- );
- }
- Block::Ref(r) => {
- for y in view.a.y..view.b.y {
- for x in view.a.x..view.b.x {
- let p = P2 { x, y };
- frame[p] = last_frame[p + r.pos_off] + r.color_off
- }
- }
- }
- }
-}
diff --git a/lvc/codec/src/diff.rs b/lvc/codec/src/diff.rs
deleted file mode 100644
index 4d1a805..0000000
--- a/lvc/codec/src/diff.rs
+++ /dev/null
@@ -1,131 +0,0 @@
-use crate::{Frame, Pixel, Ref, View, P2};
-
-// 4ms
-pub fn diff([frame1, frame2]: [&Frame; 2], view: View, rp: Ref) -> u32 {
- let mut k = 0;
- for y in view.a.y..view.b.y {
- for x in view.a.x..view.b.x {
- let pos = P2 { x, y };
- let p1 = frame1[pos + rp.pos_off] + rp.color_off;
- let p2 = frame2[pos];
- k += pixel_diff(p1, p2)
- }
- }
- k
-}
-
-#[inline(always)]
-pub fn pixel_diff(p1: Pixel, p2: Pixel) -> u32 {
- p1.r.abs_diff(p2.r) as u32 + p1.g.abs_diff(p2.g) as u32 + p1.b.abs_diff(p2.b) as u32
-}
-
-// pub fn diff([frame1, frame2]: [&Frame; 2], view: View, rp: Ref) -> u32 {
-// let mut k = 0;
-// for y in view.a.y..view.b.y {
-// let s1_ystart = (y * frame1.size.x) as usize;
-// let s2_ystart = ((y + rp.pos_off.y) * frame1.size.x + rp.pos_off.x) as usize;
-// let s1 = &frame1.pixels[s1_ystart + view.a.x as usize..s1_ystart + view.b.x as usize];
-// let s2 = &frame2.pixels[s2_ystart + view.a.x as usize..s2_ystart + view.b.x as usize];
-// let s1 = unsafe { std::mem::transmute::<_, &[i16]>(s1) };
-// let s2 = unsafe { std::mem::transmute::<_, &[i16]>(s2) };
-
-// k += s1
-// .iter()
-// .zip(s2.iter())
-// .map(|(a, b)| a.abs_diff(*b) as u32)
-// .sum::<u32>()
-// }
-// k
-// }
-
-// pub fn fast_diff([frame1, frame2]: [&Frame; 2], view: View, rp: Ref) -> u32 {
-// assert!(view.size().x % 5 == 0);
-
-// let mut diff_lanes = i32x16::from_array([0; 16]);
-// let mut k1 = [0; 32];
-// let mut k2 = [0; 32];
-
-// let next_line = frame1.size.x as usize - view.size().x as usize;
-// let index_start = view.a.x as usize + view.a.y as usize * frame1.size.x as usize;
-// let index_end = view.b.x as usize + (view.b.y as usize - 1) * frame1.size.x as usize;
-
-// let mut i = index_start;
-// let mut x = view.a.x;
-
-// while i < index_end {
-
-// let f1: &[u8] =
-// unsafe { std::slice::from_raw_parts(frame1.pixels[sl_start..].as_ptr() as *mut u8, sl_size) };
-// let f2: &[u8] =
-// unsafe { std::slice::from_raw_parts(frame2.pixels[sl_start..].as_ptr() as *mut u8, sl_size) };
-
-// for i in 0..15 {
-// k1[i] = f1[i] as i32;
-// k2[i] = f2[i] as i32;
-// }
-
-// // for j in 0..5 {
-// // let j3 = j * 3;
-// // k1[j3] = frame1.pixels[i + j].r as i32;
-// // k2[j3] = frame2.pixels[i + j].r as i32;
-// // k1[j3 + 1] = frame1.pixels[i + j].g as i32;
-// // k2[j3 + 1] = frame2.pixels[i + j].g as i32;
-// // k1[j3 + 2] = frame1.pixels[i + j].b as i32;
-// // k2[j3 + 2] = frame2.pixels[i + j].b as i32;
-// // }
-// let pl1 = i16x32::from_array(k1);
-// let pl2 = i16x32::from_array(k2);
-// diff_lanes += (pl1 - pl2).abs();
-
-// i += 5;
-// x += 5;
-// if x > view.b.x {
-// i += next_line;
-// x = view.a.x
-// }
-// }
-
-// return diff_lanes.reduce_sum() as u32;
-// }
-
-// pub fn fast_diff([frame1, frame2]: [&Frame; 2], view: View, rp: Ref) -> u32 {
-// let mut diff_lanes = i32x16::from_array([0; 16]);
-// let mut k1 = [0; 16];
-// let mut k2 = [0; 16];
-
-// let next_line = frame1.size.x as usize - view.size().x as usize;
-// let index_start = view.a.x as usize + view.a.y as usize * frame1.size.x as usize;
-// let index_end = view.b.x as usize + (view.b.y as usize - 1) * frame1.size.x as usize;
-
-// let mut i = index_start;
-// let mut x = view.a.x;
-// let mut kfill = 0;
-
-// while i < index_end {
-// k1[kfill] = frame1.pixels[i].r as i32;
-// k2[kfill] = frame2.pixels[i].r as i32;
-// kfill += 1;
-// k1[kfill] = frame1.pixels[i].g as i32;
-// k2[kfill] = frame2.pixels[i].g as i32;
-// kfill += 1;
-// k1[kfill] = frame1.pixels[i].b as i32;
-// k2[kfill] = frame2.pixels[i].b as i32;
-// kfill += 1;
-
-// i += 1;
-// x += 1;
-// if x > view.b.x {
-// i += next_line;
-// x = view.a.x
-// }
-
-// if kfill == 15 {
-// let pl1 = i32x16::from_array(k1);
-// let pl2 = i32x16::from_array(k2);
-// diff_lanes += (pl1 - pl2).abs();
-// kfill = 0;
-// }
-// }
-
-// return diff_lanes.reduce_sum() as u32;
-// }
diff --git a/lvc/codec/src/encode.rs b/lvc/codec/src/encode.rs
deleted file mode 100644
index 564b0b3..0000000
--- a/lvc/codec/src/encode.rs
+++ /dev/null
@@ -1,190 +0,0 @@
-use crate::diff::{diff, pixel_diff};
-use crate::huff::write_huff;
-use crate::impls::join;
-use crate::split::split;
-use crate::{decode::decode_block, Block, Frame, Pixel, Ref, View, P2};
-use std::io::{BufReader, BufWriter, Read, Write};
-use std::time::Instant;
-
-#[derive(Debug, Clone)]
-pub struct EncodeConfig {
- pub threshold: f32,
- pub max_block_size: usize,
- pub attention_split: u32,
- pub keyframe_interval: usize,
-}
-
-pub fn encode(
- config: EncodeConfig,
- size: P2,
- input: impl Read,
- output: impl Write,
-) -> std::io::Result<()> {
- let mut input = BufReader::new(input);
- let mut output = BufWriter::new(output);
-
- let mut last_frame = Frame::new(size);
- for frame_number in 0.. {
- let mut frame = Frame::read(&mut input, size)?;
-
- let mut config = config.clone();
- if frame_number % config.keyframe_interval != 0 {
- config.threshold = std::f32::INFINITY;
- }
-
- let t = Instant::now();
- let b: Block = encode_block(&last_frame, &frame, View::all(size), &config);
- let time_encode = t.elapsed();
-
- let t = Instant::now();
- decode_block(&last_frame, &mut frame, View::all(size), &b);
- last_frame = frame;
- let time_decode = t.elapsed();
-
- if true {
- let mut buf = vec![];
- let mut bufw = std::io::Cursor::new(&mut buf);
- b.write(&mut bufw)?;
- drop(bufw);
- let t = Instant::now();
- let bits_raw = buf.len() * 8;
- let bits_huff = write_huff(&buf, &mut output)?;
- let time_huff = t.elapsed();
- drop(buf);
-
- eprintln!(
- "frame {frame_number}: {:?}",
- time_decode + time_huff + time_encode
- );
- eprintln!(
- "\tencode {time_encode:?} ({:.2}%)",
- (bits_raw as f32 / (size.area() * 24) as f32) * 100.0
- );
- eprintln!(
- "\thuff {time_huff:?} ({:.2}%)",
- (bits_huff as f32 / bits_raw as f32) * 100.0
- );
- eprintln!("\tdecode {time_decode:?}");
- } else {
- b.write(&mut output)?;
- }
- }
- Ok(())
-}
-
-pub fn encode_block(last_frame: &Frame, frame: &Frame, view: View, config: &EncodeConfig) -> Block {
- let view_area = view.size().area();
- if view_area > config.max_block_size
- || (view_area > 64 && attention(frame, view) > config.attention_split)
- {
- let [av, bv] = split(view);
- let (ab, bb) = join(
- || Box::new(encode_block(last_frame, frame, av, config)),
- || Box::new(encode_block(last_frame, frame, bv, config)),
- );
- return Block::Split(ab, bb);
- }
-
- let mut r = Ref::default();
- let mut d = diff([last_frame, frame], view, r);
-
- // let att = 1. - attention(frame, view) as f32 * 0.000001;
- // let thres = (config.threshold as f32 * att.clamp(0.2, 1.0)) as u32;
- let thres = (config.threshold * view_area as f32) as u32;
-
- let target_average = average_color(frame, view);
-
- for granularity in [2, 1, 2, 1, 2, 1, 2, 1] {
- let (nd, nrp) = optimize_ref(last_frame, frame, view, r, granularity, target_average);
- if nd < d {
- r = nrp;
- d = nd;
- } else {
- break;
- }
- }
-
- if d < thres {
- return Block::Ref(r);
- } else {
- Block::Lit(frame.export(view))
- }
-}
-
-pub fn optimize_ref(
- last_frame: &Frame,
- frame: &Frame,
- view: View,
- r: Ref,
- g: i32,
- target_average: Pixel,
-) -> (u32, Ref) {
- let g2 = g * 2;
- [
- Some(r.apply(|r| r.pos_off += P2 { x: g, y: 0 })),
- Some(r.apply(|r| r.pos_off += P2 { x: g, y: g })),
- Some(r.apply(|r| r.pos_off += P2 { x: 0, y: g })),
- Some(r.apply(|r| r.pos_off += P2 { x: -g, y: g })),
- Some(r.apply(|r| r.pos_off += P2 { x: -g, y: 0 })),
- Some(r.apply(|r| r.pos_off += P2 { x: -g, y: -g })),
- Some(r.apply(|r| r.pos_off += P2 { x: 0, y: -g })),
- Some(r.apply(|r| r.pos_off += P2 { x: g, y: -g })),
- Some(r.apply(|r| r.pos_off += P2 { x: g2, y: 0 })),
- Some(r.apply(|r| r.pos_off += P2 { x: g2, y: g2 })),
- Some(r.apply(|r| r.pos_off += P2 { x: 0, y: g2 })),
- Some(r.apply(|r| r.pos_off += P2 { x: -g2, y: g2 })),
- Some(r.apply(|r| r.pos_off += P2 { x: -g2, y: 0 })),
- Some(r.apply(|r| r.pos_off += P2 { x: -g2, y: -g2 })),
- Some(r.apply(|r| r.pos_off += P2 { x: 0, y: -g2 })),
- Some(r.apply(|r| r.pos_off += P2 { x: g2, y: -g2 })),
- {
- let mut r = r;
- let last_avr = average_color(last_frame, view);
- let diff = target_average - last_avr;
- r.color_off = diff;
- if diff != Pixel::BLACK {
- Some(r)
- } else {
- None
- }
- },
- ]
- .into_iter()
- .flatten()
- .map(|r| (diff([last_frame, frame], view, r), r))
- .min_by_key(|e| e.0)
- .unwrap()
-}
-
-pub fn attention(frame: &Frame, view: View) -> u32 {
- let mut k = 0;
- for y in view.a.y..view.b.y - 1 {
- for x in view.a.x..view.b.x - 1 {
- let p = P2 { x, y };
- k += pixel_diff(frame[p], frame[p + P2::X]).pow(2);
- k += pixel_diff(frame[p], frame[p + P2::Y]).pow(2);
- }
- }
- k
-}
-
-pub fn average_color(frame: &Frame, view: View) -> Pixel {
- let mut r = 0u32;
- let mut g = 0u32;
- let mut b = 0u32;
-
- for y in view.a.y..view.b.y {
- for x in view.a.x..view.b.x {
- let p = frame[P2 { x, y }];
- r += p.r as u32;
- g += p.g as u32;
- b += p.b as u32;
- }
- }
- let area = view.size().area() as u32;
- Pixel {
- r: (r / area) as i16,
- g: (g / area) as i16,
- b: (b / area) as i16,
- }
-}
diff --git a/lvc/codec/src/frameio.rs b/lvc/codec/src/frameio.rs
deleted file mode 100644
index f6cbcbf..0000000
--- a/lvc/codec/src/frameio.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-use crate::{Frame, Pixel, PixelValue, P2};
-use std::io::{Read, Result, Write};
-
-impl Frame {
- pub fn read(inp: &mut impl Read, size: P2) -> Result<Frame> {
- let mut f = Frame::new(size);
-
- for y in 0..size.y {
- for x in 0..size.x {
- let mut cc = [0u8; 3];
- inp.read_exact(&mut cc)?;
- f[P2 { x, y }] = Pixel {
- r: cc[0] as PixelValue,
- g: cc[1] as PixelValue,
- b: cc[2] as PixelValue,
- };
- }
- }
- Ok(f)
- }
-
- pub fn write(out: &mut impl Write, frame: &Frame) -> Result<()> {
- for y in 0..frame.size.y {
- for x in 0..frame.size.x {
- let p = frame[P2 { x, y }];
- let mut cc = [0u8; 3];
- cc[0] = p.r.clamp(0, 255) as u8;
- cc[1] = p.g.clamp(0, 255) as u8;
- cc[2] = p.b.clamp(0, 255) as u8;
- out.write_all(&mut cc)?;
- }
- }
- Ok(())
- }
-}
diff --git a/lvc/codec/src/huff.rs b/lvc/codec/src/huff.rs
deleted file mode 100644
index 6d74c42..0000000
--- a/lvc/codec/src/huff.rs
+++ /dev/null
@@ -1,190 +0,0 @@
-use std::io::{Read, Result, Write};
-
-#[derive(Debug, Clone)]
-enum HT {
- Branch(Box<HT>, Box<HT>),
- Terminal(u8),
-}
-
-pub fn write_huff(buf: &[u8], w: &mut impl Write) -> Result<usize> {
- let mut w = BitIO::new(w);
- assert!(buf.len() <= 0xffffff, "huff frame too big");
- w.wbyte((buf.len() & 0xff) as u8)?;
- w.wbyte(((buf.len() >> 8) & 0xff) as u8)?;
- w.wbyte(((buf.len() >> 16) & 0xff) as u8)?;
-
- let mut probs = [0usize; 256];
- for b in buf {
- probs[*b as usize] += 1;
- }
- let tree = HT::from_probabilities(probs);
- let mut table = [0u32; 256];
- tree.create_lut(&mut table, 1);
- tree.write(&mut w)?;
-
-
- for b in buf {
- let mut k = table[*b as usize];
- while k != 1 {
- w.wbit((k & 1) == 1)?;
- k >>= 1;
- }
- }
-
- w.flush()?;
- Ok(w.position)
-}
-
-pub fn read_huff(r: &mut impl Read, buf: &mut Vec<u8>) -> Result<usize> {
- let mut r = BitIO::new(r);
-
- let mut len = 0usize;
- len |= r.rbyte()? as usize;
- len |= (r.rbyte()? as usize) << 8;
- len |= (r.rbyte()? as usize) << 16;
-
- let root = HT::read(&mut r)?;
- let root = match &root {
- HT::Branch(a, b) => [a, b],
- _ => panic!("no!"),
- };
-
- let mut cursor = root;
- while buf.len() != len {
- let v = r.rbit()?;
- match cursor[v as usize].as_ref() {
- HT::Branch(a, b) => {
- cursor = [a, b];
- }
- HT::Terminal(n) => {
- buf.push(*n);
- cursor = root;
- }
- }
- }
- Ok(r.position)
-}
-
-impl HT {
- pub fn from_probabilities(ps: [usize; 256]) -> Self {
- let mut parts = ps
- .into_iter()
- .enumerate()
- .map(|(n, p)| (p, HT::Terminal(n as u8)))
- .collect::<Vec<_>>();
-
- while parts.len() != 1 {
- parts.sort_by_key(|e| -(e.0 as isize));
- let ((ap, at), (bp, bt)) = (parts.pop().unwrap(), parts.pop().unwrap());
- parts.push((ap + bp + 1, HT::Branch(box at, box bt)))
- }
- parts[0].1.clone()
- }
- pub fn create_lut(&self, table: &mut [u32; 256], mut prefix: u32) {
- assert!(self.depth() < 30, "too deep! doesnt fit {}", self.depth());
- match self {
- HT::Branch(a, b) => {
- let pz = 32 - prefix.leading_zeros();
- prefix ^= 1 << pz;
- prefix ^= 1 << (pz - 1);
- a.create_lut(table, prefix);
- prefix ^= 1 << (pz - 1);
- b.create_lut(table, prefix);
- }
- HT::Terminal(n) => {
- assert_eq!(table[*n as usize], 0);
- table[*n as usize] = prefix
- }
- }
- }
- pub fn depth(&self) -> usize {
- match self {
- HT::Branch(a, b) => a.depth().max(b.depth()) + 1,
- HT::Terminal(_) => 0,
- }
- }
- pub fn write(&self, w: &mut BitIO<impl Write>) -> Result<()> {
- match self {
- HT::Branch(a, b) => {
- w.wbit(false)?;
- a.write(w)?;
- b.write(w)?;
- }
- HT::Terminal(n) => {
- w.wbit(true)?;
- w.wbyte(*n)?;
- }
- }
- Ok(())
- }
- pub fn read(r: &mut BitIO<impl Read>) -> Result<Self> {
- match r.rbit()? {
- false => Ok(Self::Branch(box Self::read(r)?, box Self::read(r)?)),
- true => Ok(Self::Terminal(r.rbyte()?)),
- }
- }
-}
-
-pub struct BitIO<T> {
- inner: T,
- byte: u8,
- position: usize,
-}
-impl<T> BitIO<T> {
- pub fn new(inner: T) -> Self {
- Self {
- inner,
- byte: 0,
- position: 0,
- }
- }
-}
-impl<T: Write> BitIO<T> {
- #[inline]
- pub fn wbit(&mut self, b: bool) -> Result<()> {
- self.byte <<= 1;
- self.byte |= b as u8;
- self.position += 1;
- if self.position & 0b111 == 0 {
- self.inner.write_all(&[self.byte])?;
- }
- Ok(())
- }
- #[inline]
- pub fn wbyte(&mut self, v: u8) -> Result<()> {
- for i in 0..8 {
- self.wbit((v & (1 << i)) != 0)?;
- }
- Ok(())
- }
- pub fn flush(&mut self) -> Result<()> {
- while self.position & 0b111 != 0 {
- self.wbit(false)?;
- }
- Ok(())
- }
-}
-
-impl<T: Read> BitIO<T> {
- #[inline]
- pub fn rbit(&mut self) -> Result<bool> {
- if self.position & 0b111 == 0 {
- let mut buf = [0];
- self.inner.read_exact(&mut buf)?;
- self.byte = buf[0];
- }
-
- let v = (self.byte & 0b10000000) != 0;
- self.byte <<= 1;
- self.position += 1;
- Ok(v)
- }
- #[inline]
- pub fn rbyte(&mut self) -> Result<u8> {
- let mut v = 0u8;
- for i in 0..8 {
- v |= (self.rbit()? as u8) << i;
- }
- Ok(v)
- }
-}
diff --git a/lvc/codec/src/impls.rs b/lvc/codec/src/impls.rs
deleted file mode 100644
index b4cc119..0000000
--- a/lvc/codec/src/impls.rs
+++ /dev/null
@@ -1,165 +0,0 @@
-use crate::{Frame, Pixel, Ref, View, P2};
-use std::ops::{Add, AddAssign, Index, IndexMut, Sub};
-
-#[cfg(feature = "parallel")]
-pub use rayon::join;
-#[cfg(not(feature = "parallel"))]
-pub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
-where
- A: FnOnce() -> RA + Send,
- B: FnOnce() -> RB + Send,
- RA: Send,
- RB: Send,
-{
- (oper_a(), oper_b())
-}
-
-impl Frame {
- pub fn export(&self, view: View) -> Vec<Pixel> {
- let mut o = vec![];
- for y in view.a.y..view.b.y {
- for x in view.a.x..view.b.x {
- o.push(self[P2 { x, y }])
- }
- }
- o
- }
- pub fn import(&mut self, view: View, mut source: &[Pixel]) {
- for y in view.a.y..view.b.y {
- for x in view.a.x..view.b.x {
- self[P2 { x, y }] = source[0];
- source = &source[1..];
- }
- }
- assert_eq!(source.len(), 0)
- }
- pub fn new(size: P2) -> Self {
- Self {
- pixels: vec![Pixel::default(); size.area()],
- size,
- }
- }
-}
-impl Ref {
- #[inline]
- pub fn apply<F: Fn(&mut Self)>(mut self, f: F) -> Self {
- f(&mut self);
- self
- }
-}
-impl Pixel {
- pub const BLACK: Pixel = Pixel { r: 0, g: 0, b: 0 };
- 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 };
-}
-impl AddAssign for P2 {
- fn add_assign(&mut self, rhs: Self) {
- self.x += rhs.x;
- self.y += rhs.y;
- }
-}
-impl Add for Pixel {
- type Output = Pixel;
- #[inline]
- fn add(self, rhs: Self) -> Self::Output {
- Self {
- r: self.r + rhs.r,
- g: self.g + rhs.g,
- b: self.b + rhs.b,
- }
- }
-}
-impl Sub for Pixel {
- type Output = Pixel;
- #[inline]
- fn sub(self, rhs: Self) -> Self::Output {
- Self {
- r: self.r - rhs.r,
- g: self.g - rhs.g,
- b: self.b - rhs.b,
- }
- }
-}
-impl P2 {
- pub const ZERO: P2 = P2 { x: 0, y: 0 };
- pub const X: P2 = P2 { x: 1, y: 0 };
- pub const Y: P2 = P2 { x: 0, y: 1 };
-
- #[inline]
- pub fn area(&self) -> usize {
- (self.x * self.y) as usize
- }
-}
-impl View {
- #[inline]
- pub fn all(b: P2) -> Self {
- Self {
- a: P2::default(),
- b,
- }
- }
- #[inline]
- pub fn size(&self) -> P2 {
- self.b - self.a
- }
-}
-impl Add<P2> for View {
- type Output = View;
- #[inline]
- fn add(self, rhs: P2) -> Self::Output {
- View {
- a: self.a + rhs,
- b: self.b + rhs,
- }
- }
-}
-impl Add for P2 {
- type Output = P2;
- #[inline]
- fn add(self, rhs: Self) -> Self::Output {
- Self {
- x: self.x + rhs.x,
- y: self.y + rhs.y,
- }
- }
-}
-impl Sub for P2 {
- type Output = P2;
- #[inline]
- fn sub(self, rhs: Self) -> Self::Output {
- Self {
- x: self.x - rhs.x,
- y: self.y - rhs.y,
- }
- }
-}
-
-impl Index<P2> for Frame {
- type Output = Pixel;
- #[inline]
- fn index(&self, P2 { x, y }: P2) -> &Self::Output {
- &self
- .pixels
- .get(x as usize + (y as usize * self.size.x as usize))
- .unwrap_or(&Pixel { r: 0, g: 0, b: 0 })
- }
-}
-impl IndexMut<P2> for Frame {
- #[inline]
- fn index_mut(&mut self, P2 { x, y }: P2) -> &mut Self::Output {
- &mut self.pixels[x as usize + (y as usize * self.size.x as usize)]
- }
-}
-
-pub trait ToArray {
- type Output;
- fn to_array(self) -> [Self::Output; 2];
-}
-impl<A> ToArray for (A, A) {
- type Output = A;
- #[inline]
- fn to_array(self) -> [A; 2] {
- [self.0, self.1]
- }
-}
diff --git a/lvc/codec/src/lib.rs b/lvc/codec/src/lib.rs
deleted file mode 100644
index c764211..0000000
--- a/lvc/codec/src/lib.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-#![feature(portable_simd)]
-#![feature(io_error_other)]
-#![feature(box_syntax)]
-
-pub mod debug;
-pub mod decode;
-pub mod diff;
-pub mod encode;
-pub mod frameio;
-pub mod huff;
-pub mod impls;
-pub mod serialize;
-pub mod split;
-
-pub type PixelValue = i16;
-
-pub use decode::{decode, Decoder};
-pub use encode::encode;
-
-#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
-pub struct Pixel {
- pub r: PixelValue,
- pub g: PixelValue,
- pub b: PixelValue,
-}
-
-#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
-pub struct P2 {
- pub x: i32,
- pub y: i32,
-}
-
-pub struct Frame {
- pub size: P2,
- pub pixels: Vec<Pixel>,
-}
-
-#[derive(Debug, Clone, Copy)]
-pub struct View {
- pub a: P2,
- pub b: P2,
-}
-
-#[derive(Debug, Clone)]
-pub enum Block {
- Split(Box<Block>, Box<Block>),
- Lit(Vec<Pixel>),
- Ref(Ref),
-}
-
-#[derive(Debug, Clone, Copy, Default)]
-pub struct Ref {
- pub pos_off: P2,
- pub color_off: Pixel,
-}
diff --git a/lvc/codec/src/serialize.rs b/lvc/codec/src/serialize.rs
deleted file mode 100644
index 960aa1b..0000000
--- a/lvc/codec/src/serialize.rs
+++ /dev/null
@@ -1,116 +0,0 @@
-use crate::{split::split, Block, Pixel, Ref, View, P2};
-use std::io::{Read, Result, Write};
-
-impl Pixel {
- #[inline]
- pub fn write(&self, w: &mut impl Write) -> Result<()> {
- w.write_all(&[
- self.r.clamp(0, 255) as u8,
- self.g.clamp(0, 255) as u8,
- self.b.clamp(0, 255) as u8,
- ])
- }
- #[inline]
- pub fn read(r: &mut impl Read) -> Result<Pixel> {
- Ok(Self {
- r: read_byte(r)? as i16,
- g: read_byte(r)? as i16,
- b: read_byte(r)? as i16,
- })
- }
-}
-impl Pixel {
- #[inline]
- pub fn write_full(&self, w: &mut impl Write) -> Result<()> {
- write_word(w, self.r)?;
- write_word(w, self.g)?;
- write_word(w, self.b)?;
- Ok(())
- }
- #[inline]
- pub fn read_full(r: &mut impl Read) -> Result<Pixel> {
- Ok(Self {
- r: read_word(r)?,
- g: read_word(r)?,
- b: read_word(r)?,
- })
- }
-}
-impl P2 {
- #[inline]
- pub fn write(&self, w: &mut impl Write) -> Result<()> {
- write_word(w, self.x as i16)?;
- write_word(w, self.y as i16)?;
- Ok(())
- }
-
- #[inline]
- pub fn read(r: &mut impl Read) -> Result<P2> {
- Ok(Self {
- x: read_word(r)? as i32,
- y: read_word(r)? as i32,
- })
- }
-}
-
-impl Block {
- pub fn write(&self, w: &mut impl Write) -> Result<()> {
- match self {
- Block::Split(a, b) => {
- w.write_all(&[0])?;
- a.write(w)?;
- b.write(w)?;
- }
- Block::Lit(pixels) => {
- w.write_all(&[1])?;
- for p in pixels {
- p.write(w)?;
- }
- }
- Block::Ref(k) => {
- w.write_all(&[2])?;
- k.pos_off.write(w)?;
- k.color_off.write_full(w)?;
- }
- }
- Ok(())
- }
- pub fn read(r: &mut impl Read, view: View) -> Result<Block> {
- match read_byte(r)? {
- 0 => {
- let [av, bv] = split(view);
- Ok(Block::Split(
- box Block::read(r, av)?,
- box Block::read(r, bv)?,
- ))
- }
- 1 => {
- let mut px = vec![];
- for _ in 0..view.size().area() {
- px.push(Pixel::read(r)?)
- }
- Ok(Block::Lit(px))
- }
- 2 => Ok(Block::Ref(Ref {
- pos_off: P2::read(r)?,
- color_off: Pixel::read_full(r)?,
- })),
- _ => Err(std::io::Error::other("unknown block variant")),
- }
- }
-}
-
-#[inline]
-fn read_byte(r: &mut impl Read) -> Result<u8> {
- let mut buf = [0u8];
- r.read_exact(&mut buf)?;
- Ok(buf[0])
-}
-#[inline]
-fn write_word(w: &mut impl Write, v: i16) -> Result<()> {
- w.write_all(&[(v & 0xff) as u8, (v >> 8) as u8])
-}
-#[inline]
-fn read_word(r: &mut impl Read) -> Result<i16> {
- Ok((read_byte(r)? as u16 | ((read_byte(r)? as u16) << 8)) as i16)
-}
diff --git a/lvc/codec/src/split.rs b/lvc/codec/src/split.rs
deleted file mode 100644
index c17179e..0000000
--- a/lvc/codec/src/split.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-use crate::{View, P2};
-
-pub fn split(view: View) -> [View; 2] {
- let s = view.size();
- if s.x > s.y {
- let mid_x = (view.a.x + view.b.x) / 2;
- [
- View {
- a: view.a,
- b: P2 {
- x: mid_x,
- y: view.b.y,
- },
- },
- View {
- a: P2 {
- x: mid_x,
- y: view.a.y,
- },
- b: view.b,
- },
- ]
- } else {
- let mid_y = (view.a.y + view.b.y) / 2;
- [
- View {
- a: view.a,
- b: P2 {
- x: view.b.x,
- y: mid_y,
- },
- },
- View {
- a: P2 {
- x: view.a.x,
- y: mid_y,
- },
- b: view.b,
- },
- ]
- }
-}