use clap::Parser; use png_to_svg::cli::Cli; use png_to_svg::formatting::El; use png_to_svg::output::create_output_canvas; use rayon::prelude::{ParallelBridge, ParallelIterator}; fn to_opacity(value: u8) -> f32 { value as f32 / 255.0 } fn main() -> anyhow::Result<()> { let args = Cli::parse(); println!("{:?}", args); let input = image::open(args.input_file)?; let input = input .as_rgba8() .ok_or_else(|| anyhow::Error::msg("Invalid input format"))?; let (sender, thread_handle) = create_output_canvas( input.width() as usize * args.scale, input.height() as usize * args.scale, args.output_file, ); let pixel_width = input.width() as usize; input .pixels() .into_iter() .enumerate() .map(move |(idx, pixel)| (idx, pixel, sender.clone())) .par_bridge() .for_each(move |(index, pixel, sender)| { // Skip blank pixels if pixel.0.iter().all(|val| *val == 0) { return; } let (x, y) = (index % pixel_width, index / pixel_width); let attributes = vec![ ("width", format!("{}", args.scale)).into(), ("height", format!("{}", args.scale)).into(), ("x", format!("{}", x * args.scale)).into(), ("y", format!("{}", y * args.scale)).into(), ( "fill", format!("rgb({}, {}, {})", pixel.0[0], pixel.0[1], pixel.0[2]), ) .into(), ("fill-opacity", format!("{}", to_opacity(pixel.0[3]))).into(), ]; let _ = sender.send(El::create("rect", attributes.as_slice())); }); thread_handle .join() .map_err(|_| anyhow::Error::msg("The image writing thread failed, somehow"))??; Ok(()) }