Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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(())
}