diff --git a/encoder/src/dec.rs b/encoder/src/dec.rs index 5c298dc..32ca51c 100644 --- a/encoder/src/dec.rs +++ b/encoder/src/dec.rs @@ -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 } diff --git a/encoder/src/enc.rs b/encoder/src/enc.rs index 866adeb..79741dc 100644 --- a/encoder/src/enc.rs +++ b/encoder/src/enc.rs @@ -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, diff --git a/encoder/src/main.rs b/encoder/src/main.rs index 3fb5695..e69095a 100644 --- a/encoder/src/main.rs +++ b/encoder/src/main.rs @@ -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!(), diff --git a/pico_decoder/src/main.c b/pico_decoder/src/main.c index 12a8bf2..0e7eeb6 100644 --- a/pico_decoder/src/main.c +++ b/pico_decoder/src/main.c @@ -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();