Fixed CZ1 compression

This commit is contained in:
G2-Games 2024-05-09 20:27:44 -05:00
parent 402c8359fd
commit c363692efd
3 changed files with 26 additions and 14 deletions

View file

@ -1,6 +1,6 @@
//! Shared types and traits between CZ# files //! Shared types and traits between CZ# files
use std::io::{self, Read, Seek, Write}; use std::{collections::HashMap, io::{self, Read, Seek, Write}};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use thiserror::Error; use thiserror::Error;
@ -339,10 +339,19 @@ pub fn apply_palette(
pub fn rgba_to_indexed(input: &[u8], palette: &[[u8; 4]]) -> Result<Vec<u8>, CzError> { pub fn rgba_to_indexed(input: &[u8], palette: &[[u8; 4]]) -> Result<Vec<u8>, CzError> {
let mut output_map = Vec::new(); let mut output_map = Vec::new();
let mut cache = HashMap::new();
for rgba in input.windows(4).step_by(4) { for rgba in input.windows(4).step_by(4) {
let index = palette.iter().position(|e| e == rgba).unwrap_or_default(); let value = match cache.get(rgba) {
output_map.push(index as u8); Some(val) => *val,
None => {
let value = palette.iter().position(|e| e == rgba).unwrap_or_default() as u8;
cache.insert(rgba, value);
value
}
};
output_map.push(value)
} }
Ok(output_map) Ok(output_map)

View file

@ -303,7 +303,7 @@ pub fn compress(
let mut offset = 0; let mut offset = 0;
let mut count = 0; let mut count = 0;
let mut last = String::new(); let mut last = Vec::new();
let mut output_buf: Vec<u8> = vec![]; let mut output_buf: Vec<u8> = vec![];
let mut output_info = CompressionInfo { let mut output_info = CompressionInfo {
@ -335,15 +335,15 @@ pub fn compress(
(output_buf, output_info) (output_buf, output_info)
} }
fn compress_lzw(data: &[u8], size: usize, last: String) -> (usize, Vec<u16>, String) { fn compress_lzw(data: &[u8], size: usize, last: Vec<u8>) -> (usize, Vec<u16>, Vec<u8>) {
let mut count = 0; let mut count = 0;
let mut dictionary = HashMap::new(); let mut dictionary = HashMap::new();
for i in 0..256 { for i in 0..=255 {
dictionary.insert(i.to_string(), i as u16); dictionary.insert(vec![i], i as u16);
} }
let mut dictionary_count = (dictionary.len() + 1) as u16; let mut dictionary_count = (dictionary.len() + 1) as u16;
let mut element = String::new(); let mut element = Vec::new();
if last.len() != 0 { if last.len() != 0 {
element = last element = last
} }
@ -351,14 +351,14 @@ fn compress_lzw(data: &[u8], size: usize, last: String) -> (usize, Vec<u16>, Str
let mut compressed = Vec::with_capacity(size); let mut compressed = Vec::with_capacity(size);
for c in data { for c in data {
let mut entry = element.clone(); let mut entry = element.clone();
entry.push_str(&c.to_string()); entry.push(*c);
if dictionary.get(&entry).is_some() { if dictionary.get(&entry).is_some() {
element = entry element = entry
} else { } else {
compressed.push(*dictionary.get(&element).unwrap()); compressed.push(*dictionary.get(&element).unwrap());
dictionary.insert(entry, dictionary_count); dictionary.insert(entry, dictionary_count);
element = c.to_string(); element = vec![*c];
dictionary_count += 1; dictionary_count += 1;
} }
@ -372,16 +372,16 @@ fn compress_lzw(data: &[u8], size: usize, last: String) -> (usize, Vec<u16>, Str
let last_element = element; let last_element = element;
if compressed.len() == 0 { if compressed.len() == 0 {
if last_element.len() != 0 { if last_element.len() != 0 {
for c in last_element.chars() { for c in last_element {
compressed.push(*dictionary.get(&c.to_string()).unwrap()); compressed.push(*dictionary.get(&vec![c]).unwrap());
} }
} }
return (count, compressed, String::new()) return (count, compressed, Vec::new())
} else if compressed.len() < size { } else if compressed.len() < size {
if last_element.len() != 0 { if last_element.len() != 0 {
compressed.push(*dictionary.get(&last_element).unwrap()); compressed.push(*dictionary.get(&last_element).unwrap());
} }
return (count, compressed, String::new()) return (count, compressed, Vec::new())
} }
(count, compressed, last_element) (count, compressed, last_element)

View file

@ -63,6 +63,9 @@ impl DynamicCz {
CzVersion::CZ5 => unimplemented!(), CzVersion::CZ5 => unimplemented!(),
}; };
let mut file = File::create("raw1").unwrap();
file.write_all(&bitmap).unwrap();
let image_size = header_common.width() as usize * header_common.height() as usize; let image_size = header_common.width() as usize * header_common.height() as usize;
if bitmap.len() != image_size * (header_common.depth() >> 3) as usize { if bitmap.len() != image_size * (header_common.depth() >> 3) as usize {
// If the bitmap is smaller or larger than the image size, it is likely wrong // If the bitmap is smaller or larger than the image size, it is likely wrong