Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(examples): add example of library usage #62

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ package-lock.json
node_modules/
yarn.lock
yarn-error.log

# outputs that may be created by running the examples
*.jpg
*.png
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: check-byte-order-marker
- id: fix-byte-order-marker
- id: check-case-conflict
- id: check-merge-conflict
- id: check-symlinks
Expand Down
28 changes: 21 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# libvips-rust-bindings

Rust bindings for libvips. Generated from `version 8.14.5`.

This is a safe wrapper for [libvips](https://libvips.github.io/libvips/) C library. It is made on top of the C API and based on the introspection API results.
Expand All @@ -17,9 +18,9 @@ Both the bindings and the generated operations were pushed to crates.io with mos

Everything in ops.rs and error.rs (and of course bindings.rs) is generated programmatically. You need to make changes for these files to the builder for these. Then, run the following shell scripts from the `generator` directory.

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

## A note to the maintainers
Expand All @@ -34,9 +35,9 @@ Vips needs to be initialized and shut down, this struct does this job, though yo

Not all functions were implemented, so if you need some that are not yet there, feel free to open a PR or an issue (it is pretty straight forward to add the ones that needs to be manual).

Many vips operations have optional arguments. The ones that have have been implemented with too variants by this crate. Basically there'll be a regular call with only the required parameters and an additional with the suffix `with_opts` which will take a struct holding the defaults.
Many vips operations have optional arguments. The ones that have have been implemented with too variants by this crate. Basically there'll be a regular call with only the required parameters and an additional with the suffix `with_opts` which will take a struct holding the defaults.

The structs's names for those defaults are named after the operation name in `class case` plus the suffix `Options`. All the struct implements the `Default` trait, so you can construct them like this for example:
The structs's names for those defaults are named after the operation name in `class case` plus the suffix `Options`. All the struct implements the `Default` trait, so you can construct them like this for example:

```rust
let options = ops::Composite2Options {
Expand All @@ -46,13 +47,16 @@ let options = ops::Composite2Options {
}
```

In the moment the error messages are not being appended to the errors themselves. They're in the libvips error buffer. The error buffer operations are implented inside the `VipsApps` struct.
In the moment the error messages are not being appended to the errors themselves. They're in the libvips error buffer. The error buffer operations are implented inside the `VipsApps` struct.

Most (if not all) vips operations don't mutate the `VipsImage` object, so they'll return a new object for this. The implementation of `VipsImage` in this crate takes care of freeing the internal pointer after it is dropped. <span style="color:red">Be aware that the VipsImage object is not thread safe in the moment.</span> I'll investigate what is happening and provide a solution for it in the future.
Most (if not all) vips operations don't mutate the `VipsImage` object, so they'll return a new object for this. The implementation of `VipsImage` in this crate takes care of freeing the internal pointer after it is dropped. <span style="color:red">Be aware that the VipsImage object is not thread safe in the moment.</span> I'll investigate what is happening and provide a solution for it in the future.

### Example

In the following code snippet we move load a JPEG file from the file system and then transforming it by reducing the scale by 50% and saving it as a .

```rust
// examples/jpeg_to_png.rs
use libvips::{ops, VipsImage, VipsApp};

fn main() {
Expand Down Expand Up @@ -87,3 +91,13 @@ fn main() {
}
}
```

The above example can be run from the console using cargo.

```console
$ cargo run --examples jpeg_to_png.rs
Compiling libvips v1.6.1 (<REDACTED>/libvips-rust-bindings)
Finished dev [unoptimized + debuginfo] target(s) in 3.29s
Running `target/debug/examples/jpeg_to_png`
./output.png was created in the repository root!
```
71 changes: 71 additions & 0 deletions examples/png_to_jpeg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use libvips::{ops, VipsApp, VipsImage};
use std::env;
use std::path::Path;

// Load a JPEG file, transform and convert it to PNG
// Use the following cargo command to run this example
// cargo run --examples jpeg_to_png

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);
let cargo_toml_dir = env::current_dir()
.expect("Where is my Cargo.toml file?")
.display()
.to_string();
let image_path = Path::new("resources/test.png")
.display()
.to_string();

// loads an image from file
let image = VipsImage::new_from_file(&format!(
"{}/{}",
cargo_toml_dir, image_path
))
.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,
interlace: true,
optimize_coding: true,
optimize_scans: true,
..ops::JpegsaveOptions::default()
};

// alternatively you can use `jpegsave` that will use the default options
match ops::jpegsave_with_opts(
&resized,
&format!(
"{}/{}",
cargo_toml_dir, "png_to_jpeg.jpg"
),
&options,
) {
Err(_) => println!(
"error: {}",
app.error_buffer()
.unwrap()
),
Ok(_) => println!("./png_to_jpeg.jpg was created in the repository root!"),
}
}
Binary file added resources/test.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.