Allow conversion and keeping dates #70
This commit is contained in:
parent
444faa3d9b
commit
f76e8d8a31
|
@ -145,8 +145,9 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "caesiumclt"
|
name = "caesiumclt"
|
||||||
version = "0.19.3"
|
version = "0.20.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"filetime",
|
||||||
"human_bytes",
|
"human_bytes",
|
||||||
"indicatif",
|
"indicatif",
|
||||||
"infer",
|
"infer",
|
||||||
|
@ -542,9 +543,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "infer"
|
name = "infer"
|
||||||
version = "0.15.0"
|
version = "0.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cb33622da908807a06f9513c19b3c1ad50fab3e4137d82a78107d502075aa199"
|
checksum = "bc150e5ce2330295b8616ce0e3f53250e53af31759a9dbedad1621ba29151847"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfb",
|
"cfb",
|
||||||
]
|
]
|
||||||
|
@ -593,8 +594,8 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libcaesium"
|
name = "libcaesium"
|
||||||
version = "0.15.4"
|
version = "0.16.1"
|
||||||
source = "git+https://github.com/Lymphatus/libcaesium?tag=0.15.4#bf5fcec976da5d2526c235e93cadd4ef4fb73581"
|
source = "git+https://github.com/Lymphatus/libcaesium?rev=0.16.1#ef402d1a1dfe417907f2379cab88c2e3b245ac4c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"gifsicle",
|
"gifsicle",
|
||||||
|
@ -678,9 +679,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mozjpeg-sys"
|
name = "mozjpeg-sys"
|
||||||
version = "1.1.1"
|
version = "2.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "74c4fe4006093b2948ccb37bb413b6b9da2d654a9a50419b5861b0f4e8ad4da9"
|
checksum = "9cf2a48f2f79f47fcce75d125d112e113a93f4a6f3cd8cc5b4cd6e16589d050f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"dunce",
|
"dunce",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "caesiumclt"
|
name = "caesiumclt"
|
||||||
version = "0.19.3"
|
version = "0.20.0"
|
||||||
authors = ["Matteo Paonessa <matteo.paonessa@gmail.com>"]
|
authors = ["Matteo Paonessa <matteo.paonessa@gmail.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
@ -10,8 +10,9 @@ structopt = "0.3"
|
||||||
indicatif = "0.17"
|
indicatif = "0.17"
|
||||||
walkdir = "2.5"
|
walkdir = "2.5"
|
||||||
num_cpus = "1.16"
|
num_cpus = "1.16"
|
||||||
infer = "0.15"
|
infer = "0.16"
|
||||||
rayon = "1.10"
|
rayon = "1.10"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
human_bytes = { version = "0.4", default-features = false }
|
human_bytes = { version = "0.4", default-features = false }
|
||||||
libcaesium = { git = "https://github.com/Lymphatus/libcaesium", tag = "0.15.4" }
|
filetime = "0.2"
|
||||||
|
libcaesium = { git = "https://github.com/Lymphatus/libcaesium", rev = "0.16.1" }
|
72
src/main.rs
72
src/main.rs
|
@ -1,7 +1,8 @@
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
use caesium::SupportedFileTypes;
|
||||||
|
use filetime::{FileTime, set_file_times};
|
||||||
use human_bytes::human_bytes;
|
use human_bytes::human_bytes;
|
||||||
use indicatif::ProgressBar;
|
use indicatif::ProgressBar;
|
||||||
use indicatif::ProgressDrawTarget;
|
use indicatif::ProgressDrawTarget;
|
||||||
|
@ -27,12 +28,21 @@ struct CompressionResult {
|
||||||
pub result: bool,
|
pub result: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct OutputFormat {
|
||||||
|
pub file_type: SupportedFileTypes,
|
||||||
|
pub extension: String
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let opt = options::get_opts();
|
let opt = options::get_opts();
|
||||||
let mut verbose = opt.verbose;
|
let mut verbose = opt.verbose;
|
||||||
let args = opt.files;
|
let args = opt.files;
|
||||||
let dry_run = opt.dry_run;
|
let dry_run = opt.dry_run;
|
||||||
let output_dir = opt.output;
|
let output_dir = opt.output;
|
||||||
|
let output_format = map_output_format(opt.output_format);
|
||||||
|
let convert = output_format.file_type != SupportedFileTypes::Unkn;
|
||||||
|
let keep_dates = opt.keep_dates;
|
||||||
|
|
||||||
if opt.quiet {
|
if opt.quiet {
|
||||||
verbose = 0;
|
verbose = 0;
|
||||||
}
|
}
|
||||||
|
@ -86,12 +96,13 @@ fn main() {
|
||||||
|
|
||||||
let results = Arc::new(Mutex::new(Vec::new()));
|
let results = Arc::new(Mutex::new(Vec::new()));
|
||||||
files.par_iter().for_each(|input_file| {
|
files.par_iter().for_each(|input_file| {
|
||||||
let input_size = match fs::metadata(input_file) {
|
let input_file_metadata = fs::metadata(input_file);
|
||||||
Ok(s) => s.len(),
|
let (input_size, input_mtime, input_atime) = match input_file_metadata {
|
||||||
|
Ok(s) => (s.len(), FileTime::from_last_modification_time(&s), FileTime::from_last_access_time(&s)),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let error_message = format!("Cannot get file size for {}, Error: {}", input_file.display(), e);
|
let error_message = format!("Cannot get file size for {}, Error: {}", input_file.display(), e);
|
||||||
log(error_message.as_str(), 202, Warning, verbose);
|
log(error_message.as_str(), 202, Warning, verbose);
|
||||||
0
|
(0, FileTime::now(), FileTime::now())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -130,7 +141,11 @@ fn main() {
|
||||||
.map(char::from)
|
.map(char::from)
|
||||||
.collect();
|
.collect();
|
||||||
let random_suffixed_name = format!("{}.{}", filename_str, random_suffix);
|
let random_suffixed_name = format!("{}.{}", filename_str, random_suffix);
|
||||||
let final_output_full_path = output_dir.clone().join(filename);
|
let mut final_output_full_path = output_dir.clone().join(filename);
|
||||||
|
if convert {
|
||||||
|
final_output_full_path.set_extension(output_format.extension.clone());
|
||||||
|
}
|
||||||
|
|
||||||
let output_full_path = output_dir.clone().join(random_suffixed_name);
|
let output_full_path = output_dir.clone().join(random_suffixed_name);
|
||||||
let output_full_dir = output_full_path.parent().unwrap_or_else(|| Path::new("/"));
|
let output_full_dir = output_full_path.parent().unwrap_or_else(|| Path::new("/"));
|
||||||
compression_result.output_path = final_output_full_path.display().to_string();
|
compression_result.output_path = final_output_full_path.display().to_string();
|
||||||
|
@ -156,7 +171,13 @@ fn main() {
|
||||||
Some(ofp) => ofp
|
Some(ofp) => ofp
|
||||||
};
|
};
|
||||||
if !dry_run {
|
if !dry_run {
|
||||||
match caesium::compress(input_full_path.to_string(), output_full_path_str.to_string(), &compression_parameters) {
|
let result = if convert {
|
||||||
|
caesium::convert(input_full_path.to_string(), output_full_path_str.to_string(), &compression_parameters, output_format.file_type)
|
||||||
|
} else {
|
||||||
|
caesium::compress(input_full_path.to_string(), output_full_path_str.to_string(), &compression_parameters)
|
||||||
|
};
|
||||||
|
|
||||||
|
match result {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
compression_result.result = true;
|
compression_result.result = true;
|
||||||
let output_metadata = fs::metadata(output_full_path.clone());
|
let output_metadata = fs::metadata(output_full_path.clone());
|
||||||
|
@ -183,7 +204,7 @@ fn main() {
|
||||||
};
|
};
|
||||||
final_output_size = existing_file_size;
|
final_output_size = existing_file_size;
|
||||||
} else {
|
} else {
|
||||||
match fs::rename(output_full_path, final_output_full_path) {
|
match fs::rename(output_full_path, final_output_full_path.clone()) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
compression_result.error = format!("Cannot rename existing file. Error: {}.", e);
|
compression_result.error = format!("Cannot rename existing file. Error: {}.", e);
|
||||||
|
@ -192,7 +213,7 @@ fn main() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match fs::rename(output_full_path, final_output_full_path) {
|
match fs::rename(output_full_path, final_output_full_path.clone()) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
compression_result.error = format!("Cannot rename existing file. Error: {}.", e);
|
compression_result.error = format!("Cannot rename existing file. Error: {}.", e);
|
||||||
|
@ -201,6 +222,16 @@ fn main() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
compression_result.compressed_size = final_output_size;
|
compression_result.compressed_size = final_output_size;
|
||||||
|
if compression_result.result && keep_dates {
|
||||||
|
|
||||||
|
|
||||||
|
match set_file_times(final_output_full_path, input_atime, input_mtime) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(_) => {
|
||||||
|
compression_result.error = "Cannot set original file dates.".into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
results.lock().unwrap().push(compression_result);
|
results.lock().unwrap().push(compression_result);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -273,3 +304,28 @@ fn setup_progress_bar(len: u64, verbose: u8) -> ProgressBar {
|
||||||
|
|
||||||
progress_bar
|
progress_bar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn map_output_format(format: String) -> OutputFormat {
|
||||||
|
match format.to_lowercase().as_str() {
|
||||||
|
"jpg|jpeg" => OutputFormat {
|
||||||
|
file_type: SupportedFileTypes::Jpeg,
|
||||||
|
extension: format
|
||||||
|
},
|
||||||
|
"png" => OutputFormat {
|
||||||
|
file_type: SupportedFileTypes::Png,
|
||||||
|
extension: format
|
||||||
|
},
|
||||||
|
"webp" => OutputFormat {
|
||||||
|
file_type: SupportedFileTypes::WebP,
|
||||||
|
extension: format
|
||||||
|
},
|
||||||
|
"tiff|tif" => OutputFormat {
|
||||||
|
file_type: SupportedFileTypes::Tiff,
|
||||||
|
extension: format
|
||||||
|
},
|
||||||
|
_ =>OutputFormat {
|
||||||
|
file_type: SupportedFileTypes::Unkn,
|
||||||
|
extension: "".to_string()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use structopt::clap::arg_enum;
|
use structopt::clap::arg_enum;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
|
@ -16,7 +15,7 @@ arg_enum! {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(StructOpt, Debug)]
|
#[derive(StructOpt)]
|
||||||
#[structopt(name = "", about = "CaesiumCLT - Command Line Tools for image compression")]
|
#[structopt(name = "", about = "CaesiumCLT - Command Line Tools for image compression")]
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
/// sets output file quality between [0-100], 0 for optimization
|
/// sets output file quality between [0-100], 0 for optimization
|
||||||
|
@ -52,7 +51,7 @@ pub struct Opt {
|
||||||
pub overwrite: OverwritePolicy,
|
pub overwrite: OverwritePolicy,
|
||||||
|
|
||||||
/// do not compress files but just show output paths
|
/// do not compress files but just show output paths
|
||||||
#[structopt(short = "d", long)]
|
#[structopt(long = "dry-run", short = "d", long)]
|
||||||
pub dry_run: bool,
|
pub dry_run: bool,
|
||||||
|
|
||||||
/// suppress all output
|
/// suppress all output
|
||||||
|
@ -71,6 +70,14 @@ pub struct Opt {
|
||||||
#[structopt(long, default_value = "1")]
|
#[structopt(long, default_value = "1")]
|
||||||
pub verbose: u8,
|
pub verbose: u8,
|
||||||
|
|
||||||
|
/// convert the image to the selected format (jpg, png, webp, tiff)
|
||||||
|
#[structopt(long = "output-format", default_value = "none")]
|
||||||
|
pub output_format: String,
|
||||||
|
|
||||||
|
/// keep original file date information
|
||||||
|
#[structopt(long = "keep-dates")]
|
||||||
|
pub keep_dates: bool,
|
||||||
|
|
||||||
/// Files to process
|
/// Files to process
|
||||||
#[structopt(name = "FILE", parse(from_os_str))]
|
#[structopt(name = "FILE", parse(from_os_str))]
|
||||||
pub files: Vec<PathBuf>,
|
pub files: Vec<PathBuf>,
|
||||||
|
|
Loading…
Reference in New Issue