diff --git a/src/cz_common.rs b/src/cz_common.rs index 2095fc9..2119832 100644 --- a/src/cz_common.rs +++ b/src/cz_common.rs @@ -58,6 +58,8 @@ pub struct CommonHeader { /// Bit depth in Bits Per Pixel (BPP) depth: u16, + + color_block: u8, } impl CzHeader for CommonHeader { @@ -74,6 +76,7 @@ impl CzHeader for CommonHeader { width: bytes.read_u16::()?, height: bytes.read_u16::()?, depth: bytes.read_u16::()?, + color_block: bytes.read_u8()?, }) } @@ -107,13 +110,22 @@ pub trait CzImage { Self: Sized; /// 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 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 fn into_bitmap(self) -> Vec; + + /// Set the bitmap the image contains + fn set_bitmap(&mut self, bitmap: Vec, header: Self::Header); } pub fn parse_colormap( diff --git a/src/formats/cz0.rs b/src/formats/cz0.rs index eeb5172..1952dec 100644 --- a/src/formats/cz0.rs +++ b/src/formats/cz0.rs @@ -1,4 +1,4 @@ -use std::io::{Cursor, Read}; +use std::io::{self, Cursor, Read}; use byteorder::{LittleEndian, ReadBytesExt}; @@ -45,7 +45,8 @@ impl CzHeader for Cz0Header { return Err(CzError::VersionMismatch); } - let _unknown = bytes.read_u48::()?; + let _unknown = bytes.read_u32::()?; + let _unknown = bytes.read_u8()?; let crop_width = bytes.read_u16::()?; let crop_height = bytes.read_u16::()?; @@ -105,28 +106,58 @@ impl CzImage for Cz0Image { 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)?; + let mut bitmap = vec![0u8; bytes.len() - header.header_length()]; + input.read_exact(&mut bitmap)?; Ok(Self { header, bitmap }) } - fn save_as_png(&self, name: &str) { - image::save_buffer( + fn save_as_png(&self, name: &str) -> Result<(), image::error::ImageError> { + Ok(image::save_buffer( name, &self.bitmap, self.header.width() as u32, self.header.height() as u32, image::ExtendedColorType::Rgba8, - ) - .unwrap() + )?) } fn header(&self) -> &Self::Header { &self.header } + fn set_header(&mut self, header: Self::Header) { + self.header = header + } + fn into_bitmap(self) -> Vec { self.bitmap } + + fn save_as_cz(&self) -> Result<(), CzError> { + todo!() + } + + fn set_bitmap(&mut self, bitmap: Vec, header: Self::Header) { + self.bitmap = bitmap; + + self.header = header; + } +} + +impl TryFrom<&[u8]> for Cz0Image { + type Error = CzError; + + fn try_from(value: &[u8]) -> Result { + 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 }) + } } diff --git a/src/formats/cz1.rs b/src/formats/cz1.rs index 8b0e065..b618776 100644 --- a/src/formats/cz1.rs +++ b/src/formats/cz1.rs @@ -51,24 +51,38 @@ impl CzImage for Cz1Image { 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( self.header.width() as u32, self.header.height() as u32, 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 { &self.header } + fn set_header(&mut self, header: Self::Header) { + self.header = header + } + fn into_bitmap(self) -> Vec { self.bitmap } + + fn save_as_cz(&self) -> Result<(), CzError> { + todo!() + } + + fn set_bitmap(&mut self, bitmap: Vec, header: Self::Header) { + todo!() + } } fn apply_palette(input: &mut Vec, palette: &[Rgba]) { diff --git a/src/formats/cz3.rs b/src/formats/cz3.rs index 15a041e..3480cec 100644 --- a/src/formats/cz3.rs +++ b/src/formats/cz3.rs @@ -122,22 +122,36 @@ impl CzImage for Cz3Image { 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( self.header.width() as u32, self.header.height() as u32, 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 { &self.header } + fn set_header(&mut self, header: Self::Header) { + self.header = header + } + fn into_bitmap(self) -> Vec { self.bitmap } + + fn save_as_cz(&self) -> Result<(), CzError> { + todo!() + } + + fn set_bitmap(&mut self, bitmap: Vec, header: Self::Header) { + todo!() + } } diff --git a/src/main.rs b/src/main.rs index 942fe85..2f982f3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,12 +8,12 @@ pub mod formats { // Generic tools use std::fs; -use crate::{cz_common::CzImage, formats::cz3::Cz3Image}; +use crate::{cz_common::CzImage, formats::{cz0::Cz0Image, cz3::Cz3Image}}; fn main() { - let input = fs::read("../test_files/BAD_BG_011_10.cz4").expect("Error, could not open image"); - let img_file = Cz3Image::decode(&input).unwrap(); + let input = fs::read("../test_files/Old_TestFiles/782.cz0").expect("Error, could not open image"); + let img_file = Cz0Image::decode(&input).unwrap(); println!("{:#?}", img_file.header()); - img_file.save_as_png("test.png") + img_file.save_as_png("test.png").unwrap(); }