Compare commits

..

No commits in common. "77365cf089213095943579ffdb2166546935adba" and "a9ed206b72f4984caeb10e816fd3b404d5df4825" have entirely different histories.

6 changed files with 32 additions and 11 deletions

View file

@ -1,7 +1,7 @@
[package] [package]
name = "cz" name = "cz"
edition = "2021" edition = "2021"
version = "0.1.3" version = "0.1.2"
description=""" description="""
An encoder/decoder for CZ# image files used in the LUCA System engine by An encoder/decoder for CZ# image files used in the LUCA System engine by
Prototype Ltd. Prototype Ltd.

View file

@ -312,7 +312,9 @@ fn compress_lzw(data: &[u8], size: usize, last: Vec<u8>) -> (usize, Vec<u16>, Ve
(count, compressed, last_element) (count, compressed, last_element)
} }
pub fn compress2(data: &[u8]) -> (Vec<u8>, CompressionInfo) { pub fn compress2(data: &[u8], size: usize) -> (Vec<u8>, CompressionInfo) {
let size = if size == 0 { 0x87BDF } else { size };
let mut part_data; let mut part_data;
let mut offset = 0; let mut offset = 0;
@ -326,7 +328,7 @@ pub fn compress2(data: &[u8]) -> (Vec<u8>, CompressionInfo) {
}; };
loop { loop {
(count, part_data, last) = compress_lzw2(&data[offset..], last); (count, part_data, last) = compress_lzw2(&data[offset..], size, last);
if count == 0 { if count == 0 {
break; break;
} }
@ -344,13 +346,20 @@ pub fn compress2(data: &[u8]) -> (Vec<u8>, CompressionInfo) {
if output_info.chunk_count == 0 { if output_info.chunk_count == 0 {
panic!("No chunks compressed!") 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(); output_info.total_size_compressed = output_buf.len();
(output_buf, output_info) (output_buf, output_info)
} }
fn compress_lzw2(data: &[u8], last: Vec<u8>) -> (usize, Vec<u8>, Vec<u8>) { fn compress_lzw2(data: &[u8], size: usize, last: Vec<u8>) -> (usize, Vec<u8>, Vec<u8>) {
let mut data = data.to_vec();
if !data.is_empty() {
data[0] = 0;
}
let mut count = 0; let mut count = 0;
let mut dictionary = HashMap::new(); let mut dictionary = HashMap::new();
for i in 0..=255 { for i in 0..=255 {
@ -363,7 +372,7 @@ fn compress_lzw2(data: &[u8], last: Vec<u8>) -> (usize, Vec<u8>, Vec<u8>) {
element = last element = last
} }
let mut bit_io = BitIo::new(vec![0u8; 0xF0000]); let mut bit_io = BitIo::new(vec![0u8; size + 2]);
let write_bit = |bit_io: &mut BitIo, code: u64| { let write_bit = |bit_io: &mut BitIo, code: u64| {
if code > 0x7FFF { if code > 0x7FFF {
bit_io.write_bit(1, 1); bit_io.write_bit(1, 1);
@ -389,9 +398,9 @@ fn compress_lzw2(data: &[u8], last: Vec<u8>) -> (usize, Vec<u8>, Vec<u8>) {
count += 1; count += 1;
if dictionary_count >= 0x3FFFE { if size > 0 && bit_io.byte_size() >= size {
count -= 1; count -= 1;
break break;
} }
} }
@ -403,7 +412,7 @@ fn compress_lzw2(data: &[u8], last: Vec<u8>) -> (usize, Vec<u8>, Vec<u8>) {
} }
} }
return (count, bit_io.bytes(), Vec::new()); return (count, bit_io.bytes(), Vec::new());
} else if bit_io.byte_size() < 0x87BDF { } else if bit_io.byte_size() < size {
if !last_element.is_empty() { if !last_element.is_empty() {
write_bit(&mut bit_io, *dictionary.get(&last_element).unwrap()); write_bit(&mut bit_io, *dictionary.get(&last_element).unwrap());
} }

View file

@ -6,7 +6,7 @@ use crate::compression::{compress2, decompress2, get_chunk_info};
pub fn decode<T: Seek + ReadBytesExt + Read>(bytes: &mut T) -> Result<Vec<u8>, CzError> { pub fn decode<T: Seek + ReadBytesExt + Read>(bytes: &mut T) -> Result<Vec<u8>, CzError> {
// Get information about the compressed chunks // Get information about the compressed chunks
let block_info = get_chunk_info(bytes)?; let block_info = get_chunk_info(bytes).unwrap();
bytes.seek(SeekFrom::Start(block_info.length as u64))?; bytes.seek(SeekFrom::Start(block_info.length as u64))?;
// Get the bitmap // Get the bitmap
@ -16,7 +16,7 @@ pub fn decode<T: Seek + ReadBytesExt + Read>(bytes: &mut T) -> Result<Vec<u8>, C
} }
pub fn encode<T: WriteBytesExt + Write>(output: &mut T, bitmap: &[u8]) -> Result<(), CzError> { pub fn encode<T: WriteBytesExt + Write>(output: &mut T, bitmap: &[u8]) -> Result<(), CzError> {
let (compressed_data, compressed_info) = compress2(&bitmap); let (compressed_data, compressed_info) = compress2(bitmap, 0x87BDF);
compressed_info.write_into(output)?; compressed_info.write_into(output)?;

View file

@ -23,9 +23,13 @@ pub fn encode<T: WriteBytesExt + Write>(
bitmap: &[u8], bitmap: &[u8],
header: &CommonHeader, header: &CommonHeader,
) -> Result<(), CzError> { ) -> Result<(), CzError> {
let timer = std::time::Instant::now();
let bitmap = diff_line(header, bitmap); let bitmap = diff_line(header, bitmap);
println!("diff_line took {:?}", timer.elapsed());
let timer = std::time::Instant::now();
let (compressed_data, compressed_info) = compress(&bitmap, 0xFEFD); let (compressed_data, compressed_info) = compress(&bitmap, 0xFEFD);
println!("Compression took {:?}", timer.elapsed());
compressed_info.write_into(output)?; compressed_info.write_into(output)?;

View file

@ -1,6 +1,6 @@
[package] [package]
name = "utils" name = "utils"
version = "0.1.1" version = "0.1.0"
edition = "2021" edition = "2021"
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"
authors.workspace = true authors.workspace = true

View file

@ -219,6 +219,14 @@ fn main() {
Error::raw(ErrorKind::ValueValidation, "Replacement must be a file\n").exit() Error::raw(ErrorKind::ValueValidation, "Replacement must be a file\n").exit()
} }
if !output.is_file() {
Error::raw(
ErrorKind::ValueValidation,
"Replacement output must be a file\n",
)
.exit()
}
// Replace the input file with the new image // Replace the input file with the new image
replace_cz(&input, &output, &replacement, version, depth).unwrap(); replace_cz(&input, &output, &replacement, version, depth).unwrap();
} }