add more RLE variants that barely help

This commit is contained in:
Crispy 2025-06-17 16:02:34 +02:00
parent d44e5d9c55
commit c5f7c245d2
3 changed files with 172 additions and 18 deletions

View file

@ -237,6 +237,41 @@ pub fn rle_vertical(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) ->
frame 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 { pub fn rle_vertical_ext(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
let mut x = 0; let mut x = 0;
let mut y = 0; let mut y = 0;
@ -272,6 +307,48 @@ pub fn rle_vertical_ext(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize)
frame 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 { pub fn rle_vertical_16(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
let mut x = 0; let mut x = 0;
let mut y = 0; let mut y = 0;
@ -301,7 +378,7 @@ pub fn rle_vertical_16(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize)
pub fn tree_16(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame { pub fn tree_16(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
let fg = 1; let fg = 1;
let mut frame = [[1-fg; HEIGHT]; WIDTH]; let mut frame = [[1 - fg; HEIGHT]; WIDTH];
let top_node = ((encoded[0] as u16) << 8) | encoded[1] as u16; let top_node = ((encoded[0] as u16) << 8) | encoded[1] as u16;
let mut i = 2; let mut i = 2;
let mut nodes = [0u16; 16]; let mut nodes = [0u16; 16];
@ -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; let node = ((encoded[i] as u16) << 8) | encoded[i + 1] as u16;
i += 2; i += 2;
nodes[index] = node; 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;
// }
// }
} }
} }
} }

View file

@ -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 { pub fn rle_horizontal(_prev_frame: &Frame, frame: &Frame) -> EncodedFrame {
let mut pixels = Vec::new(); let mut pixels = Vec::new();
for y in 0..HEIGHT { 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 { pub fn rle_vertical_16(_prev_frame: &Frame, frame: &Frame) -> EncodedFrame {
let mut data = Vec::new(); let mut data = Vec::new();
let mut last_pixel = 0; let mut last_pixel = 0;

View file

@ -11,15 +11,17 @@ pub use util::*;
const INSPECT_ENC: bool = false; const INSPECT_ENC: bool = false;
const INSPECT_DEC: bool = false; const INSPECT_DEC: bool = false;
const MAX_ERROR: usize = 0; // max wrong pixels 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] = &[ const LOSSLESS_ENCODINGS: &[FrameEncoder] = &[
enc::rle_horizontal, enc::rle_horizontal,
enc::rle_horizontal_ext,
enc::rle_vertical, enc::rle_vertical,
enc::rle_vertical_ext, enc::rle_vertical_ext,
enc::rle_vertical_var,
enc::rle_vertical_16, enc::rle_vertical_16,
// enc::rle_diff_horizontal, enc::rle_diff_horizontal,
// enc::rle_diff_vertical, enc::rle_diff_vertical,
// enc::bg_strips_horizontal_16, // only works for the tiny display // enc::bg_strips_horizontal_16, // only works for the tiny display
enc::bg_strips_horizontal_24, // intended for the 240x320 display enc::bg_strips_horizontal_24, // intended for the 240x320 display
// enc::tree_16,// turns out to be useless // 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 decoded = decode(&last_frame, &encoded.data, &mut 0);
let error = frame_error(frame, &decoded); 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 { if error <= MAX_ERROR {
options.push(encoded); options.push(encoded);
} else { } else {
@ -172,8 +168,10 @@ enum Encoding {
FillBlack, FillBlack,
FillWhite, FillWhite,
RLEHorizontal, RLEHorizontal,
RLEHorizontalExt,
RLEVertical, RLEVertical,
RLEVerticalExt, RLEVerticalExt,
RLEVerticalVar,
RLEVertical16, RLEVertical16,
RLEDiffHorizontal, RLEDiffHorizontal,
RLEDiffVertical, RLEDiffVertical,
@ -198,8 +196,10 @@ fn get_matching_decoder(encoding: Encoding) -> FrameDecoder {
Encoding::FillWhite => dec::fill_white, Encoding::FillWhite => dec::fill_white,
Encoding::FillBlack => dec::fill_black, Encoding::FillBlack => dec::fill_black,
Encoding::RLEHorizontal => dec::rle_horizontal, Encoding::RLEHorizontal => dec::rle_horizontal,
Encoding::RLEHorizontalExt => dec::rle_horizontal_ext,
Encoding::RLEVertical => dec::rle_vertical, Encoding::RLEVertical => dec::rle_vertical,
Encoding::RLEVerticalExt => dec::rle_vertical_ext, Encoding::RLEVerticalExt => dec::rle_vertical_ext,
Encoding::RLEVerticalVar => dec::rle_vertical_var,
Encoding::RLEVertical16 => dec::rle_vertical_16, Encoding::RLEVertical16 => dec::rle_vertical_16,
Encoding::RLEDiffHorizontal => dec::rle_diff_horizontal, Encoding::RLEDiffHorizontal => dec::rle_diff_horizontal,
Encoding::RLEDiffVertical => dec::rle_diff_vertical, Encoding::RLEDiffVertical => dec::rle_diff_vertical,