Added extended header struct

This commit is contained in:
G2-Games 2024-05-08 12:24:03 -05:00
parent f4eb9ea1b3
commit 73184837af
3 changed files with 95 additions and 110 deletions

View file

@ -213,6 +213,91 @@ impl CzHeader for CommonHeader {
}
}
#[derive(Debug, Clone, Copy)]
pub struct ExtendedHeader {
/// Unknown bytes
unknown_1: [u8; 5],
/// Width of cropped image area
pub crop_width: u16,
/// Height of cropped image area
pub crop_height: u16,
/// Bounding box width
pub bounds_width: u16,
/// Bounding box height
pub bounds_height: u16,
/// Offset width
pub offset_width: Option<u16>,
/// Offset height
pub offset_height: Option<u16>,
unknown_2: Option<u32>,
}
impl ExtendedHeader {
pub fn new<T: Seek + ReadBytesExt + Read>(
input: &mut T,
common_header: &CommonHeader
) -> Result<Self, CzError> {
let mut unknown_1 = [0u8; 5];
input.read_exact(&mut unknown_1)?;
let crop_width = input.read_u16::<LittleEndian>()?;
let crop_height = input.read_u16::<LittleEndian>()?;
let bounds_width = input.read_u16::<LittleEndian>()?;
let bounds_height = input.read_u16::<LittleEndian>()?;
let mut offset_width = None;
let mut offset_height = None;
let mut unknown_2 = None;
if common_header.length() > 28 {
offset_width = Some(input.read_u16::<LittleEndian>()?);
offset_height = Some(input.read_u16::<LittleEndian>()?);
unknown_2 = Some(input.read_u32::<LittleEndian>()?);
}
Ok(Self {
unknown_1,
crop_width,
crop_height,
bounds_width,
bounds_height,
offset_width,
offset_height,
unknown_2,
})
}
pub fn as_bytes(&self) -> Result<Vec<u8>, io::Error> {
let mut buf = vec![];
buf.write_all(&self.unknown_1)?;
buf.write_u16::<LittleEndian>(self.crop_width)?;
buf.write_u16::<LittleEndian>(self.crop_height)?;
buf.write_u16::<LittleEndian>(self.bounds_width)?;
buf.write_u16::<LittleEndian>(self.bounds_height)?;
if self.offset_width.is_some() {
buf.write_u16::<LittleEndian>(self.offset_width.unwrap())?;
buf.write_u16::<LittleEndian>(self.offset_height.unwrap())?;
buf.write_u32::<LittleEndian>(self.unknown_2.unwrap())?;
}
Ok(buf)
}
}
pub fn get_palette<T: Seek + ReadBytesExt + Read>(
input: &mut T,
num_colors: usize,

View file

@ -5,12 +5,13 @@ use std::{
use byteorder::ReadBytesExt;
use crate::{
common::{apply_palette, get_palette, CommonHeader, CzError, CzHeader, CzVersion},
common::{apply_palette, get_palette, CommonHeader, CzError, CzHeader, CzVersion, ExtendedHeader},
formats::{cz0, cz1, cz2, cz3, cz4},
};
pub struct DynamicCz {
header_common: CommonHeader,
header_extended: Option<ExtendedHeader>,
palette: Option<Vec<[u8; 4]>>,
bitmap: Vec<u8>,
}
@ -45,6 +46,10 @@ impl DynamicCz {
pub fn decode<T: Seek + ReadBytesExt + Read>(input: &mut T) -> Result<Self, CzError> {
// Get the header common to all CZ images
let header_common = CommonHeader::new(input)?;
let mut header_extended = None;
if header_common.length() > 15 && header_common.version() != CzVersion::CZ2 {
header_extended = Some(ExtendedHeader::new(input, &header_common)?);
}
input.seek(SeekFrom::Start(header_common.length() as u64))?;
// Get the color palette if the bit depth is 8 or less
@ -77,6 +82,7 @@ impl DynamicCz {
Ok(Self {
header_common,
header_extended,
palette,
bitmap,
})

View file

@ -1,113 +1,7 @@
use std::io::{self, Read, Seek, Write};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use std::io::{Read, Seek};
use byteorder::ReadBytesExt;
use crate::common::{CommonHeader, CzError, CzHeader, CzVersion};
#[derive(Debug, Clone, Copy)]
pub struct Cz0Header {
/// Common CZ# header
pub common: CommonHeader,
/// Unknown bytes
unknown_1: [u8; 5],
/// Width of cropped image area
pub crop_width: u16,
/// Height of cropped image area
pub crop_height: u16,
/// Bounding box width
pub bounds_width: u16,
/// Bounding box height
pub bounds_height: u16,
/// Offset width
pub offset_width: Option<u16>,
/// Offset height
pub offset_height: Option<u16>,
unknown_2: Option<[u8; 4]>,
}
impl Cz0Header {
fn new<T: Seek + ReadBytesExt + Read>(bytes: &mut T) -> Result<Self, CzError>
where
Self: Sized,
{
let common = CommonHeader::new(bytes)?;
if common.version() != CzVersion::CZ0 {
return Err(CzError::VersionMismatch(common.version() as u8, 0));
}
let mut unknown_1 = [0u8; 5];
bytes.read_exact(&mut unknown_1)?;
let crop_width = bytes.read_u16::<LittleEndian>()?;
let crop_height = bytes.read_u16::<LittleEndian>()?;
let bounds_width = bytes.read_u16::<LittleEndian>()?;
let bounds_height = bytes.read_u16::<LittleEndian>()?;
let mut offset_width = None;
let mut offset_height = None;
let mut unknown_2 = None;
if common.length() > 28 {
offset_width = Some(bytes.read_u16::<LittleEndian>()?);
offset_height = Some(bytes.read_u16::<LittleEndian>()?);
let mut un_2 = [0u8; 4];
bytes.read_exact(&mut un_2)?;
unknown_2 = Some(un_2);
}
Ok(Self {
common,
unknown_1,
crop_width,
crop_height,
bounds_width,
bounds_height,
offset_width,
offset_height,
unknown_2,
})
}
fn to_bytes(&self) -> Result<Vec<u8>, io::Error> {
let mut buf = vec![];
buf.write_all(&self.common.to_bytes()?)?;
buf.write_all(&self.unknown_1)?;
buf.write_u16::<LittleEndian>(self.crop_width)?;
buf.write_u16::<LittleEndian>(self.crop_height)?;
buf.write_u16::<LittleEndian>(self.bounds_width)?;
buf.write_u16::<LittleEndian>(self.bounds_height)?;
if self.common.length() > 28 {
buf.write_u16::<LittleEndian>(self.offset_width.unwrap())?;
buf.write_u16::<LittleEndian>(self.offset_height.unwrap())?;
buf.write_all(&self.unknown_2.unwrap())?;
}
Ok(buf)
}
}
#[derive(Debug)]
pub struct Cz0Image {
header: Cz0Header,
bitmap: Vec<u8>,
}
use crate::common::CzError;
pub fn decode<T: Seek + ReadBytesExt + Read>(bytes: &mut T) -> Result<Vec<u8>, CzError> {
// Get the rest of the file, which is the bitmap