Added docmentation and fixes

This commit is contained in:
G2-Games 2024-05-07 16:27:18 -05:00
parent 8945b80065
commit aa03498fd0
10 changed files with 50 additions and 51 deletions

View file

@ -11,3 +11,4 @@ A encoder/decoder for CZ# image files used in
byteorder = "1.5.0" byteorder = "1.5.0"
thiserror = "1.0.59" thiserror = "1.0.59"
png = "0.17.13" png = "0.17.13"
image = "0.25.1"

View file

@ -19,7 +19,7 @@ pub enum CzError {
#[error("File is not a CZ image")] #[error("File is not a CZ image")]
NotCzFile, NotCzFile,
#[error("Failed to read/write input/output")] #[error("Failed to read/write input/output: {}", 0)]
IoError(#[from] io::Error), IoError(#[from] io::Error),
#[error("Problem while decoding file")] #[error("Problem while decoding file")]
@ -166,7 +166,7 @@ pub trait CzImage {
fn into_bitmap(self) -> Vec<u8>; fn into_bitmap(self) -> Vec<u8>;
/// Set the bitmap the image contains /// Set the bitmap the image contains
fn set_bitmap(&mut self, bitmap: &[u8], header: &Self::Header); fn set_bitmap(&mut self, bitmap: &[u8], width: u16, height: u16);
} }
pub fn parse_colormap<T: Seek + ReadBytesExt + Read>( pub fn parse_colormap<T: Seek + ReadBytesExt + Read>(

View file

@ -7,17 +7,29 @@ use std::{
use crate::binio::BitIO; use crate::binio::BitIO;
use crate::common::{CzError, CzHeader}; use crate::common::{CzError, CzHeader};
/// The size of compressed data in each chunk
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct ChunkInfo { pub struct ChunkInfo {
/// The size of the data when compressed
pub size_compressed: usize, pub size_compressed: usize,
/// The size of the original uncompressed data
pub size_raw: usize, pub size_raw: usize,
} }
/// A CZ# file's information about compression chunks
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct CompressionInfo { pub struct CompressionInfo {
/// Number of compression chunks
pub chunk_count: usize, pub chunk_count: usize,
/// Total size of the data when compressed
pub total_size_compressed: usize, pub total_size_compressed: usize,
/// Total size of the original uncompressed data
pub total_size_raw: usize, pub total_size_raw: usize,
/// The compression chunk information
pub chunks: Vec<ChunkInfo>, pub chunks: Vec<ChunkInfo>,
/// Length of the compression chunk info /// Length of the compression chunk info
@ -25,6 +37,9 @@ pub struct CompressionInfo {
} }
/// Get info about the compression chunks /// Get info about the compression chunks
///
/// These are defined by a length value, followed by the number of data chunks
/// that length value says split into compressed and original size u32 values
pub fn parse_chunk_info<T: Seek + ReadBytesExt + Read>( pub fn parse_chunk_info<T: Seek + ReadBytesExt + Read>(
bytes: &mut T, bytes: &mut T,
) -> Result<CompressionInfo, CzError> { ) -> Result<CompressionInfo, CzError> {

View file

@ -33,7 +33,7 @@ impl DynamicCz {
encoder.set_depth(png::BitDepth::Eight); encoder.set_depth(png::BitDepth::Eight);
let mut writer = encoder.write_header()?; let mut writer = encoder.write_header()?;
writer.write_image_data(&self.bitmap())?; // Save writer.write_image_data(&self.bitmap())?;
Ok(()) Ok(())
} }
@ -59,7 +59,13 @@ impl CzImage for DynamicCz {
} }
fn save_as_cz<T: Into<std::path::PathBuf>>(&self, path: T) -> Result<(), CzError> { fn save_as_cz<T: Into<std::path::PathBuf>>(&self, path: T) -> Result<(), CzError> {
todo!() match self {
DynamicCz::CZ0(img) => img.save_as_cz(path),
DynamicCz::CZ1(_) => unimplemented!(),
DynamicCz::CZ2(_) => unimplemented!(),
DynamicCz::CZ3(_) => unimplemented!(),
DynamicCz::CZ4(_) => unimplemented!(),
}
} }
fn header(&self) -> &Self::Header { fn header(&self) -> &Self::Header {
@ -96,7 +102,7 @@ impl CzImage for DynamicCz {
} }
} }
fn set_bitmap(&mut self, bitmap: &[u8], header: &Self::Header) { fn set_bitmap(&mut self, bitmap: &[u8], width: u16, height: u16) {
todo!() unimplemented!()
} }
} }

View file

@ -189,10 +189,11 @@ impl CzImage for Cz0Image {
self.bitmap self.bitmap
} }
fn set_bitmap(&mut self, bitmap: &[u8], header: &Self::Header) { fn set_bitmap(&mut self, bitmap: &[u8], width: u16, height: u16) {
self.bitmap = bitmap.to_vec(); self.bitmap = bitmap.to_vec();
self.header = *header; self.header.common.width = width;
self.header.common.height = height;
} }
} }

