add some more compression variations

This commit is contained in:
Crispy 2025-06-17 03:06:02 +02:00
parent 62ee8a6efa
commit a1bcf7d90b
4 changed files with 168 additions and 54 deletions

View file

@ -51,6 +51,57 @@ pub fn cell_diff_4_vertical(prev_frame: &Frame, encoded: &[u8], reader: &mut usi
frame
}
pub fn cell_diff_8_vertical_big(prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
const CELLS_X: usize = WIDTH / 8;
const CELLS_Y: usize = HEIGHT / 8;
let mut modified_cells = [[false; CELLS_Y]; CELLS_X];
let (mut cell_runs, modified_cells_flat) =
rle_255_decode(&unpack_nybbles(encoded), CELLS_X * CELLS_Y);
if cell_runs % 2 == 1 {
cell_runs += 1;
}
*reader += cell_runs / 2;
let encoded = &encoded[(cell_runs / 2)..];
let mut changed_cell_count = 0;
let mut i = 0;
for cellx in 0..CELLS_X {
for celly in 0..CELLS_Y {
let cell = modified_cells_flat[i] == 1;
modified_cells[cellx][celly] = cell;
if cell {
changed_cell_count += 1;
}
i += 1;
}
}
let mut frame = *prev_frame;
let changed_pixel_count = changed_cell_count * 8 * 8;
let (runs, new_pixels) = rle_255_decode(encoded, changed_pixel_count);
*reader += runs;
let mut index = 0;
for x in 0..WIDTH {
for y in 0..HEIGHT {
let cellx = x / 8;
let celly = y / 8;
let is_changed = modified_cells[cellx][celly];
if is_changed {
frame[x][y] = new_pixels[index];
index += 1;
}
}
}
frame
}
pub fn cell_diff_8_vertical(prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
let bitmap = {
*reader += 3;
@ -83,7 +134,7 @@ pub fn cell_diff_8_vertical(prev_frame: &Frame, encoded: &[u8], reader: &mut usi
frame
}
pub fn bg_strips_horizontal16(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
pub fn bg_strips_horizontal_16(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
*reader += 1;
let bg = encoded[0] >> 7;
let fg = 1 - bg;
@ -104,7 +155,7 @@ pub fn bg_strips_horizontal16(_prev_frame: &Frame, encoded: &[u8], reader: &mut
frame
}
pub fn bg_strips_horizontal24(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
pub fn bg_strips_horizontal_24(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
*reader += 2;
let bg = encoded[0] >> 7;
let fg = 1 - bg;
@ -221,6 +272,34 @@ pub fn rle_vertical_ext(_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 y = 0;
let mut color = 0;
let mut i = 0;
let mut frame = FRAME_0;
while x < WIDTH {
let upper = encoded[i] as u16;
let lower = encoded[i+1] as u16;
i += 2;
let run = (upper<<8) | lower;
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 fill_white(_prev_frame: &Frame, _encoded: &[u8], _reader: &mut usize) -> Frame {
FRAME_1
}

View file

@ -53,58 +53,58 @@ pub fn cell_diff_4_vertical(prev_frame: &Frame, frame: &Frame, loss: usize) -> E
}
}
// pub fn cell_diff_4_vertical_large(prev_frame: &Frame, frame: &Frame, loss: usize) -> EncodedFrame {
// let loss = loss / 4;
// const CELLS_X: usize = WIDTH / 4;
// const CELLS_Y: usize = HEIGHT / 4;
pub fn cell_diff_8_vertical_big(prev_frame: &Frame, frame: &Frame, loss: usize) -> EncodedFrame {
let loss = loss / 8;
const CELLS_X: usize = WIDTH / 8;
const CELLS_Y: usize = HEIGHT / 8;
// let mut modified_cells = [[0; CELLS_Y]; CELLS_X];
let mut modified_cells = [[0; CELLS_Y]; CELLS_X];
// for cellx in 0..CELLS_X {
// for celly in 0..CELLS_Y {
// let mut changed = 0;
// for dx in 0..4 {
// for dy in 0..4 {
// let x = cellx * 4 + dx;
// let y = celly * 4 + dy;
// let pixel = frame[x][y];
for cellx in 0..CELLS_X {
for celly in 0..CELLS_Y {
let mut changed = 0;
for dx in 0..8 {
for dy in 0..8 {
let x = cellx * 8 + dx;
let y = celly * 8 + dy;
let pixel = frame[x][y];
// if pixel != prev_frame[x][y] {
// changed += 1;
// }
// }
// }
// if changed > loss {
// modified_cells[cellx][celly] = 1;
// }
// }
// }
// let mut changed_pixels = Vec::new();
// for x in 0..WIDTH {
// for y in 0..HEIGHT {
// let cellx = x / 4;
// let celly = y / 4;
if pixel != prev_frame[x][y] {
changed += 1;
}
}
}
if changed > loss {
modified_cells[cellx][celly] = 1;
}
}
}
let mut changed_pixels = Vec::new();
for x in 0..WIDTH {
for y in 0..HEIGHT {
let cellx = x / 8;
let celly = y / 8;
// if modified_cells[cellx][celly] != 0 {
// changed_pixels.push(frame[x][y]);
// }
// }
// }
// let mut modified_cells_flat = Vec::new();
// for x in 0..CELLS_X {
// for y in 0..CELLS_Y {
// modified_cells_flat.push(modified_cells[x][y]);
// }
// }
// let mut data = Vec::new();
// data.extend_from_slice(&pack_nybbles(rle_encode(&modified_cells_flat, 15)));
// data.extend_from_slice(&rle_255_encode(&changed_pixels));
if modified_cells[cellx][celly] != 0 {
changed_pixels.push(frame[x][y]);
}
}
}
let mut modified_cells_flat = Vec::new();
for x in 0..CELLS_X {
for y in 0..CELLS_Y {
modified_cells_flat.push(modified_cells[x][y]);
}
}
let mut data = Vec::new();
data.extend_from_slice(&pack_nybbles(rle_encode(&modified_cells_flat, 15)));
data.extend_from_slice(&rle_255_encode(&changed_pixels));
// EncodedFrame {
// encoding: Encoding::CellDiff4VV_large,
// data,
// }
// }
EncodedFrame {
encoding: Encoding::CellDiff8VBig,
data,
}
}
pub fn cell_diff_8_vertical(prev_frame: &Frame, frame: &Frame, loss: usize) -> EncodedFrame {
const CELLS_X: usize = WIDTH / 8;
@ -348,6 +348,37 @@ pub fn rle_vertical_ext(_prev_frame: &Frame, frame: &Frame) -> EncodedFrame {
}
}
pub fn rle_vertical_16(_prev_frame: &Frame, frame: &Frame) -> EncodedFrame {
let mut data = Vec::new();
let mut last_pixel = 0;
let mut run: u16 = 0;
for x in 0..WIDTH {
for y in 0..HEIGHT {
let pixel = frame[x][y];
if pixel != last_pixel || run == 0xffff {
data.push((run >> 8) as u8);
data.push((run & 0xff) as u8);
if run == 0xffff && pixel == last_pixel {
// inserting dummy run because we ran out of max len
data.push(0);
data.push(0);
}
run = 1;
} else {
run += 1;
}
last_pixel = pixel;
}
}
data.push((run >> 8) as u8);
data.push((run & 0xff) as u8);
EncodedFrame {
encoding: Encoding::RLEVertical16,
data,
}
}
pub fn fill_white(_prev_frame: &Frame, _frame: &Frame, _loss: usize) -> EncodedFrame {
EncodedFrame {
encoding: Encoding::FillWhite,

View file

@ -17,6 +17,7 @@ const LOSSLESS_ENCODINGS: &[FrameEncoder] = &[
enc::rle_horizontal,
enc::rle_vertical,
enc::rle_vertical_ext,
enc::rle_vertical_16,
// enc::rle_diff_horizontal,
// enc::rle_diff_vertical,
// enc::bg_strips_horizontal_16, // only works for the tiny display
@ -27,7 +28,8 @@ const LOSSY_ENCODINGS: &[FrameEncoderLossy] = &[
enc::fill_black,
// todo: adapt for big display
// enc::cell_diff_8_vertical,
// enc::cell_diff_4_vertical,
enc::cell_diff_4_vertical,
enc::cell_diff_8_vertical_big,
];
fn main() {
@ -166,6 +168,7 @@ enum Encoding {
RLEHorizontal,
RLEVertical,
RLEVerticalExt,
RLEVertical16,
RLEDiffHorizontal,
RLEDiffVertical,
BGStripsH16,
@ -175,6 +178,7 @@ enum Encoding {
// DrawCommands,
// CellDiff8H,
CellDiff8V,
CellDiff8VBig,
// CellDiff4HH,
// CellDiff4HV,
// CellDiff4VH,
@ -189,15 +193,17 @@ fn get_matching_decoder(encoding: Encoding) -> FrameDecoder {
Encoding::RLEHorizontal => dec::rle_horizontal,
Encoding::RLEVertical => dec::rle_vertical,
Encoding::RLEVerticalExt => dec::rle_vertical_ext,
Encoding::RLEVertical16 => dec::rle_vertical_16,
Encoding::RLEDiffHorizontal => dec::rle_diff_horizontal,
Encoding::RLEDiffVertical => dec::rle_diff_vertical,
Encoding::BGStripsH16 => dec::bg_strips_horizontal16,
Encoding::BGStripsH24 => dec::bg_strips_horizontal24,
Encoding::BGStripsH16 => dec::bg_strips_horizontal_16,
Encoding::BGStripsH24 => dec::bg_strips_horizontal_24,
// Encoding::BGStripsV => todo!(),
// Encoding::QuadTree => todo!(),
// Encoding::DrawCommands => todo!(),
// Encoding::CellDiff8H => todo!(),
Encoding::CellDiff8V => dec::cell_diff_8_vertical,
Encoding::CellDiff8VBig => dec::cell_diff_8_vertical_big,
// Encoding::CellDiff4HH => todo!(),
// Encoding::CellDiff4HV => todo!(),
// Encoding::CellDiff4VH => todo!(),

View file

@ -75,9 +75,7 @@ void draw_num(u16 x, u16 y, u32 num) {
int main() {
gpio_init(PICO_DEFAULT_LED_PIN);
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
gpio_put(PICO_DEFAULT_LED_PIN, 1);
tft_init_display(100 * 1000 * 1000); // max is 62.5MHz
// tft_fill(0);
while (!error) {
decode_next_frame();