mirror of
https://github.com/G2-Games/lbee-utils.git
synced 2025-04-19 15:22:53 -05:00
Added docmentation and fixes
This commit is contained in:
parent
8945b80065
commit
aa03498fd0
10 changed files with 50 additions and 51 deletions
|
@ -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"
|
||||||
|
|
|
@ -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>(
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
|
||||||
|
|
||||||
let mut success = 0;
|
img.save_as_png("test.png").unwrap();
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue