use std::collections::HashMap;
use crate::*;
use image::{io::Reader as ImageReader, DynamicImage};
#[derive(Debug)]
pub(crate) struct ImageBuilder {
pub frames_h:u8,
pub frames_v:u8,
pub cols_per_frame:u8,
pub rows_per_frame:u8,
pub width:usize,
pub height:usize,
pub pixels :Vec<u8>,
}
impl ImageBuilder {
pub fn from_image(specs:Specs, file_name:&str, frames_layout: Option<(u8, u8)>, palette:&mut Palette, palette_hash:&mut HashMap<Color32, u8>) -> ImageBuilder {
let split = file_name.split('/');
let last = split.last().unwrap().to_string();
let mut last_split = last.split('.');
let asset_name = last_split.next().unwrap().to_string();
println!("cargo:warning=Converting image {}", asset_name);
let mut img_rgba = ImageReader::open(file_name)
.unwrap()
.decode()
.unwrap();
if let DynamicImage::ImageRgba8{..} = img_rgba {
println!("cargo:warning=Image for '{}' is Rgba8, proceeding... ", asset_name);
} else {
println!("cargo:warning=Image for '{}' is not Rgba8, converting... ", asset_name);
img_rgba = DynamicImage::from(img_rgba.to_rgba8());
}
let (width,height) = (img_rgba.width() as usize, img_rgba.height() as usize);
if ((width % specs.tile_width as usize) != 0) || ((height % specs.tile_height as usize) != 0) {
panic!("Build error: PNG image cannot fit into {}x{} tiles!", specs.tile_width, specs.tile_height)
}
let (cols_per_frame, rows_per_frame) = match frames_layout {
Some(value) => (value.0, value.1),
None => (1, 1),
};
let frames_h = u8::try_from(
(width / cols_per_frame as usize)/specs.tile_width as usize
).ok().unwrap();
let frames_v = u8::try_from(
(height / rows_per_frame as usize)/specs.tile_height as usize
).ok().unwrap();
println!(
"cargo:warning= Tilifying '{}' to {} frames with {}x{} tiles",
asset_name,
frames_h as usize * frames_v as usize,
cols_per_frame,
rows_per_frame
);
ImageBuilder {
frames_h,
frames_v,
cols_per_frame,
rows_per_frame,
width,
height,
pixels: Self::palletize(img_rgba, palette, palette_hash),
}
}
pub fn palletize(img:DynamicImage, palette:&mut Palette, color_hash:&mut HashMap<Color32, u8>) -> Vec<u8> {
let mut pixels = vec![];
for y in 0 .. img.height() as usize{
for x in 0 .. img.width() as usize{
let color = {
let buf = img.as_bytes();
let index = x + (y * img.width() as usize);
let buf_index = index * 4;
let r = buf[buf_index];
let g = buf[buf_index+1];
let b = buf[buf_index+2];
let a = buf[buf_index+3];
let rgba_color = if a < 255 {
Color32{r:0, g:0, b:0, a:0} } else {
Color32{r, g, b, a}
};
if color_hash.contains_key(&rgba_color) {
*color_hash.get(&rgba_color).unwrap()
} else {
let color_head = u8::try_from(color_hash.len()).ok().unwrap();
println!("cargo:warning= Inserting Palette {:02} -> {:02}: {:?}", palette.id(), color_head, rgba_color);
color_hash.insert(rgba_color, color_head);
palette.push(rgba_color);
color_head
}
};
pixels.push(color)
}
}
pixels
}
}