Fixed CZ0 decoding, made preparations for writing CZ files

This commit is contained in:
G2-Games 2024-05-04 00:44:10 -05:00
parent e7f76a51c0
commit 1279ed4aec
5 changed files with 90 additions and 19 deletions

View file

@ -58,6 +58,8 @@ pub struct CommonHeader {
/// Bit depth in Bits Per Pixel (BPP) /// Bit depth in Bits Per Pixel (BPP)
depth: u16, depth: u16,
color_block: u8,
} }
impl CzHeader for CommonHeader { impl CzHeader for CommonHeader {
@ -74,6 +76,7 @@ impl CzHeader for CommonHeader {
width: bytes.read_u16::<LittleEndian>()?, width: bytes.read_u16::<LittleEndian>()?,
height: bytes.read_u16::<LittleEndian>()?, height: bytes.read_u16::<LittleEndian>()?,
depth: bytes.read_u16::<LittleEndian>()?, depth: bytes.read_u16::<LittleEndian>()?,
color_block: bytes.read_u8()?,
}) })
} }
@ -107,13 +110,22 @@ pub trait CzImage {
Self: Sized; Self: Sized;
/// Save the image as a PNG /// Save the image as a PNG
fn save_as_png(&self, name: &str); fn save_as_png(&self, name: &str) -> Result<(), image::error::ImageError>;
/// Save the image as its corresponding CZ# type
fn save_as_cz(&self) -> Result<(), CzError>;
/// Get the header for metadata /// Get the header for metadata
fn header(&self) -> &Self::Header; fn header(&self) -> &Self::Header;
/// Set the header with its metadata
fn set_header(&mut self, header: Self::Header);
/// Get the raw underlying bitmap for an image /// Get the raw underlying bitmap for an image
fn into_bitmap(self) -> Vec<u8>; fn into_bitmap(self) -> Vec<u8>;
/// Set the bitmap the image contains
fn set_bitmap(&mut self, bitmap: Vec<u8>, header: Self::Header);
} }
pub fn parse_colormap( pub fn parse_colormap(

View file

@ -1,4 +1,4 @@
use std::io::{Cursor, Read}; use std::io::{self, Cursor, Read};
use byteorder::{LittleEndian, ReadBytesExt}; use byteorder::{LittleEndian, ReadBytesExt};
@ -45,7 +45,8 @@ impl CzHeader for Cz0Header {
return Err(CzError::VersionMismatch); return Err(CzError::VersionMismatch);
} }
let _unknown = bytes.read_u48::<LittleEndian>()?; let _unknown = bytes.read_u32::<LittleEndian>()?;
let _unknown = bytes.read_u8()?;
let crop_width = bytes.read_u16::<LittleEndian>()?; let crop_width = bytes.read_u16::<LittleEndian>()?;
let crop_height = bytes.read_u16::<LittleEndian>()?; let crop_height = bytes.read_u16::<LittleEndian>()?;
@ -105,28 +106,58 @@ impl CzImage for Cz0Image {
let header = Cz0Header::new(&mut input)?; let header = Cz0Header::new(&mut input)?;
// Get the rest of the file, which is the bitmap // Get the rest of the file, which is the bitmap
let mut bitmap = vec![]; let mut bitmap = vec![0u8; bytes.len() - header.header_length()];
input.read_to_end(&mut bitmap)?; input.read_exact(&mut bitmap)?;
Ok(Self { header, bitmap }) Ok(Self { header, bitmap })
} }
fn save_as_png(&self, name: &str) { fn save_as_png(&self, name: &str) -> Result<(), image::error::ImageError> {
image::save_buffer( Ok(image::save_buffer(
name, name,
&self.bitmap, &self.bitmap,
self.header.width() as u32, self.header.width() as u32,
self.header.height() as u32, self.header.height() as u32,
image::ExtendedColorType::Rgba8, image::ExtendedColorType::Rgba8,
) )?)
.unwrap()
} }
fn header(&self) -> &Self::Header { fn header(&self) -> &Self::Header {
&self.header &self.header
} }
fn set_header(&mut self, header: Self::Header) {
self.header = header
}
fn into_bitmap(self) -> Vec<u8> { fn into_bitmap(self) -> Vec<u8> {
self.bitmap self.bitmap
} }
fn save_as_cz(&self) -> Result<(), CzError> {
todo!()
}
fn set_bitmap(&mut self, bitmap: Vec<u8>, header: Self::Header) {
self.bitmap = bitmap;
self.header = header;
}
}
impl TryFrom<&[u8]> for Cz0Image {
type Error = CzError;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
let mut input = Cursor::new(value);
// Get the header from the input
let header = Cz0Header::new(&mut input)?;
// Get the rest of the file, which is the bitmap
let mut bitmap = vec![];
input.read_to_end(&mut bitmap)?;
Ok(Self { header, bitmap })
}
} }

