3个版本 (稳定)
1.0.1 | 2024年4月24日 |
---|---|
1.0.0 | 2024年4月15日 |
0.4.0 | 2024年4月6日 |
#377 在 图像
每月131次下载
29KB
400 行
jippigy
一个简单、多线程的JPEG压缩crate,由turbojpeg提供动力。
使用常见的2x2色度子采样进行压缩。
目前这个crate没有提供更精细的控制JPEG压缩的方式。更多选项请查看turbojpeg。
提供单线程或多线程压缩JPEG图像的方法。两种方法都通过img_parts crate保留原始JPEG的EXIF数据。
1.0.1 补丁
摘要
- 并行压缩返回的jpeg字节顺序与传入的顺序相同.
- 重新导出
ParallelIntoIterator
。 - 轻微优化。
有关更多详细信息,请参阅CHANGELOG.md。
构建turbojpeg
时出错?
问题通常与turbojpeg-sys
有关(参见这个问题和我在设置此crate CI时的尝试)。
要成功构建turbojpeg-sys
,您需要在系统中安装cmake
、C编译器(gcc、clang等)和NASM(参见:turbojpeg
's 要求)。更多详情请参阅turbojpeg-sys
's Building
部分。
示例
with_
方法是可选的。
使用 Single
进行单图像压缩
use jippigy::Single;
use image::{RgbImage, ImageFormat::Jpeg};
use std::io::Cursor;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut vec: Vec<u8> = Vec::new();
let img = RgbImage::new(1000, 1000);
let _write = img.write_to(&mut Cursor::new(&mut vec), Jpeg)?;
let _result: Vec<u8> = Single::from_bytes(vec)
.with_quality(80)
.build()
.compress()?;
Ok(())
}
使用 Parallel
进行多线程批量压缩
通过 into_iter()
,Parallel
转换为 ParallelIntoIterator
,它以相同的顺序返回传入的项目。这意味着,您可以像以下示例那样做,将JPEG文件的文件名保存到向量中,然后稍后与您创建的 ParallelIntoIterator
进行zip。
use jippigy::Parallel;
use std::path::PathBuf;
use tempdir::TempDir;
const TEST_DIR: &str = "./tests/images/";
fn main() -> Result<(), Box<dyn std::error::Error>> {
let image_dir_path = PathBuf::from(format!("{}", TEST_DIR));
let mut vec_of_bytes = Vec::new();
let mut list_of_names = Vec::new();
// push the filenames and read bytes into a separate vector.
for file in std::fs::read_dir(image_dir_path.clone())? {
let filepath = file?.path();
if filepath.is_file() {
let filename = filepath.clone()
.file_name()
.and_then(|osstr| osstr.to_str())
.and_then(|a| Some(a.to_string()))
.unwrap_or_default();
list_of_names.push(filename);
let read_file = std::fs::read(filepath);
vec_of_bytes.push(read_file?);
}
}
// this temporary directory is here for doctest purposes,
// but you will create your own directory.
let tempdir = TempDir::new("compressed")?;
// zip list_of_names vector with this iterator.
for zipped in Parallel::from_vec(vec_of_bytes)
.with_quality(50)
.with_device(4)
.build()
.into_iter()
.zip(list_of_names)
{
// saves compresssed JPEG with the original name.
let (compressed_bytes, name) = zipped;
if let Ok(bytes) = compressed_bytes {
std::fs::write(
image_dir_path
.join(tempdir.path())
.join(format!("{name}").as_str()),
bytes,
)?;
println!("saved: {name}");
}
}
tempdir.close()?;
Ok(())
}
依赖项
~11MB
~173K SLoC