add more RLE variants that barely help
This commit is contained in:
parent
d44e5d9c55
commit
c5f7c245d2
3 changed files with 172 additions and 18 deletions
|
@ -237,6 +237,41 @@ pub fn rle_vertical(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) ->
|
|||
frame
|
||||
}
|
||||
|
||||
pub fn rle_horizontal_ext(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
|
||||
let mut x = 0;
|
||||
let mut y = 0;
|
||||
let mut color = 0;
|
||||
let mut i = 0;
|
||||
let mut frame = FRAME_0;
|
||||
|
||||
while y < HEIGHT {
|
||||
let byte = encoded[i];
|
||||
i += 1;
|
||||
|
||||
let mut run = byte as u16;
|
||||
if byte == 0 && encoded[i] == 0 {
|
||||
// 16 bit run length
|
||||
let upper = (encoded[i + 1] as u16) << 8;
|
||||
if upper > 0 {
|
||||
let lower = encoded[i + 2] as u16;
|
||||
i += 3;
|
||||
run = upper | lower;
|
||||
}
|
||||
}
|
||||
for _ in 0..run {
|
||||
frame[x][y] = color;
|
||||
x += 1;
|
||||
if x == WIDTH {
|
||||
x = 0;
|
||||
y += 1;
|
||||
}
|
||||
}
|
||||
color = 1 - color;
|
||||
}
|
||||
*reader += i;
|
||||
frame
|
||||
}
|
||||
|
||||
pub fn rle_vertical_ext(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
|
||||
let mut x = 0;
|
||||
let mut y = 0;
|
||||
|
@ -272,6 +307,48 @@ pub fn rle_vertical_ext(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize)
|
|||
frame
|
||||
}
|
||||
|
||||
pub fn rle_vertical_var(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
|
||||
let mut x = 0;
|
||||
let mut y = 0;
|
||||
let mut color = 0;
|
||||
let mut i = 0;
|
||||
let mut frame = FRAME_0;
|
||||
|
||||
while x < WIDTH {
|
||||
let byte = encoded[i];
|
||||
i += 1;
|
||||
|
||||
let run;
|
||||
if byte & 0xC0 == 0x80 {
|
||||
// two-byte mode
|
||||
let upper = (byte & 0x3f) as u32;
|
||||
let lower = encoded[i] as u32;
|
||||
i += 1;
|
||||
run = (upper << 8) | lower;
|
||||
} else if byte & 0xE0 == 0xC0 {
|
||||
// 3-byte mode
|
||||
let upper = (byte & 0x1f) as u32;
|
||||
let mid = encoded[i] as u32;
|
||||
let lower = encoded[i + 1] as u32;
|
||||
i += 2;
|
||||
run = (upper << 16) | (mid << 8) | lower;
|
||||
} else {
|
||||
run = byte as u32;
|
||||
}
|
||||
for _ in 0..run {
|
||||
frame[x][y] = color;
|
||||
y += 1;
|
||||
if y == HEIGHT {
|
||||
y = 0;
|
||||
x += 1;
|
||||
}
|
||||
}
|
||||
color = 1 - color;
|
||||
}
|
||||
*reader += i;
|
||||
frame
|
||||
}
|
||||
|
||||
pub fn rle_vertical_16(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
|
||||
let mut x = 0;
|
||||
let mut y = 0;
|
||||
|
@ -313,14 +390,6 @@ pub fn tree_16(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame
|
|||
let node = ((encoded[i] as u16) << 8) | encoded[i + 1] as u16;
|
||||
i += 2;
|
||||
nodes[index] = node;
|
||||
// temp fill for visualisation:
|
||||
// for px in 0..(WIDTH / 4) {
|
||||
// let x = cx * (WIDTH / 4) + px;
|
||||
// for py in 0..(HEIGHT / 4) {
|
||||
// let y = cy * (HEIGHT / 4) + py;
|
||||
// frame[x][y] = 1;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -280,6 +280,47 @@ pub fn rle_diff_vertical(prev_frame: &Frame, frame: &Frame) -> EncodedFrame {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn rle_horizontal_ext(_prev_frame: &Frame, frame: &Frame) -> EncodedFrame {
|
||||
let mut data = Vec::new();
|
||||
let mut last_pixel = 0;
|
||||
let mut run: u16 = 0;
|
||||
|
||||
let push_run = |data: &mut Vec<u8>, run| {
|
||||
if run < 256 {
|
||||
data.push(run as u8);
|
||||
} else {
|
||||
// double zero to mark 16 bit run length
|
||||
data.push(0);
|
||||
data.push(0);
|
||||
data.push((run >> 8) as u8);
|
||||
data.push((run & 0xff) as u8);
|
||||
}
|
||||
};
|
||||
|
||||
for y in 0..HEIGHT {
|
||||
for x in 0..WIDTH {
|
||||
let pixel = frame[x][y];
|
||||
if pixel != last_pixel || run == 0xffff {
|
||||
push_run(&mut data, run);
|
||||
if run == 0xffff && pixel == last_pixel {
|
||||
// inserting dummy run because we ran out of max len
|
||||
data.push(0);
|
||||
}
|
||||
run = 1;
|
||||
} else {
|
||||
run += 1;
|
||||
}
|
||||
last_pixel = pixel;
|
||||
}
|
||||
}
|
||||
push_run(&mut data, run);
|
||||
EncodedFrame {
|
||||
encoding: Encoding::RLEHorizontalExt,
|
||||
data,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn rle_horizontal(_prev_frame: &Frame, frame: &Frame) -> EncodedFrame {
|
||||
let mut pixels = Vec::new();
|
||||
for y in 0..HEIGHT {
|
||||
|
@ -413,6 +454,50 @@ pub fn rle_vertical_ext(_prev_frame: &Frame, frame: &Frame) -> EncodedFrame {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn rle_vertical_var(_prev_frame: &Frame, frame: &Frame) -> EncodedFrame {
|
||||
// variable bit count
|
||||
// 0xxx xxxx 7 bits <=127
|
||||
// 10xx xxxx xxxx xxxx 14 bits <= 16_383
|
||||
// 110x xxxx xxxx xxxx xxxx xxxx 21 bits <= 2_097_151
|
||||
// no dummy zero-length runs needed, as the max length will not be reachable, even at 1080p resolution
|
||||
let mut data = Vec::new();
|
||||
let mut last_pixel = 0;
|
||||
let mut run: u32 = 0;
|
||||
|
||||
let push_run = |data: &mut Vec<u8>, run| {
|
||||
if run < 0x7f {
|
||||
data.push(run as u8);
|
||||
}else if run < 0x3fff {
|
||||
data.push((run >> 8) as u8 | 0x80);
|
||||
data.push(run as u8);
|
||||
} else {
|
||||
data.push((run >> 16) as u8 | 0xC0);
|
||||
data.push((run >> 8 ) as u8);
|
||||
data.push(run as u8);
|
||||
}
|
||||
};
|
||||
|
||||
for x in 0..WIDTH {
|
||||
for y in 0..HEIGHT {
|
||||
let pixel = frame[x][y];
|
||||
if pixel != last_pixel{
|
||||
push_run(&mut data, run);
|
||||
run = 1;
|
||||
} else {
|
||||
run += 1;
|
||||
}
|
||||
last_pixel = pixel;
|
||||
}
|
||||
}
|
||||
push_run(&mut data, run);
|
||||
EncodedFrame {
|
||||
encoding: Encoding::RLEVerticalVar,
|
||||
data,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rle_vertical_16(_prev_frame: &Frame, frame: &Frame) -> EncodedFrame {
|
||||
let mut data = Vec::new();
|
||||
let mut last_pixel = 0;
|
||||
|
|
|
@ -11,15 +11,17 @@ pub use util::*;
|
|||
const INSPECT_ENC: bool = false;
|
||||
const INSPECT_DEC: bool = false;
|
||||
const MAX_ERROR: usize = 0; // max wrong pixels
|
||||
const MAX_LOSS: usize = 16; // highest "loss" value tried for all lossy encodings
|
||||
const MAX_LOSS: usize = 0; // highest "loss" value tried for all lossy encodings
|
||||
|
||||
const LOSSLESS_ENCODINGS: &[FrameEncoder] = &[
|
||||
enc::rle_horizontal,
|
||||
enc::rle_horizontal_ext,
|
||||
enc::rle_vertical,
|
||||
enc::rle_vertical_ext,
|
||||
enc::rle_vertical_var,
|
||||
enc::rle_vertical_16,
|
||||
// enc::rle_diff_horizontal,
|
||||
// enc::rle_diff_vertical,
|
||||
enc::rle_diff_horizontal,
|
||||
enc::rle_diff_vertical,
|
||||
// enc::bg_strips_horizontal_16, // only works for the tiny display
|
||||
enc::bg_strips_horizontal_24, // intended for the 240x320 display
|
||||
// enc::tree_16,// turns out to be useless
|
||||
|
@ -131,12 +133,6 @@ fn encode(frames: &[Frame]) -> Vec<u8> {
|
|||
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 {
|
||||
|
@ -172,8 +168,10 @@ enum Encoding {
|
|||
FillBlack,
|
||||
FillWhite,
|
||||
RLEHorizontal,
|
||||
RLEHorizontalExt,
|
||||
RLEVertical,
|
||||
RLEVerticalExt,
|
||||
RLEVerticalVar,
|
||||
RLEVertical16,
|
||||
RLEDiffHorizontal,
|
||||
RLEDiffVertical,
|
||||
|
@ -198,8 +196,10 @@ fn get_matching_decoder(encoding: Encoding) -> FrameDecoder {
|
|||
Encoding::FillWhite => dec::fill_white,
|
||||
Encoding::FillBlack => dec::fill_black,
|
||||
Encoding::RLEHorizontal => dec::rle_horizontal,
|
||||
Encoding::RLEHorizontalExt => dec::rle_horizontal_ext,
|
||||
Encoding::RLEVertical => dec::rle_vertical,
|
||||
Encoding::RLEVerticalExt => dec::rle_vertical_ext,
|
||||
Encoding::RLEVerticalVar => dec::rle_vertical_var,
|
||||
Encoding::RLEVertical16 => dec::rle_vertical_16,
|
||||
Encoding::RLEDiffHorizontal => dec::rle_diff_horizontal,
|
||||
Encoding::RLEDiffVertical => dec::rle_diff_vertical,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue