diff --git a/encoder/src/dec.rs b/encoder/src/dec.rs index 3e73c27..cca9602 100644 --- a/encoder/src/dec.rs +++ b/encoder/src/dec.rs @@ -1,5 +1,45 @@ use crate::*; +pub fn cell_diff_8_horizontal(prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame { + let bitmap = { + *reader += 3; + let mut bitmap = (encoded[0] as u32) << 16; + bitmap |= (encoded[1] as u32) << 8; + bitmap | encoded[2] as u32 + }; + let encoded = &encoded[3..]; + + let mut frame = *prev_frame; + let changed_pixel_count = bitmap.count_ones() as usize * 8 * 8; + let (runs, new_pixels) = rle_255_decode_until(encoded, changed_pixel_count); + *reader += runs; + + let cells_x = WIDTH / 8; + let cells_y = HEIGHT / 8; + let mut index = 0; + + for celly in 0..cells_y { + for cellx in 0..cells_x { + let is_changed = (bitmap >> (cellx + cells_x * celly)) & 1; + if is_changed == 1 { + let pixels = &new_pixels[(index * 8 * 8)..((index + 1) * 8 * 8)]; + let mut i = 0; + for dx in 0..8 { + for dy in 0..8 { + let x = cellx * 8 + dx; + let y = celly * 8 + dy; + frame[x][y] = pixels[i]; + i += 1; + } + } + index += 1; + } + } + } + + frame +} + pub fn bg_strips_horizontal(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame { *reader += 1; let bg = encoded[0] >> 7; diff --git a/encoder/src/enc.rs b/encoder/src/enc.rs index e7e0f92..2c29754 100644 --- a/encoder/src/enc.rs +++ b/encoder/src/enc.rs @@ -1,5 +1,43 @@ use crate::*; +pub fn cell_diff_8_horizontal(prev_frame: &Frame, frame: &Frame) -> EncodedFrame { + let cells_x = WIDTH / 8; + let cells_y = HEIGHT / 8; + let loss = 0; + + let mut bitmap: u32 = 0; + let mut changed_pixels = Vec::new(); + + for celly in 0..cells_y { + for cellx in 0..cells_x { + let mut changed = 0; + let mut cell_contents = Vec::new(); + // todo try encoding the cells in frame space instead of one cell at a time + 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]; + cell_contents.push(pixel); + if pixel != prev_frame[x][y] { + changed += 1; + } + } + } + if changed > loss { + bitmap |= 1 << (cellx + cells_x * celly); + changed_pixels.extend_from_slice(&cell_contents); + } + } + } + let mut data = vec![(bitmap >> 16) as u8, (bitmap >> 8) as u8, bitmap as u8]; + data.extend_from_slice(&rle_255_encode(&changed_pixels)); + EncodedFrame { + encoding: Encoding::CellDiff8H, + data, + } +} + pub fn bg_strips_horizontal(_prev_frame: &Frame, frame: &Frame) -> EncodedFrame { let bg = most_common_pixel(frame); fn pack_strip(x: usize, y: usize, width: usize) -> [u8; 2] { diff --git a/encoder/src/main.rs b/encoder/src/main.rs index daadb9c..60e9e52 100644 --- a/encoder/src/main.rs +++ b/encoder/src/main.rs @@ -8,6 +8,7 @@ pub use util::*; const INSPECT_ENC: bool = false; const INSPECT_DEC: bool = false; +const MAX_ERROR: usize = 0; fn main() { let frames = get_all_frames("../video/frames/"); @@ -56,8 +57,8 @@ fn encode(frames: &[Frame]) -> Vec { enc::rle_diff_horizontal, enc::rle_diff_vertical, enc::bg_strips_horizontal, + enc::cell_diff_8_horizontal, ]; - let max_error = 0; let mut last_frame = FRAME_0; for (i, frame) in frames.iter().enumerate() { @@ -67,7 +68,7 @@ fn encode(frames: &[Frame]) -> Vec { let decode = get_matching_decoder(encoded.encoding); let decoded = decode(&last_frame, &encoded.data, &mut 0); let error = frame_error(frame, &decoded); - if error <= max_error { + if error <= MAX_ERROR { options.push(encoded); } else { // dbg!(&encoded); @@ -108,7 +109,7 @@ enum Encoding { // BGStripsV, // QuadTree, // DrawCommands, - // CellDiff8H, + CellDiff8H, // CellDiff8V, // CellDiff4HH, // CellDiff4HV, @@ -128,7 +129,7 @@ fn get_matching_decoder(encoding: Encoding) -> FrameDecoder { // Encoding::BGStripsV => todo!(), // Encoding::QuadTree => todo!(), // Encoding::DrawCommands => todo!(), - // Encoding::CellDiff8H => todo!(), + Encoding::CellDiff8H => dec::cell_diff_8_horizontal, // Encoding::CellDiff8V => todo!(), // Encoding::CellDiff4HH => todo!(), // Encoding::CellDiff4HV => todo!(),