18个稳定版本

8.3.0 2019年11月9日
1.7.0 2024年2月3日
1.6.1 2023年11月3日
1.5.1 2023年1月23日
1.1.2 2019年11月11日

#30 in 图像

Download history 293/week @ 2024-04-22 119/week @ 2024-04-29 124/week @ 2024-05-06 253/week @ 2024-05-13 357/week @ 2024-05-20 244/week @ 2024-05-27 239/week @ 2024-06-03 276/week @ 2024-06-10 363/week @ 2024-06-17 326/week @ 2024-06-24 257/week @ 2024-07-01 415/week @ 2024-07-08 208/week @ 2024-07-15 291/week @ 2024-07-22 272/week @ 2024-07-29 127/week @ 2024-08-05

904 每月下载量
2 crate 中使用

MIT 许可证

3MB
89K SLoC

libvips-rust-bindings

libvips的Rust绑定。从版本 version 8.14.5 生成。

这是libvips C库的安全包装。它基于C API和基于内省API结果。

这个crate本身没有文档,但与libvips本身相比没有逻辑或特殊行为。官方libvips 文档 中描述的所有调用和类型都只是翻译为Rust类型。所有默认值也得到尊重。

crate的编写方式

作为第一步,它运行bindgen来生成对C libvips库的不安全调用。在生成之后,编译并执行C代码。此代码内省操作并将它们作为文本输出。然后解析此文本,并生成 error.rsops.rs 模块。

这些基本上是在生成的绑定之上的安全包装。尽管没有广泛测试,但所有的内存清理应该按照预期工作。重要的是要注意,所有操作名称中的“vips”前缀都被移除了。

绑定和生成的操作都已推送到crates.io,其中包含了libvips的大多数可选依赖项。当调用依赖于这些子依赖项的函数(大多数与格式相关)时,请小心。

贡献

ops.rs和error.rs(以及当然,bindings.rs)中的所有内容都是通过程序生成的。您需要修改这些文件的构建器。然后,从 generator 目录运行以下shell脚本。

$ ./build.sh     # Builds the libvips-builder docker image
$ ./generate.sh  # Actually generates the bindings

对维护者的说明

crate的发布是手动完成的,并且在完成此操作后需要在仓库中更新 Cargo.lock 版本。一旦在仓库中添加了github actions,就可以在合并后发布。

如何使用它

本包的主要实体是VipsApp结构体。它不存储任何信息,只要它没有被销毁,vips 应该能够按预期工作。

Vips需要初始化和关闭,这个结构体就负责这项工作,尽管您不必手动关闭它,当持有VipsApp结构体值的变量被销毁时,它将自动完成。

并非所有函数都已实现,所以如果您需要尚未实现的某些功能,请随意提交一个PR或问题(添加需要手动实现的功能相对简单)。

许多vips操作都有可选参数。这个crate通过多种变体实现了这些操作。基本上,会有一个仅包含必要参数的常规调用和一个带有后缀with_opts的附加调用,后者将接受一个包含默认值的结构体。

这些默认值的结构体名称是以class case中的操作名称命名的,并加上后缀Options。所有结构体都实现了Default特质,所以您可以像这样构建它们,例如

let options = ops::Composite2Options {
    x: 10,
    y: 10,
    .. Composite2Options::default()
}

目前错误消息没有被附加到错误本身上。它们位于libvips错误缓冲区中。错误缓冲区操作是在VipsApps结构体中实现的。

大多数(如果不是所有)vips操作都不会修改VipsImage对象,所以它们将返回一个新的对象。这个crate中对VipsImage的实现会在它被销毁后处理内部指针的释放。请注意,目前VipsImage对象不是线程安全的。我将调查发生了什么,并在未来提供一个解决方案。

示例

use libvips::{ops, VipsImage, VipsApp};

fn main() {
    // this initializes the libvips library. it has to live as long as the application lives (or as long as you want to use the library within your app)
    // you can't have multiple objects of this type and when it is dropped it will call the libvips functions to free all internal structures.
    let app = VipsApp::new("Test Libvips", false).expect("Cannot initialize libvips");
    //set number of threads in libvips's threadpool
    app.concurrency_set(2);
    // loads an image from file
    let image = VipsImage::new_from_file("test.png").unwrap();

    // will resize the image and return a new instance.
    // libvips works most of the time with immutable objects, so it will return a new object
    // the VipsImage struct implements Drop, which will free the memory
    let resized = ops::resize(&image, 0.5).unwrap();

    //optional parameters
    let options = ops::JpegsaveOptions {
        q: 90,
        background: vec![255.0],
        strip: true,
        optimize_coding: true,
        optimize_scans: true,
        interlace: true,
        ..ops::JpegsaveOptions::default()
    };

    // alternatively you can use `jpegsave` that will use the default options
    match ops::jpegsave_with_opts(&resized, "output.jpeg",  &options) {
        Err(_) => println!("error: {}", app.error_buffer().unwrap()),
        Ok(_) => println!("Great Success!")
    }
}

依赖项

~0.3–0.9MB
~19K SLoC