diff --git a/cz/src/common.rs b/cz/src/common.rs index edb96ab..6b00e1d 100644 --- a/cz/src/common.rs +++ b/cz/src/common.rs @@ -66,7 +66,7 @@ pub trait CzHeader { fn common(&self) -> &CommonHeader; /// Turn the header into bytes equivalent to the original header from the file - fn to_bytes(&self) -> Result, io::Error>; + fn write_into(&self, output: &mut T) -> Result; /// The version of the image fn version(&self) -> CzVersion; @@ -198,18 +198,21 @@ impl CzHeader for CommonHeader { self.unknown } - fn to_bytes(&self) -> Result, io::Error> { - let mut buf = vec![]; - + fn write_into( + &self, + output: &mut T, + ) -> Result { + let pos = output.stream_position()?; let magic_bytes = [b'C', b'Z', b'0' + self.version as u8, b'\0']; - buf.write_all(&magic_bytes)?; - buf.write_u32::(self.length() as u32)?; - buf.write_u16::(self.width())?; - buf.write_u16::(self.height())?; - buf.write_u16::(self.depth())?; - buf.write_u8(self.color_block())?; - Ok(buf) + output.write_all(&magic_bytes)?; + output.write_u32::(self.length() as u32)?; + output.write_u16::(self.width())?; + output.write_u16::(self.height())?; + output.write_u16::(self.depth())?; + output.write_u8(self.color_block())?; + + Ok((output.stream_position()? - pos) as usize) } } @@ -279,22 +282,25 @@ impl ExtendedHeader { }) } - pub fn as_bytes(&self) -> Result, io::Error> { - let mut buf = vec![]; + pub fn write_into( + &self, + output: &mut T + ) -> Result { + let pos = output.stream_position()?; - buf.write_all(&self.unknown_1)?; - buf.write_u16::(self.crop_width)?; - buf.write_u16::(self.crop_height)?; - buf.write_u16::(self.bounds_width)?; - buf.write_u16::(self.bounds_height)?; + output.write_all(&self.unknown_1)?; + output.write_u16::(self.crop_width)?; + output.write_u16::(self.crop_height)?; + output.write_u16::(self.bounds_width)?; + output.write_u16::(self.bounds_height)?; if self.offset_width.is_some() { - buf.write_u16::(self.offset_width.unwrap())?; - buf.write_u16::(self.offset_height.unwrap())?; - buf.write_u32::(self.unknown_2.unwrap())?; + output.write_u16::(self.offset_width.unwrap())?; + output.write_u16::(self.offset_height.unwrap())?; + output.write_u32::(self.unknown_2.unwrap())?; } - Ok(buf) + Ok((output.stream_position()? - pos) as usize) } } @@ -330,3 +336,13 @@ pub fn apply_palette( Ok(output_map) } + +pub fn rgba_to_indexed(input: &[u8], palette: &[[u8; 4]]) -> Result, CzError> { + let mut output_map = Vec::new(); + + for rgba in input.windows(4).step_by(4) { + dbg!(rgba); + } + + Ok(output_map) +} diff --git a/cz/src/dynamic.rs b/cz/src/dynamic.rs index 094657d..7b9454b 100644 --- a/cz/src/dynamic.rs +++ b/cz/src/dynamic.rs @@ -1,11 +1,10 @@ use std::{ - io::{BufReader, Read, Seek, SeekFrom}, - path::Path + fs::File, io::{BufReader, Cursor, Read, Seek, SeekFrom, Write}, path::Path }; use byteorder::ReadBytesExt; use crate::{ - common::{apply_palette, get_palette, CommonHeader, CzError, CzHeader, CzVersion, ExtendedHeader}, + common::{apply_palette, get_palette, rgba_to_indexed, CommonHeader, CzError, CzHeader, CzVersion, ExtendedHeader}, formats::{cz0, cz1, cz2, cz3, cz4}, }; @@ -89,7 +88,32 @@ impl DynamicCz { } pub fn save_as_cz>(&self, path: T) -> Result<(), CzError> { - todo!() + let mut out_file = File::create(path.into())?; + + self.header_common.write_into(&mut out_file)?; + + if let Some(ext) = self.header_extended { + ext.write_into(&mut out_file)?; + } + + let output_bitmap; + match &self.palette { + Some(pal) if self.header_common.depth() <= 8 => { + output_bitmap = rgba_to_indexed(&self.bitmap(), &pal)? + }, + _ => output_bitmap = self.bitmap().clone() + } + + match self.header_common.version() { + CzVersion::CZ0 => cz0::encode(&mut out_file, &self.bitmap)?, + CzVersion::CZ1 => todo!(), + CzVersion::CZ2 => todo!(), + CzVersion::CZ3 => todo!(), + CzVersion::CZ4 => todo!(), + CzVersion::CZ5 => todo!(), + } + + Ok(()) } pub fn header(&self) -> &CommonHeader { diff --git a/cz/src/formats/cz0.rs b/cz/src/formats/cz0.rs index f39acb1..779f103 100644 --- a/cz/src/formats/cz0.rs +++ b/cz/src/formats/cz0.rs @@ -1,12 +1,23 @@ -use std::io::{Read, Seek}; -use byteorder::ReadBytesExt; +use std::io::{Read, Write, Seek}; +use byteorder::{ReadBytesExt, WriteBytesExt}; use crate::common::CzError; -pub fn decode(bytes: &mut T) -> Result, CzError> { +pub fn decode( + input: &mut T +) -> Result, CzError> { // Get the rest of the file, which is the bitmap let mut bitmap = vec![]; - bytes.read_to_end(&mut bitmap)?; + input.read_to_end(&mut bitmap)?; Ok(bitmap) } + +pub fn encode( + output: &mut T, + bitmap: &[u8] +) -> Result<(), CzError> { + output.write_all(bitmap)?; + + Ok(()) +} diff --git a/cz/src/formats/cz1.rs b/cz/src/formats/cz1.rs index 686c268..2265165 100644 --- a/cz/src/formats/cz1.rs +++ b/cz/src/formats/cz1.rs @@ -1,5 +1,5 @@ -use byteorder::ReadBytesExt; -use std::io::{Read, Seek, SeekFrom}; +use byteorder::{ReadBytesExt, WriteBytesExt}; +use std::io::{Read, Seek, SeekFrom, Write}; use crate::common::CzError; use crate::compression::{decompress, get_chunk_info}; @@ -14,3 +14,12 @@ pub fn decode(bytes: &mut T) -> Result, C Ok(bitmap) } + +pub fn encode( + output: &mut T, + bitmap: &[u8] +) -> Result<(), CzError> { + output.write_all(bitmap)?; + + Ok(()) +}