mod color_map_utils;
use std::fs::File;
use std::io::Read;
use std::io::Cursor;
use flate2::read::GzDecoder;
use image::{ImageBuffer, Rgb, RgbImage};
use color_map_utils::map_block_color;
use color_map_utils::extract_colors_data;
use wasm_bindgen::prelude::*;
pub fn process_image_file(input_path: &str, output_path: &str) -> Result<(), String> {
let file = File::open(input_path).map_err(|_| "Failed to open input file")?;
let mut decoder = GzDecoder::new(file);
let mut buffer = Vec::new();
decoder.read_to_end(&mut buffer).map_err(|_| "Failed to read compressed data")?;
let value = fastnbt::from_bytes(&buffer).map_err(|_| "Failed to parse NBT data")?;
println!("value: {:?}", value);
let color_data = extract_colors_data(&value).ok_or("No color data found in NBT")?;
create_and_save_image(&color_data, output_path)
}
pub fn create_and_save_image(color_data: &[u8], output_path: &str) -> Result<(), String> {
let image_size = compute_image_size(color_data.len())?;
let image = build_image(color_data, image_size, image_size);
image.save(output_path).map_err(|_| "Failed to save image".to_string())
}
fn compute_image_size(data_length: usize) -> Result<usize, String> {
let side_length = (data_length as f64).sqrt() as usize;
if side_length * side_length != data_length {
Err("Data does not contain a perfect square of pixels.".into())
} else {
Ok(side_length)
}
}
fn build_image(data: &[u8], width: usize, height: usize) -> RgbImage {
let mut image: RgbImage = ImageBuffer::new(width as u32, height as u32);
for (y, row) in data.chunks(width).enumerate() {
for (x, &block_id) in row.iter().enumerate() {
let color = map_block_color(block_id);
image.put_pixel(x as u32, y as u32, Rgb([color.0, color.1, color.2]));
}
}
image
}
#[wasm_bindgen]
pub fn process_image_from_memory(input_data: &[u8]) -> Result<Vec<u8>, JsValue> {
let mut decoder = GzDecoder::new(input_data);
let mut buffer = Vec::new();
decoder.read_to_end(&mut buffer).map_err(|_| JsValue::from_str("Failed to read compressed data"))?;
let value = fastnbt::from_bytes(&buffer).map_err(|_| JsValue::from_str("Failed to parse NBT data"))?;
let color_data = extract_colors_data(&value).ok_or(JsValue::from_str("No color data found in NBT"))?;
create_image_bytes(&color_data)
}
fn create_image_bytes(color_data: &[u8]) -> Result<Vec<u8>, JsValue> {
let image_size = compute_image_size(color_data.len()).map_err(|e| JsValue::from_str(&e))?;
let image = build_image(color_data, image_size, image_size);
let mut image_bytes = Vec::new();
let mut cursor = Cursor::new(&mut image_bytes);
image.write_to(&mut cursor, image::ImageOutputFormat::Png).map_err(|_| JsValue::from_str("Failed to write image to buffer"))?;
Ok(image_bytes)
}