/
main.rs
134 lines (119 loc) · 4.51 KB
/
main.rs
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
mod file_util;
mod options;
mod print;
mod profiles;
#[cfg(test)]
mod tests;
use options::Opt;
use stitchy_core::{Stitch, ImageFiles, FilePathWithMetadata, OrderBy, TakeFrom, util::make_size_string};
use clap::Parser;
fn main() {
// Get command line args, check for flags that merely print to the console and exit
let mut opt = Opt::parse();
if opt.help {
print::help();
return;
}
if opt.version {
print::version();
return;
}
if opt.printdefaults {
print::defaults();
return;
}
// Save options if requested, or try to load stored options otherwise
let mut previous_options: Option<Opt> = None;
if opt.setdefaults {
if let Some(error) = opt.check_for_basic_errors(&None) {
println!("Cannot save settings. {}", error);
return;
}
if let Some(json) = opt.serialise() {
profiles::Profile::main().write_string(json);
}
} else if opt.cleardefaults {
profiles::Profile::main().delete();
} else if let Some(json) = profiles::Profile::main().into_string() {
if let Some(profile_opt) = Opt::deserialise_as_current(&json) {
opt = opt.mix_in(&profile_opt);
previous_options = Some(profile_opt);
}
}
// Check conditions where the user did not request a number of files, but this is allowed
// because some operations on the defaults file does not require that files are processed now
if opt.number_of_files.is_none() && (opt.setdefaults || opt.cleardefaults) {
return;
}
// Perform simple validation
if let Some(error) = opt.check_for_basic_errors(&previous_options) {
println!("{}", error);
return;
}
// Ensure some number of files was provided
if let Some(error) = opt.check_number_of_files_provided() {
println!("{}", error);
return;
}
// Pre-use preparations
opt.prepare_for_use();
// Call function to do all the file processing, print final messages here
match run_with_options(opt) {
Ok(msg) => println!("{}", msg),
Err(msg) => println!("{}", msg)
}
}
/// Runs Stitchy using the supplied options. The options should have been checked for basic errors
/// and prepared for use before calling this function.
fn run_with_options(opt: Opt) -> Result<String, String> {
// Determine the list of files to use as input
let number_of_files = opt.number_of_files.ok_or_else(|| String::from(
"Internal error - sorting files before verifying that a number was supplied"))?;
let unsorted_sources = match &opt.input_dir {
Some(source_path) => {
let dir = file_util::to_absolute_dir(source_path)?;
ImageFiles::<FilePathWithMetadata>::builder()
.add_directory(dir)?
.build()?
}
None => {
ImageFiles::<FilePathWithMetadata>::builder()
.add_current_directory(vec![])?
.build()?
}
};
let image_sources = unsorted_sources
.sort_and_truncate_by(
number_of_files,
opt.order.unwrap_or(OrderBy::Latest),
opt.take_from.unwrap_or(TakeFrom::Start),
opt.reverse
)?;
// Determine the output path, considering the input files if need be
let total_source_size = image_sources.total_size();
let output_format = file_util::determine_output_format(&image_sources, &opt)?;
let output_file_path = file_util::next_available_output(&image_sources, &opt)?;
// Open the image files and process them to make the output image
let images = image_sources.into_image_contents(true)?;
let output = Stitch::builder()
.images(images)
.alignment(opt.get_alignment())
.width_limit(opt.maxw as u32)
.height_limit(opt.maxh as u32)
.stitch()?;
// Write the output file, returning a success message or an error message
file_util::write_image_to_file(output, &output_file_path, Some(output_format), opt.quality)?;
let output_string = match file_util::size_of_file(&output_file_path) {
Ok(size_bytes) =>
format!(
"Created file: {:?}, {}, ({})",
output_file_path.file_name().unwrap(),
make_size_string(size_bytes),
file_util::make_ratio_string(total_source_size, size_bytes)),
Err(_) =>
format!(
"Created file: {:?}",
output_file_path.file_name().unwrap())
};
Ok(output_string)
}