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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
pub mod args;
pub mod common;
use crate::args::StackPngArgs;
use crate::common::print_error;
use image::{imageops::FilterType, DynamicImage, ImageBuffer, Rgba};
use serde_json::json;
pub struct ImageResult {
pub image: DynamicImage,
pub width: u32,
pub height: u32,
}
pub fn process_images(args: &StackPngArgs) -> ImageResult {
let mut img_results: Vec<_> = args
.files
.iter()
.map(|f| match image::open(&f) {
Err(e) => print_error(format!("{e:?}\n\nCould not open/parse image `{}`!", f)),
Ok(i) => i,
})
.collect();
let first = img_results.first().unwrap();
let width = first.width();
let height = first.height();
if !img_results
.iter()
.all(|i| i.width() == width && i.height() == height)
{
if !args.resize {
print_error(format!(
"All images in sequence must have the same aspect ratio!\n\
To allow resizing images with different dimensions, use the `--resize` flag.\n\
\n\
First image in sequence has dimensions {width}x{height} (WxH), but not all images matched these dimensions!",
))
}
img_results.iter_mut().for_each(|i| {
if i.width() == width && i.height() == height {
return;
}
*i = if args.ignore_aspect_ratio {
i.resize_exact(width, height, FilterType::Nearest)
} else {
i.resize(width, height, FilterType::Nearest)
}
})
}
if !img_results
.iter()
.all(|i| i.width() == width && i.height() == height)
{
print_error(format!(
"All images in sequence must have the same dimensions!\n\
Tried to resize preserving aspect ratios, but failed since not all images had the same aspect ratio. Use the `--ignore-aspect-ratio` flag to force images to resize.\n\
\n\
First image in sequence has dimensions {width}x{height} (WxH) and aspect ratio {:.3?}, but not all images matched these dimensions!",
width as f64 / height as f64
))
}
let mut img = ImageBuffer::from_fn(width, height * img_results.len() as u32, |_, _| {
Rgba([0, 0, 0, 0])
});
for (index, image) in img_results.iter().enumerate() {
image::imageops::overlay(&mut img, image, 0, (height * (index as u32)) as i64);
}
ImageResult {
image: DynamicImage::from(img),
width,
height,
}
}
pub fn create_mc_meta(args: &StackPngArgs, image: &ImageResult) -> String {
let mcmeta = json!({
"animation": {
"frametime": args.frame_time,
"width": image.width,
"height": image.height
}
});
mcmeta.to_string()
}