add RLEVerticalExt (16 bit run length support)

This commit is contained in:
Crispy 2025-06-16 23:46:01 +02:00
parent 90f648e0b0
commit 62ee8a6efa
8 changed files with 77689 additions and 106875 deletions

View file

@ -4,7 +4,8 @@
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/../ch32v003fun/ch32v003fun"
"${workspaceFolder}/../ch32v003fun/ch32v003fun",
"${workspaceFolder}/../pico-sdk/**"
],
"defines": [],
"compilerPath": "/usr/bin/clang",

View file

@ -1,6 +1,6 @@
use crate::*;
pub fn cell_diff_4_vertical_small(prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
pub fn cell_diff_4_vertical(prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
const CELLS_X: usize = WIDTH / 4;
const CELLS_Y: usize = HEIGHT / 4;
@ -126,7 +126,6 @@ pub fn bg_strips_horizontal24(_prev_frame: &Frame, encoded: &[u8], reader: &mut
frame
}
pub fn rle_diff_horizontal(prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
let (runs, decoded) = rle_255_decode(encoded, FRAME_SIZE);
*reader += runs;
@ -187,6 +186,41 @@ pub fn rle_vertical(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) ->
frame
}
pub fn rle_vertical_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 x < WIDTH {
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;
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

@ -1,6 +1,6 @@
use crate::*;
pub fn cell_diff_4_vertical_small(prev_frame: &Frame, frame: &Frame, loss: usize) -> EncodedFrame {
pub fn cell_diff_4_vertical(prev_frame: &Frame, frame: &Frame, loss: usize) -> EncodedFrame {
let loss = loss / 4;
const CELLS_X: usize = WIDTH / 4;
const CELLS_Y: usize = HEIGHT / 4;
@ -48,7 +48,7 @@ pub fn cell_diff_4_vertical_small(prev_frame: &Frame, frame: &Frame, loss: usize
data.extend_from_slice(&rle_255_encode(&changed_pixels));
EncodedFrame {
encoding: Encoding::CellDiff4VV_small,
encoding: Encoding::CellDiff4VV,
data,
}
}
@ -306,6 +306,48 @@ pub fn rle_vertical(_prev_frame: &Frame, frame: &Frame) -> EncodedFrame {
}
}
pub fn rle_vertical_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<u8>, run| {
if run < 256 {
data.push(run as u8);
} else {
// double zero to mark 16 bit run length
// if data.last() != Some(&0) {
// }
data.push(0);
data.push(0);
data.push((run >> 8) as u8);
data.push((run & 0xff) as u8);
}
};
for x in 0..WIDTH {
for y in 0..HEIGHT {
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::RLEVerticalExt,
data,
}
}
pub fn fill_white(_prev_frame: &Frame, _frame: &Frame, _loss: usize) -> EncodedFrame {
EncodedFrame {
encoding: Encoding::FillWhite,

View file

@ -16,17 +16,18 @@ const MAX_LOSS: usize = 16; // highest "loss" value tried for all lossy encoding
const LOSSLESS_ENCODINGS: &[FrameEncoder] = &[
enc::rle_horizontal,
enc::rle_vertical,
enc::rle_diff_horizontal,
enc::rle_diff_vertical,
enc::rle_vertical_ext,
// 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::bg_strips_horizontal_24, // intended for the 240x320 display
];
const LOSSY_ENCODINGS: &[FrameEncoderLossy] = &[
enc::fill_white,
enc::fill_black,
// todo: adapt these for big display
// todo: adapt for big display
// enc::cell_diff_8_vertical,
// enc::cell_diff_4_vertical_small,
// enc::cell_diff_4_vertical,
];
fn main() {
@ -80,6 +81,7 @@ fn main() {
}
export_string += "} Encoding_t;\n\n";
export_string += "const unsigned char video[] = {";
// export_string += &format!("const unsigned char video[{}] = {{", encoded.len());
let mut i = 99;
for byte in encoded {
if i > 15 {
@ -108,7 +110,9 @@ fn encode(frames: &[Frame]) -> Vec<u8> {
options.push(encoded);
} else {
dbg!(&encoded);
eprintln!("{:?}, error: {error}, frame: {_i}", encoded.encoding);
println!("{:?}, error: {error}, frame: {_i}", encoded.encoding);
println!("original | decoded");
render_images(&frame, &decoded);
panic!("error in lossless compression");
}
@ -161,6 +165,7 @@ enum Encoding {
FillWhite,
RLEHorizontal,
RLEVertical,
RLEVerticalExt,
RLEDiffHorizontal,
RLEDiffVertical,
BGStripsH16,
@ -173,7 +178,7 @@ enum Encoding {
// CellDiff4HH,
// CellDiff4HV,
// CellDiff4VH,
CellDiff4VV_small,
CellDiff4VV,
// CellDiff4VV_large,
}
@ -183,6 +188,7 @@ fn get_matching_decoder(encoding: Encoding) -> FrameDecoder {
Encoding::FillBlack => dec::fill_black,
Encoding::RLEHorizontal => dec::rle_horizontal,
Encoding::RLEVertical => dec::rle_vertical,
Encoding::RLEVerticalExt => dec::rle_vertical_ext,
Encoding::RLEDiffHorizontal => dec::rle_diff_horizontal,
Encoding::RLEDiffVertical => dec::rle_diff_vertical,
Encoding::BGStripsH16 => dec::bg_strips_horizontal16,
@ -195,8 +201,7 @@ fn get_matching_decoder(encoding: Encoding) -> FrameDecoder {
// Encoding::CellDiff4HH => todo!(),
// Encoding::CellDiff4HV => todo!(),
// Encoding::CellDiff4VH => todo!(),
Encoding::CellDiff4VV_small => dec::cell_diff_4_vertical_small,
// Encoding::CellDiff4VV_large => dec::cell_diff_4_vertical_large,
Encoding::CellDiff4VV => dec::cell_diff_4_vertical,
}
}

View file

@ -1,121 +0,0 @@
BGStripsH24, error: 868, frame: 14
| ██████| ██████|
| ██████| ██████|
| ██████| ██████|
| ██████| ██████|
| ██████| ██████|
| ██████| ██████|
| ██████| ██████|
| ██████| ██████|
| ██████| ██████|
| ██████| ██████|
| ██████| ██████|
| ██████| ██████|
| ██████| ██████|
| ▀█████| ▀█████|
| █████| █████|
| █████| █████|
| █████| █████|
| █████| █████|
| █████| █████|
| █████| █████|
| █████| █████|
| █████| █████|
| █████| █████|
| █████| █████|
| ██████| ██████|
| ██████| ██████|
| ██████| ██████|
| ██████| ██████|
| ██████| ██████|
| ██████| ██████|
| ███████| ███████|
| ███████| ███████|
| ███████| ███████|
| ███████| ███████|
| ███████| ███████|
| ███████| ███████|
| ███████| ███████|
| ▄███████| ▄███████|
| ████████| ████████|
| ████████| ████████|
| ████████| ████████|
| ████████| ████████|
| ████████| ████████|
| ████████| ████████|
| ▄████████| ▄████████|
| █████████| █████████|
| █████████| █████████|
| █████████| █████████|
| █████████| █████████|
| ██████████| ██████████|
| ██████████| ██████████|
| ███████████| ███████████|
| ███████████| ███████████|
| ▄███████████| ▄███████████|
| ████████████| ████████████|
| ▄████████████| ▄████████████|
| █████████████| █████████████|
| ▄█████████████| ▄█████████████|
| ██████████████| ██████████████|
| ▄██████████████| ▄██████████████|
| ███████████████| ███████████████|
| ▄███████████████| ▄███████████████|
| ████████████████| ████████████████|
| ▄████████████████| ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀|
| █████████████████| |
| ▄█████████████████| |
| ██████████████████| |
| ▄██████████████████| |
| ███████████████████| |
| ███████████████████| |
| ███████████████████| |
| ███████████████████| |
| ▀██████████████████| |
| ██████████████████| |
| ██████████████████| |
| ██████████████████| |
| ██████████████████| |
| ██████████████████| |
| ██████████████████| |
| █ ██████████████████| |
| ██ ██████████████████| |
| ███ ██████████████████| |
| ▀▀█▄ ██████████████████| |
| ██████████████████| |
| ▀█████████████████| |
| ▀██████████████| |
| ▀▀██████████| |
| ▀▀██████| |
| ▀▀██| |
| ▀| |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |

View file

@ -1,6 +1,7 @@
build_thing:
cmake -B bin -DPICO_SDK_PATH=../../pico-sdk
# -DCMAKE_CXX_FLAGS=-Oz
make -j8 -C bin
# then manually copy bin/thing.uf2 to the pico

File diff suppressed because it is too large Load diff

View file

@ -75,21 +75,21 @@ 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();
draw_num(30,2, reader);
draw_num(15, 8, video[reader]);
refresh_screen();
sleep_ms(100);
// sleep_ms(100);
if (reader >= sizeof(video))
reader = 0;
error = true;
// reader = 0;
}
gpio_put(PICO_DEFAULT_LED_PIN, 1);
draw_num(30, 2, reader);
draw_num(15, 8, video[reader]);
draw_num(30, 2, reader-1);
draw_num(15, 8, video[reader-1]);
draw_num(30, 16, last_frame_start);
draw_num(15, 22, last_frame_type);
refresh_screen();
@ -106,7 +106,7 @@ void refresh_screen() {
DC_D;
u32 pixel_count = AREA;
const u8 pixels[2] = {0, 176};
const u8 pixels[2] = {0, 255};
while (pixel_count--) {
u8 p = pixels[frame[pixel_count]];
@ -135,14 +135,14 @@ void fill_frame(u8 color) {
void set_pixel(u16 x, u16 y, u8 color)
{
if (x >= WIDTH || y >= HEIGHT){
while (1){
gpio_put(PICO_DEFAULT_LED_PIN, 1);
sleep_ms(50);
gpio_put(PICO_DEFAULT_LED_PIN, 0);
sleep_ms(50);
}
}
// if (x >= WIDTH || y >= HEIGHT){
// while (1){
// gpio_put(PICO_DEFAULT_LED_PIN, 1);
// sleep_ms(50);
// gpio_put(PICO_DEFAULT_LED_PIN, 0);
// sleep_ms(50);
// }
// }
x = (WIDTH-1) - x;
const u32 index = x * HEIGHT + y;
frame[index] = color;
@ -150,6 +150,7 @@ void set_pixel(u16 x, u16 y, u8 color)
void rle_horizontal();
void rle_vertical();
void rle_vertical_ext();
void bg_strips_h();
void cell_diff_4vv();
@ -179,13 +180,18 @@ void decode_next_frame()
rle_vertical();
break;
#endif
#ifdef USE_RLEVerticalExt
case Encoding_RLEVerticalExt:
rle_vertical_ext();
break;
#endif
#ifdef USE_BGStripsH24
case Encoding_BGStripsH24:
bg_strips_h();
break;
#endif
#ifdef USE_CellDiff4VV_small
case Encoding_CellDiff4VV_small:
#ifdef USE_CellDiff4VV
case Encoding_CellDiff4VV:
cell_diff_4vv();
break;
#endif
@ -219,8 +225,7 @@ void rle_horizontal()
#endif
#ifdef USE_RLEVertical
void rle_vertical()
{
void rle_vertical() {
u16 x = 0;
u16 y = 0;
u8 color = 0;
@ -241,9 +246,39 @@ void rle_vertical()
}
#endif
#ifdef USE_RLEVerticalExt
void rle_vertical_ext() {
u16 x = 0;
u16 y = 0;
u8 color = 0;
while (x < WIDTH) {
u8 byte = next_byte();
u16 run = byte;
if (byte == 0 && video[reader] == 0) {
// 16 bit run length
u16 upper = video[reader + 1] << 8;
if (upper) {
u16 lower = video[reader + 2];
run = upper | lower;
reader += 3;
}
}
for (u16 i = 0; i < run; i++) {
set_pixel(x, y, color);
y += 1;
if (y == HEIGHT) {
y = 0;
x += 1;
}
}
color = !color;
}
}
#endif
#ifdef USE_BGStripsH24
void bg_strips_h()
{
void bg_strips_h() {
u8 head = next_byte();
u8 bg = head >> 7;
u8 fg = 1 - bg;
@ -262,7 +297,7 @@ void bg_strips_h()
}
#endif
#ifdef USE_CellDiff4VV_small
#ifdef USE_CellDiff4VV
void cell_diff_4vv() {
const u32 cells_x = WIDTH/4;
const u32 cells_y = HEIGHT/4;