diff --git a/cz/src/common.rs b/cz/src/common.rs index aa5eb5d..5ec8665 100644 --- a/cz/src/common.rs +++ b/cz/src/common.rs @@ -1,6 +1,6 @@ //! 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 thiserror::Error; @@ -339,10 +339,19 @@ pub fn apply_palette( pub fn rgba_to_indexed(input: &[u8], palette: &[[u8; 4]]) -> Result, CzError> { let mut output_map = Vec::new(); + let mut cache = HashMap::new(); for rgba in input.windows(4).step_by(4) { - let index = palette.iter().position(|e| e == rgba).unwrap_or_default(); - output_map.push(index as u8); + let value = match cache.get(rgba) { + 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) diff --git a/cz/src/compression.rs b/cz/src/compression.rs index ebfc468..2d271d9 100644 --- a/cz/src/compression.rs +++ b/cz/src/compression.rs @@ -303,7 +303,7 @@ pub fn compress( let mut offset = 0; let mut count = 0; - let mut last = String::new(); + let mut last = Vec::new(); let mut output_buf: Vec = vec![]; let mut output_info = CompressionInfo { @@ -335,15 +335,15 @@ pub fn compress( (output_buf, output_info) } -fn compress_lzw(data: &[u8], size: usize, last: String) -> (usize, Vec, String) { +fn compress_lzw(data: &[u8], size: usize, last: Vec) -> (usize, Vec, Vec) { let mut count = 0; let mut dictionary = HashMap::new(); - for i in 0..256 { - dictionary.insert(i.to_string(), i as u16); + for i in 0..=255 { + dictionary.insert(vec![i], i 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 { element = last } @@ -351,14 +351,14 @@ fn compress_lzw(data: &[u8], size: usize, last: String) -> (usize, Vec, Str let mut compressed = Vec::with_capacity(size); for c in data { let mut entry = element.clone(); - entry.push_str(&c.to_string()); + entry.push(*c); if dictionary.get(&entry).is_some() { element = entry } else { compressed.push(*dictionary.get(&element).unwrap()); dictionary.insert(entry, dictionary_count); - element = c.to_string(); + element = vec![*c]; dictionary_count += 1; } @@ -372,16 +372,16 @@ fn compress_lzw(data: &[u8], size: usize, last: String) -> (usize, Vec, Str let last_element = element; if compressed.len() == 0 { if last_element.len() != 0 { - for c in last_element.chars() { - compressed.push(*dictionary.get(&c.to_string()).unwrap()); + for c in last_element { + compressed.push(*dictionary.get(&vec![c]).unwrap()); } } - return (count, compressed, String::new()) + return (count, compressed, Vec::new()) } else if compressed.len() < size { if last_element.len() != 0 { compressed.push(*dictionary.get(&last_element).unwrap()); } - return (count, compressed, String::new()) + return (count, compressed, Vec::new()) } (count, compressed, last_element) diff --git a/cz/src/dynamic.rs b/cz/src/dynamic.rs index 1e7643e..e7b7dce 100644 --- a/cz/src/dynamic.rs +++ b/cz/src/dynamic.rs @@ -63,6 +63,9 @@ impl DynamicCz { 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; 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