add 16 wide, 2 deep tree with RLE at the end. turns out to be worse than other algs

This commit is contained in:
Crispy 2025-06-17 15:21:20 +02:00
parent a1bcf7d90b
commit d44e5d9c55
3 changed files with 144 additions and 6 deletions

View file

@ -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

View file

@ -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;

View file

@ -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<u8> {
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<u8> {
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,
}
}