From 9da8d686830242467e7b60de5666f5ecbe248f8b Mon Sep 17 00:00:00 2001 From: G2-Games Date: Thu, 9 May 2024 21:19:00 -0500 Subject: [PATCH] Added CZ3 encoding --- cz/src/compression.rs | 32 ++++++++++++++++++++++++++++++++ cz/src/dynamic.rs | 5 +---- cz/src/formats/cz3.rs | 31 ++++++++++++++++++++++++------- 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/cz/src/compression.rs b/cz/src/compression.rs index 2d271d9..b1ae0ed 100644 --- a/cz/src/compression.rs +++ b/cz/src/compression.rs @@ -289,6 +289,38 @@ pub fn line_diff(header: &T, data: &[u8]) -> Vec { output_buf } +pub fn diff_line(header: &T, input: &[u8]) -> Vec { + let width = header.width() as u32; + let height = header.height() as u32; + + let mut data = Vec::with_capacity(input.len()); + + let block_height = + (f32::ceil(height as f32 / 3.0) as u16) as usize; + let pixel_byte_count = header.depth() >> 3; + let line_byte_count = (width * pixel_byte_count as u32) as usize; + + let mut curr_line; + let mut prev_line: Vec = Vec::with_capacity(line_byte_count); + + let mut i = 0; + for y in 0..height { + curr_line = input[i..i + line_byte_count].to_vec(); + if y % block_height as u32 != 0 { + for x in 0..line_byte_count { + curr_line[x] -= prev_line[x]; + prev_line[x] += curr_line[x]; + } + } else { + prev_line.clone_from(&curr_line); + } + + data.extend_from_slice(&curr_line); + i += line_byte_count; + } + + data +} pub fn compress( data: &[u8], diff --git a/cz/src/dynamic.rs b/cz/src/dynamic.rs index e7b7dce..eec5caa 100644 --- a/cz/src/dynamic.rs +++ b/cz/src/dynamic.rs @@ -63,9 +63,6 @@ impl DynamicCz { CzVersion::CZ5 => unimplemented!(), }; - let mut file = File::create("raw1").unwrap(); - file.write_all(&bitmap).unwrap(); - let image_size = header_common.width() as usize * header_common.height() as usize; if bitmap.len() != image_size * (header_common.depth() >> 3) as usize { // If the bitmap is smaller or larger than the image size, it is likely wrong @@ -109,7 +106,7 @@ impl DynamicCz { CzVersion::CZ0 => cz0::encode(&mut out_file, &output_bitmap)?, CzVersion::CZ1 => cz1::encode(&mut out_file, &output_bitmap)?, CzVersion::CZ2 => todo!(), - CzVersion::CZ3 => todo!(), + CzVersion::CZ3 => cz3::encode(&mut out_file, &output_bitmap, &self.header_common)?, CzVersion::CZ4 => todo!(), CzVersion::CZ5 => todo!(), } diff --git a/cz/src/formats/cz3.rs b/cz/src/formats/cz3.rs index 5cf6f72..dea8f0f 100644 --- a/cz/src/formats/cz3.rs +++ b/cz/src/formats/cz3.rs @@ -1,12 +1,13 @@ -use std::io::{Read, Seek, SeekFrom}; -use byteorder::ReadBytesExt; +use std::io::{Read, Write, Seek, SeekFrom}; +use byteorder::{ReadBytesExt, WriteBytesExt}; -use crate::common::{CommonHeader, CzError}; -use crate::compression::{decompress, line_diff, get_chunk_info}; +use crate::common::{CommonHeader, CzError, CzHeader}; +use crate::compression::{compress, decompress, diff_line, get_chunk_info, line_diff}; -pub fn decode(bytes: &mut T, header: &CommonHeader) - -> Result, CzError> -{ +pub fn decode( + bytes: &mut T, + header: &CommonHeader +) -> Result, CzError> { let block_info = get_chunk_info(bytes)?; bytes.seek(SeekFrom::Start(block_info.length as u64))?; @@ -15,3 +16,19 @@ pub fn decode(bytes: &mut T, header: &CommonHeade Ok(bitmap) } + +pub fn encode( + output: &mut T, + bitmap: &[u8], + header: &H, +) -> Result<(), CzError> { + let bitmap = diff_line(header, bitmap); + + let (compressed_data, compressed_info) = compress(&bitmap, 65277); + + compressed_info.write_into(output)?; + + output.write_all(&compressed_data)?; + + Ok(()) +}