使用rust的image库进行图片压缩

image库中有许多对图片处理方法.

可以参考一份中文翻译(https://www.jianshu.com/p/342c6a4bc7a1).

也可以去仓库地址中查看(https://github.com/image-rs/image),仓库中examples文件夹中放着一些例子,其中就有图片压缩的例子,提供了几种压缩算法的对比,下面的例子是改动了官方的例子,对文件夹中的图片文件进行压缩:

Cargo.toml设置,主要是依赖image库。

[package]
name = "image-compress-tools"
version = "0.1.0"
authors = [""]
edition = "2018"

[dependencies]
image = "0.22.3"
use image::{FilterType, JPEG, PNG};
use std::fmt;
use std::fs::{self, File};
use std::time::{Duration, Instant};

struct Elapsed(Duration);

impl Elapsed {
    fn from(start: &Instant) -> Self {
        Elapsed(start.elapsed())
    }
}

impl fmt::Display for Elapsed {
    fn fmt(&self, out: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match (self.0.as_secs(), self.0.subsec_nanos()) {
            (0, n) if n < 1000 => write!(out, "{} ns", n),
            (0, n) if n < 1000_000 => write!(out, "{} µs", n / 1000),
            (0, n) => write!(out, "{} ms", n / 1000_000),
            (s, n) if s < 10 => write!(out, "{}.{:02} s", s, n / 10_000_000),
            (s, _) => write!(out, "{} s", s),
        }
    }
}

fn main() {
    let exts: Vec<&str> = vec!["png", "jpg", "jpeg"];
    use std::path::Path;
    //以当前目录为源目录,以当前目录+scale目录
    let src_path = Path::new(".");
    let target_path = src_path.join("scale");
    let target_path = target_path.as_path();
    fs::create_dir_all(target_path).unwrap();
    for entry in src_path.read_dir().expect("read_dir call failed") {
        if let Ok(entry) = entry {
            let path = entry.path();
            let img_path = &path.as_path();
            if img_path.is_file() {
                let extension = match img_path.extension() {
                    Some(ext) => ext.to_str().unwrap(),
                    _ => break,
                };
                if exts.contains(&extension) {//文件后缀判断
                    let file_name = img_path.file_name().unwrap().to_str().unwrap();
                    let timer = Instant::now();
                    println!("target by {} in {}", file_name, Elapsed::from(&timer));
                    let tiny = match image::open(img_path) {
                        Ok(image) => image,
                        _ => {
                            println!(
                                "{} 压缩失败,图片格式有误,可以使用画图工具打开重新保存",
                                file_name
                            );
                            break;
                        }
                    };
                    let tiny = match image::open(img_path) {
                        Ok(image) => image,
                        _ => {
                            println!(
                                "{} 压缩失败,图片格式有误,可以使用画图工具打开重新保存",
                                file_name
                            );
                            break;
                        }
                    };
                    let scaled = tiny.resize(800, 600, FilterType::Triangle);//使用这个算法进行压缩
                    let mut output = File::create(target_path.join(file_name).as_path()).unwrap();
                    scaled.write_to(&mut output, JPEG).unwrap();//都输出成jpg格式
                }
            }
        }
    }
}

image图片格式支持:

目前该库基本支持市面上大部分的图片格式

  • PNG (encode & decode)
  • JPEG (encode & decode)
  • GIF (encode & decode)
  • BMP (encode & decode)
  • ICO (encode & decode)
  • TIFF (just decode)
  • webp (just decode)
  • PPM (encode & decode)

 image::open方法通过打开文件后,对文件名的后缀进行判断后调用对应的图片格式进行处理(这里就一个坑,一个真实是png的图片,文件后缀名是jpg,在打开时就会调用jpg相关处理方法,jpg会判断soi marker,却发现这个文件没有就会报错)。

官方的例子使用了几种压缩算法进行大小和效率对比,上面的例子使用了FilterType::Triangle。

        ("near", FilterType::Nearest),
        ("tri", FilterType::Triangle),
        ("xcmr", FilterType::CatmullRom),
        ("ygauss", FilterType::Gaussian),
        ("zlcz2", FilterType::Lanczos3),

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值