1mod color_map_utils;
4
5use std::fs::File;
6use std::io::Read;
7use std::io::Cursor;
8use flate2::read::GzDecoder;
9use image::{ImageBuffer, Rgb, RgbImage};
10use color_map_utils::map_block_color;
11use color_map_utils::extract_colors_data;
12use wasm_bindgen::prelude::*;
13
14pub fn process_image_file(input_path: &str, output_path: &str) -> Result<(), String> {
26 let file = File::open(input_path).map_err(|_| "Failed to open input file")?;
27 let mut decoder = GzDecoder::new(file);
28 let mut buffer = Vec::new();
29 decoder.read_to_end(&mut buffer).map_err(|_| "Failed to read compressed data")?;
30 let value = fastnbt::from_bytes(&buffer).map_err(|_| "Failed to parse NBT data")?;
31 println!("value: {:?}", value);
32 let color_data = extract_colors_data(&value).ok_or("No color data found in NBT")?;
33 create_and_save_image(&color_data, output_path)
34}
35
36pub fn create_and_save_image(color_data: &[u8], output_path: &str) -> Result<(), String> {
48 let image_size = compute_image_size(color_data.len())?;
49 let image = build_image(color_data, image_size, image_size);
50 image.save(output_path).map_err(|_| "Failed to save image".to_string())
51}
52
53fn compute_image_size(data_length: usize) -> Result<usize, String> {
64 let side_length = (data_length as f64).sqrt() as usize;
65 if side_length * side_length != data_length {
66 Err("Data does not contain a perfect square of pixels.".into())
67 } else {
68 Ok(side_length)
69 }
70}
71
72fn build_image(data: &[u8], width: usize, height: usize) -> RgbImage {
84 let mut image: RgbImage = ImageBuffer::new(width as u32, height as u32);
85 for (y, row) in data.chunks(width).enumerate() {
86 for (x, &block_id) in row.iter().enumerate() {
87 let color = map_block_color(block_id);
88 image.put_pixel(x as u32, y as u32, Rgb([color.0, color.1, color.2]));
89 }
90 }
91 image
92}
93
94#[wasm_bindgen]
105pub fn process_image_from_memory(input_data: &[u8]) -> Result<Vec<u8>, JsValue> {
106 let mut decoder = GzDecoder::new(input_data);
107 let mut buffer = Vec::new();
108 decoder.read_to_end(&mut buffer).map_err(|_| JsValue::from_str("Failed to read compressed data"))?;
109 let value = fastnbt::from_bytes(&buffer).map_err(|_| JsValue::from_str("Failed to parse NBT data"))?;
110 let color_data = extract_colors_data(&value).ok_or(JsValue::from_str("No color data found in NBT"))?;
111 create_image_bytes(&color_data)
112}
113
114fn create_image_bytes(color_data: &[u8]) -> Result<Vec<u8>, JsValue> {
125 let image_size = compute_image_size(color_data.len()).map_err(|e| JsValue::from_str(&e))?;
126 let image = build_image(color_data, image_size, image_size);
127 let mut image_bytes = Vec::new();
128 let mut cursor = Cursor::new(&mut image_bytes);
129 image.write_to(&mut cursor, image::ImageOutputFormat::Png).map_err(|_| JsValue::from_str("Failed to write image to buffer"))?;
130 Ok(image_bytes)
131}