diff --git a/cz/src/common.rs b/cz/src/common.rs index 5ec8665..7cbe9be 100644 --- a/cz/src/common.rs +++ b/cz/src/common.rs @@ -58,7 +58,7 @@ impl TryFrom for CzVersion { } pub trait CzHeader { - fn new(bytes: &mut T) -> Result + fn from_bytes(bytes: &mut T) -> Result where Self: Sized; @@ -122,8 +122,29 @@ pub struct CommonHeader { unknown: u8, } +impl CommonHeader { + pub fn new( + version: CzVersion, + width: u16, + height: u16, + ) -> Self { + Self { + version, + length: 15, + width, + height, + depth: 32, + unknown: 0 + } + } + + pub fn set_length(&mut self, length: u32) { + self.length = length + } +} + impl CzHeader for CommonHeader { - fn new(bytes: &mut T) -> Result + fn from_bytes(bytes: &mut T) -> Result where Self: Sized, { @@ -243,7 +264,37 @@ pub struct ExtendedHeader { } impl ExtendedHeader { - pub fn new( + pub fn new( + crop_width: u16, + crop_height: u16, + bounds_width: u16, + bounds_height: u16, + ) -> Self { + ExtendedHeader { + unknown_1: [0u8; 5], + crop_width, + crop_height, + bounds_width, + bounds_height, + offset_width: None, + offset_height: None, + unknown_2: None + } + } + + pub fn with_offset( + mut self, + offset_width: u16, + offset_height: u16 + ) -> Self { + self.offset_width = Some(offset_width); + self.offset_height = Some(offset_height); + self.unknown_2 = Some(0); + + self + } + + pub fn from_bytes( input: &mut T, common_header: &CommonHeader ) -> Result { diff --git a/cz/src/compression.rs b/cz/src/compression.rs index b1ae0ed..01b4e3d 100644 --- a/cz/src/compression.rs +++ b/cz/src/compression.rs @@ -334,7 +334,7 @@ pub fn compress( let mut part_data; let mut offset = 0; - let mut count = 0; + let mut count; let mut last = Vec::new(); let mut output_buf: Vec = vec![]; @@ -362,6 +362,13 @@ pub fn compress( output_info.chunk_count += 1; } + if output_info.chunk_count == 0 { + panic!("No chunks compressed!") + } else if output_info.chunk_count != 1 { + output_info.chunks[0].size_raw -= 1; + output_info.chunks[output_info.chunk_count - 1].size_raw += 1; + } + output_info.total_size_compressed = output_buf.len() / 2; (output_buf, output_info) diff --git a/cz/src/dynamic.rs b/cz/src/dynamic.rs index eec5caa..6424aec 100644 --- a/cz/src/dynamic.rs +++ b/cz/src/dynamic.rs @@ -33,15 +33,53 @@ impl DynamicCz { Ok(()) } + + pub fn from_raw( + version: CzVersion, + width: u16, + height: u16, + bitmap: Vec, + ) -> Self { + let header_common = CommonHeader::new( + version, + width, + height + ); + + Self { + header_common, + header_extended: None, + palette: None, + bitmap, + } + } + + pub fn with_header(mut self, header: CommonHeader) -> Self { + self.header_common = header; + + self + } + + pub fn with_extended_header(mut self, ext_header: ExtendedHeader) -> Self { + if ext_header.offset_width.is_none() { + self.header_common.set_length(28) + } else { + self.header_common.set_length(36) + } + + self.header_extended = Some(ext_header); + + self + } } impl DynamicCz { pub fn decode(input: &mut T) -> Result { // Get the header common to all CZ images - let header_common = CommonHeader::new(input)?; + let header_common = CommonHeader::from_bytes(input)?; let mut header_extended = None; if header_common.length() > 15 && header_common.version() != CzVersion::CZ2 { - header_extended = Some(ExtendedHeader::new(input, &header_common)?); + header_extended = Some(ExtendedHeader::from_bytes(input, &header_common)?); } input.seek(SeekFrom::Start(header_common.length() as u64))?; diff --git a/cz/src/formats/cz1.rs b/cz/src/formats/cz1.rs index b52b44b..52a79f8 100644 --- a/cz/src/formats/cz1.rs +++ b/cz/src/formats/cz1.rs @@ -21,7 +21,7 @@ pub fn encode( output: &mut T, bitmap: &[u8] ) -> Result<(), CzError> { - let (compressed_data, compressed_info) = compress(bitmap, 65277); + let (compressed_data, compressed_info) = compress(bitmap, 0xFEFD); dbg!(&compressed_info); diff --git a/cz/src/formats/cz3.rs b/cz/src/formats/cz3.rs index dea8f0f..5e0c0ab 100644 --- a/cz/src/formats/cz3.rs +++ b/cz/src/formats/cz3.rs @@ -24,7 +24,7 @@ pub fn encode( ) -> Result<(), CzError> { let bitmap = diff_line(header, bitmap); - let (compressed_data, compressed_info) = compress(&bitmap, 65277); + let (compressed_data, compressed_info) = compress(&bitmap, 0xFEFD); compressed_info.write_into(output)?; diff --git a/utils/src/main.rs b/utils/src/main.rs index f47c938..04deefc 100644 --- a/utils/src/main.rs +++ b/utils/src/main.rs @@ -1,11 +1,23 @@ -use cz::dynamic::DynamicCz; +use cz::{common::{CzVersion, ExtendedHeader}, dynamic::DynamicCz}; fn main() { - let img = DynamicCz::open("font72.cz1").unwrap(); + let mio = image::open("mio_inverted.png").unwrap(); + let mio = mio.to_rgba8(); - img.save_as_cz("test.cz1").unwrap(); - img.save_as_png("test1.png").unwrap(); + let cz_mio = + DynamicCz::from_raw( + CzVersion::CZ3, + mio.width() as u16, + mio.height() as u16, + mio.into_raw() + ) + .with_extended_header( + ExtendedHeader::new(1280, 960, 1280, 960) + ); - let img2 = DynamicCz::open("test.cz1").unwrap(); - img2.save_as_png("test2.png").unwrap(); + cz_mio.save_as_cz("test1.cz3").unwrap(); + + let img = DynamicCz::open("test1.cz3").unwrap(); + + img.save_as_png("test.png").unwrap(); }