From d44e5d9c55bd204721932e13f5eef5e1f5a091ed Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Tue, 17 Jun 2025 15:21:20 +0200 Subject: [PATCH] add 16 wide, 2 deep tree with RLE at the end. turns out to be worse than other algs --- encoder/src/dec.rs | 74 ++++++++++++++++++++++++++++++++++++++++++--- encoder/src/enc.rs | 66 +++++++++++++++++++++++++++++++++++++++- encoder/src/main.rs | 10 +++++- 3 files changed, 144 insertions(+), 6 deletions(-) diff --git a/encoder/src/dec.rs b/encoder/src/dec.rs index 32ca51c..34f8771 100644 --- a/encoder/src/dec.rs +++ b/encoder/src/dec.rs @@ -251,8 +251,8 @@ pub fn rle_vertical_ext(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) 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 upper = (encoded[i + 1] as u16) << 8; + if upper > 0 { let lower = encoded[i + 2] as u16; i += 3; run = upper | lower; @@ -281,10 +281,10 @@ pub fn rle_vertical_16(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) while x < WIDTH { let upper = encoded[i] as u16; - let lower = encoded[i+1] as u16; + let lower = encoded[i + 1] as u16; i += 2; - let run = (upper<<8) | lower; + let run = (upper << 8) | lower; for _ in 0..run { frame[x][y] = color; y += 1; @@ -299,6 +299,72 @@ pub fn rle_vertical_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 mut frame = [[1-fg; HEIGHT]; WIDTH]; + let top_node = ((encoded[0] as u16) << 8) | encoded[1] as u16; + let mut i = 2; + let mut nodes = [0u16; 16]; + for cx in 0..4 { + for cy in 0..4 { + let index = cy * 4 + cx; + let has_node = (top_node & (1 << index)) != 0; + if has_node { + 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; + // } + // } + } + } + } + let mut color = fg; + let mut run = 0; + for cx in 0..4 { + for cy in 0..4 { + let index = cy * 4 + cx; + let node = nodes[index]; + if node != 0 { + for ccx in 0..4 { + for ccy in 0..4 { + let x = cx * (WIDTH / 4) + ccx * (WIDTH / 16); + let y = cy * (HEIGHT / 4) + ccy * (HEIGHT / 16); + + let lower_index = ccy * 4 + ccx; + if node & (1 << lower_index) != 0 { + // leaf node exists, fill from RLE + let mut px = 0; + let mut py = 0; + while px < WIDTH / 16 { + while run == 0 { + run = encoded[i]; + i += 1; + color = 1 - color; + } + run -= 1; + frame[x + px][y + py] = color; + py += 1; + if py == HEIGHT / 16 { + py = 0; + px += 1; + } + } + } + } + } + } + } + } + *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 79741dc..34ce77d 100644 --- a/encoder/src/enc.rs +++ b/encoder/src/enc.rs @@ -293,6 +293,71 @@ pub fn rle_horizontal(_prev_frame: &Frame, frame: &Frame) -> EncodedFrame { } } +/// requires WIDTH and HEIGHT to be multiples of 16 +/// two-level tree with 4x4 branches per level +pub fn tree_16(_prev_frame: &Frame, frame: &Frame) -> EncodedFrame { + let mut top_node: u16 = 0; + let mut second_nodes = Vec::new(); + let mut included_pixels = Vec::new(); + // todo allow using white as bg + let fg = 1; + for cx in 0..4 { + for cy in 0..4 { + let mut any_filled_here = false; + 'a: for px in 0..(WIDTH / 4) { + let x = cx * (WIDTH / 4) + px; + for py in 0..(HEIGHT / 4) { + let y = cy * (HEIGHT / 4) + py; + if frame[x][y] == fg{ + any_filled_here = true; + break 'a; + } + } + } + if any_filled_here { + top_node |= 1 << (cy * 4 + cx); + let mut second_node: u16 = 0; + for ccx in 0..4 { + for ccy in 0..4 { + let mut any_filled_here = false; + let mut node_pixels = Vec::new(); + for px in 0..(WIDTH / 16) { + for py in 0..(HEIGHT / 16) { + let x = cx * (WIDTH / 4) + ccx * (WIDTH / 16) + px; + let y = cy * (HEIGHT / 4) + ccy * (HEIGHT / 16) + py; + if frame[x][y] == fg { + node_pixels.push(fg); + any_filled_here = true; + }else{ + node_pixels.push(1-fg); + } + } + } + if any_filled_here { + second_node |= 1 << (ccy * 4 + ccx); + included_pixels.extend_from_slice(&node_pixels); + } + } + } + second_nodes.push(second_node); + } + } + } + let mut data = Vec::new(); + data.push((top_node >>8) as u8); + data.push(top_node as u8); + for n in second_nodes{ + data.push((n>>8)as u8); + data.push(n as u8); + } + data.extend_from_slice(&rle_255_encode(&included_pixels)); + + EncodedFrame { + encoding: Encoding::Tree16, + data, + } +} + pub fn rle_vertical(_prev_frame: &Frame, frame: &Frame) -> EncodedFrame { let mut pixels = Vec::new(); for x in 0..WIDTH { @@ -348,7 +413,6 @@ 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; diff --git a/encoder/src/main.rs b/encoder/src/main.rs index e69095a..e86f1fa 100644 --- a/encoder/src/main.rs +++ b/encoder/src/main.rs @@ -1,4 +1,4 @@ -use std::{fs::File, io::Write}; +use std::{fs::File, io::{stdout, Write}}; use enum_map::{Enum, EnumMap}; use num_enum::TryFromPrimitive; @@ -22,6 +22,7 @@ const LOSSLESS_ENCODINGS: &[FrameEncoder] = &[ // 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 ]; const LOSSY_ENCODINGS: &[FrameEncoderLossy] = &[ enc::fill_white, @@ -101,7 +102,11 @@ fn main() { fn encode(frames: &[Frame]) -> Vec { let mut out = Vec::new(); let mut last_frame = FRAME_0; + print!("encoding frames"); + let frame_count = frames.len(); for (_i, frame) in frames.iter().enumerate() { + print!("\rencoding frame {_i} of {frame_count}"); + stdout().flush().unwrap(); let mut options = Vec::new(); for encode in LOSSLESS_ENCODINGS.iter() { let encoded = encode(&last_frame, frame); @@ -157,6 +162,7 @@ fn encode(frames: &[Frame]) -> Vec { out.extend_from_slice(&best_encoding); last_frame = *frame; } + println!(); out } @@ -184,6 +190,7 @@ enum Encoding { // CellDiff4VH, CellDiff4VV, // CellDiff4VV_large, + Tree16, } fn get_matching_decoder(encoding: Encoding) -> FrameDecoder { @@ -208,6 +215,7 @@ fn get_matching_decoder(encoding: Encoding) -> FrameDecoder { // Encoding::CellDiff4HV => todo!(), // Encoding::CellDiff4VH => todo!(), Encoding::CellDiff4VV => dec::cell_diff_4_vertical, + Encoding::Tree16 => dec::tree_16, } }