View file

@ -51,24 +51,38 @@ impl CzImage for Cz1Image {
Ok(image) Ok(image)
} }
fn save_as_png(&self, name: &str) { fn save_as_png(&self, name: &str) -> Result<(), image::error::ImageError> {
let img = image::RgbaImage::from_raw( let img = image::RgbaImage::from_raw(
self.header.width() as u32, self.header.width() as u32,
self.header.height() as u32, self.header.height() as u32,
self.bitmap.clone(), self.bitmap.clone(),
) )
.unwrap(); .expect("Creating image failed");
img.save_with_format(name, ImageFormat::Png).unwrap(); img.save_with_format(name, ImageFormat::Png)?;
Ok(())
} }
fn header(&self) -> &Self::Header { fn header(&self) -> &Self::Header {
&self.header &self.header
} }
fn set_header(&mut self, header: Self::Header) {
self.header = header
}
fn into_bitmap(self) -> Vec<u8> { fn into_bitmap(self) -> Vec<u8> {
self.bitmap self.bitmap
} }
fn save_as_cz(&self) -> Result<(), CzError> {
todo!()
}
fn set_bitmap(&mut self, bitmap: Vec<u8>, header: Self::Header) {
todo!()
}
} }
fn apply_palette(input: &mut Vec<u8>, palette: &[Rgba<u8>]) { fn apply_palette(input: &mut Vec<u8>, palette: &[Rgba<u8>]) {

View file

@ -122,22 +122,36 @@ impl CzImage for Cz3Image {
Ok(Self { header, bitmap }) Ok(Self { header, bitmap })
} }
fn save_as_png(&self, name: &str) { fn save_as_png(&self, name: &str) -> Result<(), image::error::ImageError> {
let img = image::RgbaImage::from_raw( let img = image::RgbaImage::from_raw(
self.header.width() as u32, self.header.width() as u32,
self.header.height() as u32, self.header.height() as u32,
self.bitmap.clone(), self.bitmap.clone(),
) )
.unwrap(); .expect("Creating image failed");
img.save_with_format(name, ImageFormat::Png).unwrap(); img.save_with_format(name, ImageFormat::Png)?;
Ok(())
} }
fn header(&self) -> &Self::Header { fn header(&self) -> &Self::Header {
&self.header &self.header
} }
fn set_header(&mut self, header: Self::Header) {
self.header = header
}
fn into_bitmap(self) -> Vec<u8> { fn into_bitmap(self) -> Vec<u8> {
self.bitmap self.bitmap
} }
fn save_as_cz(&self) -> Result<(), CzError> {
todo!()
}
fn set_bitmap(&mut self, bitmap: Vec<u8>, header: Self::Header) {
todo!()
}
} }

View file

@ -8,12 +8,12 @@ pub mod formats {
// Generic tools // Generic tools
use std::fs; use std::fs;
use crate::{cz_common::CzImage, formats::cz3::Cz3Image}; use crate::{cz_common::CzImage, formats::{cz0::Cz0Image, cz3::Cz3Image}};
fn main() { fn main() {
let input = fs::read("../test_files/BAD_BG_011_10.cz4").expect("Error, could not open image"); let input = fs::read("../test_files/Old_TestFiles/782.cz0").expect("Error, could not open image");
let img_file = Cz3Image::decode(&input).unwrap(); let img_file = Cz0Image::decode(&input).unwrap();
println!("{:#?}", img_file.header()); println!("{:#?}", img_file.header());
img_file.save_as_png("test.png") img_file.save_as_png("test.png").unwrap();
} }