View file

@ -21,13 +21,19 @@ impl CzImage for Cz1Image {
fn decode<T: Seek + ReadBytesExt + Read>(bytes: &mut T) -> Result<Self, CzError> { fn decode<T: Seek + ReadBytesExt + Read>(bytes: &mut T) -> Result<Self, CzError> {
// Get the header from the input // Get the header from the input
let header = CommonHeader::new(bytes).unwrap(); let mut header = CommonHeader::new(bytes).unwrap();
bytes.seek(SeekFrom::Start(header.length() as u64))?; bytes.seek(SeekFrom::Start(header.length() as u64))?;
if header.version() != 1 { if header.version() != 1 {
return Err(CzError::VersionMismatch(1, header.version())); return Err(CzError::VersionMismatch(1, header.version()));
} }
// Lock the color depth to 8 if it's over 32
// This is obviously wrong, but why is it wrong?
if header.depth() > 32 {
header.depth = 8
}
// The color palette, gotten for 8 and 4 BPP images // The color palette, gotten for 8 and 4 BPP images
let mut palette = None; let mut palette = None;
if header.depth() == 8 || header.depth() == 4 { if header.depth() == 8 || header.depth() == 4 {
@ -83,7 +89,7 @@ impl CzImage for Cz1Image {
Ok(()) Ok(())
} }
fn set_bitmap(&mut self, bitmap: &[u8], header: &Self::Header) { fn set_bitmap(&mut self, bitmap: &[u8], width: u16, height: u16) {
todo!() todo!()
} }
} }

View file

@ -139,7 +139,7 @@ impl CzImage for Cz2Image {
Ok(()) Ok(())
} }
fn set_bitmap(&mut self, bitmap: &[u8], header: &Self::Header) { fn set_bitmap(&mut self, bitmap: &[u8], width: u16, height: u16) {
todo!() todo!()
} }
} }

View file

@ -148,7 +148,7 @@ impl CzImage for Cz3Image {
todo!() todo!()
} }
fn set_bitmap(&mut self, bitmap: &[u8], header: &Self::Header) { fn set_bitmap(&mut self, bitmap: &[u8], width: u16, height: u16) {
todo!() todo!()
} }
} }

View file

@ -76,7 +76,11 @@ impl CzImage for Cz4Image {
let block_info = parse_chunk_info(bytes)?; let block_info = parse_chunk_info(bytes)?;
bytes.seek(SeekFrom::Start(block_info.length as u64))?; bytes.seek(SeekFrom::Start(block_info.length as u64))?;
let pcount = header.width() as usize * header.height() as usize;
let bitmap = decompress(bytes, &block_info)?; let bitmap = decompress(bytes, &block_info)?;
let data2 = bitmap[pcount * 3..].to_vec();
let bitmap = line_diff_cz4(&header, &bitmap);
let bitmap = line_diff_cz4(&header, &bitmap); let bitmap = line_diff_cz4(&header, &bitmap);
@ -103,7 +107,7 @@ impl CzImage for Cz4Image {
todo!() todo!()
} }
fn set_bitmap(&mut self, bitmap: &[u8], header: &Self::Header) { fn set_bitmap(&mut self, bitmap: &[u8], width: u16, height: u16) {
todo!() todo!()
} }
} }

View file

@ -1,43 +1,9 @@
use cz::{dynamic::DynamicCz, CzImage}; use cz::{dynamic::DynamicCz, Cz0Image, CzImage};
use std::fs; use std::fs;
use walkdir::WalkDir;
fn main() { fn main() {
if let Err(err) = fs::DirBuilder::new().create("test/") { let mut file = fs::File::open("TEXTBOX.CZ3").unwrap();
println!("{}", err); let img = DynamicCz::decode(&mut file).unwrap();
}
img.save_as_png("test.png").unwrap();
let mut success = 0;
let mut failure = 0;
for entry in WalkDir::new("../../test_files") {
let entry = entry.unwrap();
if entry.path().is_dir() {
continue;
}
let mut input = match fs::File::open(entry.path()) {
Ok(file) => file,
Err(_) => continue,
};
let img_file = match DynamicCz::decode(&mut input) {
Ok(file) => file,
Err(err) => {
println!(
"{}: {}",
entry.path().file_name().unwrap().to_string_lossy(),
err,
);
failure += 1;
continue;
},
};
success += 1;
img_file.save_as_png(
&format!("test/z-{}.png", entry.path().file_stem().unwrap().to_string_lossy())
).unwrap();
}
} }