diff --git a/encoder/src/dec.rs b/encoder/src/dec.rs index 34f8771..a93fd4d 100644 --- a/encoder/src/dec.rs +++ b/encoder/src/dec.rs @@ -237,6 +237,41 @@ pub fn rle_vertical(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> 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 { let mut x = 0; let mut y = 0; @@ -272,6 +307,48 @@ pub fn rle_vertical_ext(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) 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 { let mut x = 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 { 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 mut i = 2; 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; 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; - // } - // } } } } diff --git a/encoder/src/enc.rs b/encoder/src/enc.rs index 34ce77d..7f05285 100644 --- a/encoder/src/enc.rs +++ b/encoder/src/enc.rs @@ -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, 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 { let mut pixels = Vec::new(); 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, 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 { let mut data = Vec::new(); let mut last_pixel = 0; diff --git a/encoder/src/main.rs b/encoder/src/main.rs index e86f1fa..117ba84 100644 --- a/encoder/src/main.rs +++ b/encoder/src/main.rs @@ -11,15 +11,17 @@ pub use util::*; const INSPECT_ENC: bool = false; const INSPECT_DEC: bool = false; 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] = &[ enc::rle_horizontal, + enc::rle_horizontal_ext, enc::rle_vertical, enc::rle_vertical_ext, + enc::rle_vertical_var, enc::rle_vertical_16, - // enc::rle_diff_horizontal, - // enc::rle_diff_vertical, + enc::rle_diff_horizontal, + 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 @@ -131,12 +133,6 @@ fn encode(frames: &[Frame]) -> Vec { let decoded = decode(&last_frame, &encoded.data, &mut 0); 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 { options.push(encoded); } else { @@ -172,8 +168,10 @@ enum Encoding { FillBlack, FillWhite, RLEHorizontal, + RLEHorizontalExt, RLEVertical, RLEVerticalExt, + RLEVerticalVar, RLEVertical16, RLEDiffHorizontal, RLEDiffVertical, @@ -198,8 +196,10 @@ fn get_matching_decoder(encoding: Encoding) -> FrameDecoder { Encoding::FillWhite => dec::fill_white, Encoding::FillBlack => dec::fill_black, Encoding::RLEHorizontal => dec::rle_horizontal, + Encoding::RLEHorizontalExt => dec::rle_horizontal_ext, Encoding::RLEVertical => dec::rle_vertical, Encoding::RLEVerticalExt => dec::rle_vertical_ext, + Encoding::RLEVerticalVar => dec::rle_vertical_var, Encoding::RLEVertical16 => dec::rle_vertical_16, Encoding::RLEDiffHorizontal => dec::rle_diff_horizontal, Encoding::RLEDiffVertical => dec::rle_diff_vertical,