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 {
self.process_start = Instant::now();
Some(Frame::read(self.params.width, self.params.height, stdin()).unwrap())
}
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) -> 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>,
}
#[derive(Debug, Clone, Copy)]
pub struct Pixel {
pub r: T,
pub g: T,
pub b: T,
}
pub type EPixel = Pixel;
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 {
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;
#[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 for Frame {
type Output = Pixel;
#[inline]
fn index(&self, Vec2 { x, y }: UVec2) -> &Self::Output {
&self.pixels[x + y * self.width]
}
}
impl IndexMut for Frame {
#[inline]
fn index_mut(&mut self, Vec2 { x, y }: UVec2) -> &mut Self::Output {
&mut self.pixels[x + y * self.width]
}
}
impl Pixel {
pub const BLACK: Pixel = Pixel { r: 0, g: 0, b: 0 };
}