Making headway on header invesigations

This commit is contained in:
G2-Games 2023-04-19 03:09:55 -05:00
parent 7f398fac4f
commit 319dea623a
3 changed files with 60 additions and 44 deletions

BIN
src/blue.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

View file

@ -5,12 +5,12 @@ use std::io::Write;
use std::fs; use std::fs;
use std::fs::File; use std::fs::File;
#[derive(Copy, Clone)]
struct HeaderCZ0 { struct HeaderCZ0 {
magic: [u8; 3], // The magic bytes, can be CZ0, (CZ1, CZ2?) magic: [u8; 3], // The magic bytes, can be CZ0, (CZ1, CZ2?)
length: u8, length: u8,
res: (i16, i16), // The width in the header res: (i16, i16), // The width in the header
depth: u8, // Bit depth depth: u8, // Bit depth
mystery: Vec<u8>,
crop: (i16, i16), // Crop dimensions crop: (i16, i16), // Crop dimensions
bounds: (i16, i16), // Bounding box dimensions bounds: (i16, i16), // Bounding box dimensions
offset: (i16, i16), // Offset coordinates offset: (i16, i16), // Offset coordinates
@ -22,14 +22,14 @@ struct CZ0File {
} }
// Converts 8 bit bytes to a 16 bit little endian word or // Converts 8 bit bytes to a 16 bit little endian word or
pub fn bytes_to_word(first:u8, second:u8) -> i16 { fn bytes_to_word(first:u8, second:u8) -> i16 {
let final_value = ((second as i16) << 8) | (first as i16); let final_value = ((second as i16) << 8) | (first as i16);
return final_value; return final_value;
} }
// Converts a 16 bit little endian word to 8 bit bytes // Converts a 16 bit little endian word to 8 bit bytes
pub fn word_to_bytes(word:i16) -> [u8; 2] { fn word_to_bytes(word:i16) -> [u8; 2] {
let first: u8 = (word & 0xFF) as u8; // Extract the first byte let first: u8 = (word & 0xFF) as u8; // Extract the first byte
let second: u8 = ((word >> 8) & 0xFF) as u8; // Extract the second byte let second: u8 = ((word >> 8) & 0xFF) as u8; // Extract the second byte
@ -38,43 +38,50 @@ pub fn word_to_bytes(word:i16) -> [u8; 2] {
/// Extract all the header information from a CZ0 file /// Extract all the header information from a CZ0 file
fn extract_header_cz0(header_vec: &Vec<u8>) -> (HeaderCZ0, usize) { fn extract_header_cz0(header_vec: &Vec<u8>) -> (HeaderCZ0, usize) {
println!("");
// Get the magic bytes // Get the magic bytes
let magic: [u8; 3] = header_vec[0..3].try_into().unwrap(); let magic: [u8; 3] = header_vec[0..3].try_into().unwrap();
println!("Magic Bytes : {:?}", magic); println!("Magic Bytes : {:?}", magic);
// Get the length of the header // Get the length of the header
let length = header_vec[4]; let length = header_vec[4];
println!("Header Length: {:?}", length); println!("Header Length : {:?} bytes", length);
// Convert the width and height to i16 values // Convert the width and height to i16 values
let width = bytes_to_word(header_vec[8], header_vec[9]); let width = bytes_to_word(header_vec[8], header_vec[9]);
let height = bytes_to_word(header_vec[10], header_vec[11]); let height = bytes_to_word(header_vec[10], header_vec[11]);
println!("Resolution : {}x{}", width, height); println!("Resolution : {}x{}", width, height);
// Get the bit depth // Get the bit depth
let depth = header_vec[12]; let depth = header_vec[12];
println!("Bit Depth : {} bits", depth); println!("Bit Depth : {} bits", depth);
// Get the mystery bytes
let mystery = header_vec[13..20].to_vec();
println!("Header Length : {:?} bytes", length);
// Get the crop resolution // Get the crop resolution
let crop_width = bytes_to_word(header_vec[20], header_vec[21]); let crop_width = bytes_to_word(header_vec[20], header_vec[21]);
let crop_height = bytes_to_word(header_vec[22], header_vec[23]); let crop_height = bytes_to_word(header_vec[22], header_vec[23]);
println!("Crop Coords : {}x{}", crop_width, crop_height); println!("Crop Coords : {}x{}", crop_width, crop_height);
// Get bounding box // Get bounding box
let bound_width = bytes_to_word(header_vec[24], header_vec[25]); let bound_width = bytes_to_word(header_vec[24], header_vec[25]);
let bound_height = bytes_to_word(header_vec[26], header_vec[27]); let bound_height = bytes_to_word(header_vec[26], header_vec[27]);
println!("Bound Coords : {}x{}", bound_width, bound_height); println!("Bound Coords : {}x{}", bound_width, bound_height);
// Get offset coordinates // Get offset coordinates
let offset_x = bytes_to_word(header_vec[28], header_vec[29]); let offset_x = bytes_to_word(header_vec[28], header_vec[29]);
let offset_y = bytes_to_word(header_vec[30], header_vec[31]); let offset_y = bytes_to_word(header_vec[30], header_vec[31]);
println!("Offset Coords: {}x{}", offset_x, offset_y); println!("Offset Coords : {}x{}", offset_x, offset_y);
let image_header = HeaderCZ0 { let image_header = HeaderCZ0 {
magic, magic,
length, length,
res: (width, height), res: (width, height),
depth, depth,
mystery,
crop: (crop_width, crop_height), crop: (crop_width, crop_height),
bounds: (bound_width, bound_height), bounds: (bound_width, bound_height),
offset: (offset_x, offset_y), offset: (offset_x, offset_y),
@ -91,7 +98,6 @@ fn decode_cz0(input_filename:&str) -> CZ0File {
let mut input = fs::read(input_filename).unwrap(); let mut input = fs::read(input_filename).unwrap();
println!("Decoding input..."); println!("Decoding input...");
// TODO Research the header more! // TODO Research the header more!
let (header, header_length) = extract_header_cz0(&input); let (header, header_length) = extract_header_cz0(&input);
input.drain(..header_length); input.drain(..header_length);
@ -109,62 +115,66 @@ fn decode_cz0(input_filename:&str) -> CZ0File {
/// header information from a previous CZ0 file in order to /// header information from a previous CZ0 file in order to
/// replace it /// replace it
fn encode_cz0(original_file:CZ0File, in_name:&str, out_name:&str) -> io::Result<()> { fn encode_cz0(original_file:CZ0File, in_name:&str, out_name:&str) -> io::Result<()> {
println!("Reading input file...");
let input_image = open(in_name).unwrap().into_rgba8(); let input_image = open(in_name).unwrap().into_rgba8();
let (input_width, input_height) = input_image.dimensions(); let (input_width, input_height) = input_image.dimensions();
let width_diff = input_width as i16 - original_file.header.res.0; let width_diff = input_width as i16 - original_file.header.res.0;
let height_diff = input_height as i16 - original_file.header.res.1; let height_diff = input_height as i16 - original_file.header.res.1;
// Crop
let crop_width = input_width as i16;
let crop_height = input_height as i16;
// Offset // Offset
let offset_x = original_file.header.offset.0 + width_diff; let offset_x = original_file.header.offset.0 + width_diff;
let offset_y = original_file.header.offset.1 + height_diff; let offset_y = original_file.header.offset.1 + height_diff;
let mut length = 28;
if offset_y > 0 || offset_x > 0 {
length = 36;
}
// Construct the header // Construct the header
let header = HeaderCZ0 { let header = HeaderCZ0 {
magic: [67, 90, 48], magic: [67, 90, 48],
length: 36, length,
res: (input_width as i16, input_height as i16), res: (input_width as i16, input_height as i16),
depth: 32, depth: original_file.header.depth,
crop: (crop_width, crop_height), mystery: original_file.header.mystery,
crop: (input_width as i16, input_height as i16),
bounds: (original_file.header.bounds.0, original_file.header.bounds.1), bounds: (original_file.header.bounds.0, original_file.header.bounds.1),
offset: (offset_x, offset_y), offset: (original_file.header.offset.0, original_file.header.offset.1),
}; };
let bitmap = input_image.to_vec(); let bitmap = input_image.to_vec();
println!("Writing to output file...");
let mut file = File::create(out_name)?; let mut file = File::create(out_name)?;
// Write magic and length // Assemble the header
file.write_all(&header.magic)?; let mut header_assembled = [
file.write_all(&[0])?; &header.magic[..],
file.write_all(&[header.length])?; &[0],
file.write_all(&vec![0u8; 3])?; &[header.length],
&vec![0u8; 3],
// Write width and height &word_to_bytes(header.res.0),
file.write_all(&word_to_bytes(header.res.0))?; &word_to_bytes(header.res.1),
file.write_all(&word_to_bytes(header.res.1))?; &[header.depth],
// Write bit depth &header.mystery,
file.write_all(&[header.depth])?;
file.write_all(&vec![0u8; 7])?;
// Write crop width and height &word_to_bytes(header.crop.0),
file.write_all(&word_to_bytes(header.crop.0))?; &word_to_bytes(header.crop.1),
file.write_all(&word_to_bytes(header.crop.1))?;
// Write bound width and height &word_to_bytes(header.bounds.0),
file.write_all(&word_to_bytes(header.bounds.0))?; &word_to_bytes(header.bounds.1),
file.write_all(&word_to_bytes(header.bounds.1))?;
// Write offset width and height &word_to_bytes(header.offset.0),
file.write_all(&word_to_bytes(header.offset.0))?; &word_to_bytes(header.offset.1),
file.write_all(&word_to_bytes(header.offset.1))?; &vec![0u8; 4],
].concat();
// Write unknown padding bytes header_assembled.drain(length as usize..);
file.write_all(&vec![0u8; 4])?;
file.write_all(&header_assembled)?;
// Write the actual image data // Write the actual image data
file.write_all(&bitmap)?; file.write_all(&bitmap)?;
@ -175,7 +185,8 @@ fn encode_cz0(original_file:CZ0File, in_name:&str, out_name:&str) -> io::Result<
fn main() -> io::Result<()> { fn main() -> io::Result<()> {
let image = decode_cz0("775.cz0"); let image = decode_cz0("775.cz0");
/* Create and save a PNG of the image data /*
// Create and save a PNG of the image data
// This errors if the image data is too short // This errors if the image data is too short
let tmp = match RgbaImage::from_raw( let tmp = match RgbaImage::from_raw(
image.header.res.0 as u32, image.header.res.0 as u32,
@ -198,8 +209,13 @@ fn main() -> io::Result<()> {
} }
}*/ }*/
encode_cz0(image, "melon_test.png", "test.cz0").unwrap();
decode_cz0("test.cz0"); match encode_cz0(image, "melon_test.png", "test.cz0") {
Ok(file) => file,
Err(error) => panic!("Problem opening the file: {:?}", error),
};
decode_cz0("test.cz0"); // Running this function standalone simply prints information about the image's header
return Ok(()); return Ok(());
} }

BIN
src/melon_test.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB