image_compression/
lib.rs

1use std::{env, fmt};
2use std::fs::{self, File};
3use std::path::Path;
4use std::time::{Duration, Instant};
5
6use image::imageops::FilterType;
7use image::ImageOutputFormat::{Jpeg, Png};
8
9struct Elapsed(Duration);
10
11impl Elapsed {
12    fn from(start: &Instant) -> Self {
13        Elapsed(start.elapsed())
14    }
15}
16
17impl fmt::Display for Elapsed {
18    fn fmt(&self, out: &mut fmt::Formatter) -> Result<(), fmt::Error> {
19        match (self.0.as_secs(), self.0.subsec_nanos()) {
20            (0, n) if n < 1000 => write!(out, "{} ns", n),
21            (0, n) if n < 1000_000 => write!(out, "{} µs", n / 1000),
22            (0, n) => write!(out, "{} ms", n / 1000_000),
23            (s, n) if s < 10 => write!(out, "{}.{:02} s", s, n / 10_000_000),
24            (s, _) => write!(out, "{} s", s),
25        }
26    }
27}
28
29pub fn dir_compression(in_dir: &Path, out_dir: &Path) {
30    for entry in in_dir.read_dir().expect("read_dir call failed") {
31        file_compression(entry.unwrap().path().as_path(), out_dir);
32    }
33}
34
35pub fn file_compression(in_file: &Path, out_dir: &Path) {
36    let extends: Vec<&str> = vec!["png", "jpg", "jpeg"];
37    if in_file.is_file() {
38        let extension = match in_file.extension() {
39            Some(ext) => ext.to_str().unwrap(),
40            _ => return,
41        };
42        if extends.contains(&extension) {//文件后缀判断
43            let file_name = in_file.file_name().unwrap().to_str().unwrap();
44            let timer = Instant::now();
45            println!("target by {} in {}", file_name, Elapsed::from(&timer));
46            let tiny = match image::open(in_file) {
47                Ok(image) => image,
48                _ => {
49                    println!(
50                        "{} 压缩失败,图片格式有误,可以使用画图工具打开重新保存",
51                        file_name
52                    );
53                    return;
54                }
55            };
56            let tiny = match image::open(in_file) {
57                Ok(image) => image,
58                _ => {
59                    println!(
60                        "{} 压缩失败,图片格式有误,可以使用画图工具打开重新保存",
61                        file_name
62                    );
63                    return;
64                }
65            };
66            let scaled = tiny.resize(800, 600, FilterType::Triangle);//使用这个算法进行压缩
67            let mut output = File::create(out_dir.join(file_name).as_path()).unwrap();
68            scaled.write_to(&mut output, Png).unwrap();//都输出成jpg格式
69        }
70    }
71}