lossy compression
This commit is contained in:
parent
242724d7fd
commit
8bfeb6d2f3
4 changed files with 194 additions and 37 deletions
|
@ -8,13 +8,13 @@ pub use util::*;
|
|||
|
||||
const INSPECT_ENC: bool = false;
|
||||
const INSPECT_DEC: bool = false;
|
||||
const MAX_ERROR: usize = 0;
|
||||
const MAX_ERROR: usize = 4; // max wrong pixels
|
||||
const MAX_LOSS: usize = 16; // highest "loss" value tried for all lossy encodings
|
||||
|
||||
fn main() {
|
||||
let frames = get_all_frames("../video/frames/");
|
||||
let encoded = encode(&frames);
|
||||
|
||||
// todo print average bytes per frame for each encoding type
|
||||
let mut stats: EnumMap<Encoding, u32> = EnumMap::default();
|
||||
let mut reader = 0;
|
||||
let mut last_frame = FRAME_0;
|
||||
|
@ -49,34 +49,59 @@ fn main() {
|
|||
|
||||
fn encode(frames: &[Frame]) -> Vec<u8> {
|
||||
let mut out = Vec::new();
|
||||
let encodings: Vec<FrameEncoder> = vec![
|
||||
enc::fill_white,
|
||||
enc::fill_black,
|
||||
let lossless_encodings: Vec<FrameEncoder> = vec![
|
||||
enc::rle_horizontal,
|
||||
enc::rle_vertical,
|
||||
enc::rle_diff_horizontal,
|
||||
enc::rle_diff_vertical,
|
||||
enc::bg_strips_horizontal,
|
||||
];
|
||||
let lossy_encodings: Vec<FrameEncoderLossy> = vec![
|
||||
enc::fill_white,
|
||||
enc::fill_black,
|
||||
enc::cell_diff_8_vertical,
|
||||
enc::cell_diff_4_vertical,
|
||||
];
|
||||
|
||||
let mut last_frame = FRAME_0;
|
||||
for (i, frame) in frames.iter().enumerate() {
|
||||
for (_i, frame) in frames.iter().enumerate() {
|
||||
let mut options = Vec::new();
|
||||
for encode in &encodings {
|
||||
for encode in &lossless_encodings {
|
||||
let encoded = encode(&last_frame, frame);
|
||||
let decode = get_matching_decoder(encoded.encoding);
|
||||
let decoded = decode(&last_frame, &encoded.data, &mut 0);
|
||||
let error = frame_error(frame, &decoded);
|
||||
if error <= MAX_ERROR {
|
||||
if error == 0 {
|
||||
options.push(encoded);
|
||||
} else {
|
||||
// dbg!(&encoded);
|
||||
// println!("{:?}, error: {error}, frame: {i}", encoded.encoding);
|
||||
// render_images(&frame, &decoded);
|
||||
// panic!("loss in compression");
|
||||
dbg!(&encoded);
|
||||
println!("{:?}, error: {error}, frame: {_i}", encoded.encoding);
|
||||
render_images(&frame, &decoded);
|
||||
panic!("error in lossless compression");
|
||||
}
|
||||
}
|
||||
for encode in &lossy_encodings {
|
||||
for loss in 0..MAX_LOSS {
|
||||
let encoded = encode(&last_frame, frame, loss);
|
||||
let decode = get_matching_decoder(encoded.encoding);
|
||||
let decoded = decode(&last_frame, &encoded.data, &mut 0);
|
||||
let error = frame_error(frame, &decoded);
|
||||
|
||||
// if error > 0 && loss == 0 {
|
||||
// dbg!(&encoded);
|
||||
// println!("{:?}, error: {error}, frame: {_i}", encoded.encoding);
|
||||
// render_images(&frame, &decoded);
|
||||
// panic!("error in 'loss 0' compression");
|
||||
// }
|
||||
if error < MAX_ERROR {
|
||||
options.push(encoded);
|
||||
} else {
|
||||
// higher loss value will mean more error so can be skipped
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
options.sort_by_key(|b| b.data.len());
|
||||
let best_encoding = options.into_iter().next().unwrap();
|
||||
if INSPECT_ENC {
|
||||
|
@ -99,10 +124,10 @@ fn encode(frames: &[Frame]) -> Vec<u8> {
|
|||
#[derive(Debug, TryFromPrimitive, Enum, Copy, Clone)]
|
||||
#[repr(u8)]
|
||||
enum Encoding {
|
||||
FillWhite,
|
||||
FillBlack,
|
||||
RLEHorizontal,
|
||||
RLEVertical,
|
||||
FillBlack = 0,
|
||||
FillWhite = 1,
|
||||
RLEHorizontal = 2,
|
||||
RLEVertical = 3,
|
||||
RLEDiffHorizontal,
|
||||
RLEDiffVertical,
|
||||
BGStripsH,
|
||||
|
@ -114,7 +139,7 @@ enum Encoding {
|
|||
// CellDiff4HH,
|
||||
// CellDiff4HV,
|
||||
// CellDiff4VH,
|
||||
// CellDiff4VV,
|
||||
CellDiff4VV,
|
||||
}
|
||||
|
||||
fn get_matching_decoder(encoding: Encoding) -> FrameDecoder {
|
||||
|
@ -134,11 +159,12 @@ fn get_matching_decoder(encoding: Encoding) -> FrameDecoder {
|
|||
// Encoding::CellDiff4HH => todo!(),
|
||||
// Encoding::CellDiff4HV => todo!(),
|
||||
// Encoding::CellDiff4VH => todo!(),
|
||||
// Encoding::CellDiff4VV => todo!(),
|
||||
Encoding::CellDiff4VV => dec::cell_diff_4_vertical,
|
||||
}
|
||||
}
|
||||
|
||||
type FrameEncoder = fn(previous_frame: &Frame, new_frame: &Frame) -> EncodedFrame;
|
||||
type FrameEncoderLossy = fn(previous_frame: &Frame, new_frame: &Frame, loss: usize) -> EncodedFrame;
|
||||
type FrameDecoder = fn(previous_frame: &Frame, encoded_bytes: &[u8], reader: &mut usize) -> Frame;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue