aboutsummaryrefslogtreecommitdiff
path: root/old/framework
diff options
context:
space:
mode:
Diffstat (limited to 'old/framework')
-rw-r--r--old/framework/Cargo.toml6
-rw-r--r--old/framework/src/common/huffman.rs181
-rw-r--r--old/framework/src/common/mod.rs1
-rw-r--r--old/framework/src/lib.rs153
-rw-r--r--old/framework/src/vector.rs128
5 files changed, 469 insertions, 0 deletions
diff --git a/old/framework/Cargo.toml b/old/framework/Cargo.toml
new file mode 100644
index 0000000..265f119
--- /dev/null
+++ b/old/framework/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "framework"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/old/framework/src/common/huffman.rs b/old/framework/src/common/huffman.rs
new file mode 100644
index 0000000..474cfab
--- /dev/null
+++ b/old/framework/src/common/huffman.rs
@@ -0,0 +1,181 @@
+#[derive(Debug, Clone)]
+enum HT {
+ Branch(Box<HT>, Box<HT>),
+ Terminal(u8),
+}
+
+pub fn encode_huff(buf: &[u8]) -> Vec<u8> {
+ let mut w = BitIO::new(Vec::new());
+ 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();
+ w.buffer
+}
+
+pub fn read_huff(r: Vec<u8>) -> Vec<u8> {
+ 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;
+ let mut buf = Vec::new();
+ 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;
+ }
+ }
+ }
+ buf
+}
+
+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::new(at), Box::new(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) {
+ match self {
+ HT::Branch(a, b) => {
+ w.wbit(false);
+ a.write(w);
+ b.write(w);
+ }
+ HT::Terminal(n) => {
+ w.wbit(true);
+ w.wbyte(*n);
+ }
+ }
+ }
+ pub fn read(r: &mut BitIO) -> Self {
+ match r.rbit() {
+ false => Self::Branch(Box::new(Self::read(r)), Box::new(Self::read(r))),
+ true => Self::Terminal(r.rbyte()),
+ }
+ }
+}
+
+pub struct BitIO {
+ buffer: Vec<u8>,
+ byte: u8,
+ position: usize,
+}
+impl BitIO {
+ pub fn new(inner: Vec<u8>) -> Self {
+ Self {
+ buffer: inner,
+ byte: 0,
+ position: 0,
+ }
+ }
+ #[inline]
+ pub fn wbit(&mut self, b: bool) {
+ self.byte <<= 1;
+ self.byte |= b as u8;
+ self.position += 1;
+ if self.position & 0b111 == 0 {
+ self.buffer.push(self.byte)
+ }
+ }
+ #[inline]
+ pub fn wbyte(&mut self, v: u8) {
+ for i in 0..8 {
+ self.wbit((v & (1 << i)) != 0);
+ }
+ }
+
+ #[inline]
+ pub fn flush(&mut self) {
+ while self.position & 0b111 != 0 {
+ self.wbit(false);
+ }
+ }
+
+ #[inline]
+ pub fn rbit(&mut self) -> bool {
+ if self.position & 0b111 == 0 {
+ self.byte = self.buffer[self.position >> 3];
+ }
+
+ let v = (self.byte & 0b10000000) != 0;
+ self.byte <<= 1;
+ self.position += 1;
+ v
+ }
+
+ #[inline]
+ pub fn rbyte(&mut self) -> u8 {
+ let mut v = 0u8;
+ for i in 0..8 {
+ v |= (self.rbit() as u8) << i;
+ }
+ v
+ }
+}
diff --git a/old/framework/src/common/mod.rs b/old/framework/src/common/mod.rs
new file mode 100644
index 0000000..6f86024
--- /dev/null
+++ b/old/framework/src/common/mod.rs
@@ -0,0 +1 @@
+pub mod huffman;
diff --git a/old/framework/src/lib.rs b/old/framework/src/lib.rs
new file mode 100644
index 0000000..af535c5
--- /dev/null
+++ b/old/framework/src/lib.rs
@@ -0,0 +1,153 @@
+use std::{
+ io::{self, stdin, stdout, Read, Write},
+ ops::{Index, IndexMut},
+ time::Instant,
+};
+use vector::{UVec2, Vec2};
+
+pub mod common;
+pub mod vector;
+
+#[derive(Clone)]
+pub struct CodecParams {
+ pub width: usize,
+ pub height: usize,
+ pub debug: usize,
+ pub mode: CodecMode,
+}
+#[derive(Clone)]
+pub enum CodecMode {
+ Encode,
+ Decode,
+}
+
+pub struct Framework {
+ process_start: Instant,
+ params: CodecParams,
+}
+
+impl Framework {
+ pub fn init() -> (Self, CodecParams) {
+ let width = std::env::var("V_WIDTH").unwrap().parse().unwrap();
+ let height = std::env::var("V_HEIGHT").unwrap().parse().unwrap();
+ let debug = std::env::var("V_DEBUG").unwrap().parse().unwrap();
+ let mode = match std::env::var("V_MODE").unwrap().as_str() {
+ "encode" => CodecMode::Encode,
+ "decode" => CodecMode::Decode,
+ _ => panic!("invalid mode"),
+ };
+ let params = CodecParams {
+ height,
+ width,
+ debug,
+ mode,
+ };
+ (
+ Self {
+ params: params.clone(),
+ process_start: Instant::now(),
+ },
+ params,
+ )
+ }
+
+ pub fn next_frame(&mut self) -> Option<Frame> {
+ let f = Some(Frame::read(self.params.width, self.params.height, stdin()).unwrap());
+ self.next_frame_manual();
+ f
+ }
+ pub fn next_frame_manual(&mut self) {
+ self.process_start = Instant::now();
+ }
+ pub fn encode_done(&mut self, output: &[u8]) {
+ let el = self.process_start.elapsed();
+ eprintln!(
+ "size={}KB ratio={:.02} t={el:?}",
+ output.len() / 1000,
+ (self.params.width * self.params.height * 3) as f32 / output.len() as f32
+ )
+ }
+
+ pub fn next_chunk(&mut self, _buffer: &mut Vec<u8>) -> bool {
+ true
+ }
+ pub fn decode_done(&mut self, output: &Frame) {
+ output.write(stdout()).unwrap();
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct Frame {
+ pub width: usize,
+ pub height: usize,
+ pub pixels: Vec<Pixel<u8>>,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub struct Pixel<T> {
+ pub r: T,
+ pub g: T,
+ pub b: T,
+}
+pub type EPixel = Pixel<u8>;
+
+impl Frame {
+ pub fn new(width: usize, height: usize) -> Self {
+ Self {
+ height,
+ width,
+ pixels: vec![Pixel::BLACK; width * height],
+ }
+ }
+ pub fn read(width: usize, height: usize, mut r: impl Read) -> io::Result<Self> {
+ let mut f = Frame::new(width, height);
+ let p = unsafe {
+ std::slice::from_raw_parts_mut(
+ f.pixels.as_mut_slice().as_mut_ptr() as *mut u8,
+ width * height * 3,
+ )
+ };
+ r.read_exact(p)?;
+ Ok(f)
+ }
+ pub fn write(&self, mut w: impl Write) -> io::Result<()> {
+ let p = unsafe {
+ std::slice::from_raw_parts(
+ self.pixels.as_slice().as_ptr() as *const u8,
+ self.width * self.height * 3,
+ )
+ };
+ w.write_all(p)
+ }
+}
+
+impl Index<(usize, usize)> for Frame {
+ type Output = Pixel<u8>;
+ #[inline]
+ fn index(&self, (x, y): (usize, usize)) -> &Self::Output {
+ &self.pixels[x + y * self.width]
+ }
+}
+impl IndexMut<(usize, usize)> for Frame {
+ #[inline]
+ fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Self::Output {
+ &mut self.pixels[x + y * self.width]
+ }
+}
+impl Index<UVec2> for Frame {
+ type Output = Pixel<u8>;
+ #[inline]
+ fn index(&self, Vec2 { x, y }: UVec2) -> &Self::Output {
+ &self.pixels[x + y * self.width]
+ }
+}
+impl IndexMut<UVec2> for Frame {
+ #[inline]
+ fn index_mut(&mut self, Vec2 { x, y }: UVec2) -> &mut Self::Output {
+ &mut self.pixels[x + y * self.width]
+ }
+}
+
+impl Pixel<u8> {
+ pub const BLACK: Pixel<u8> = Pixel { r: 0, g: 0, b: 0 };
+}
diff --git a/old/framework/src/vector.rs b/old/framework/src/vector.rs
new file mode 100644
index 0000000..5227d04
--- /dev/null
+++ b/old/framework/src/vector.rs
@@ -0,0 +1,128 @@
+pub type UVec2 = Vec2<usize>;
+
+#[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 }
+ }
+}