Giter Club home page Giter Club logo

libvips-rust-bindings's Introduction

libvips-rust-bindings

Rust bindings for libvips. Generated from version 8.14.5.

This is a safe wrapper for libvips C library. It is made on top of the C API and based on the introspection API results.

This crate itself is not documented, but it has no logic or special behavior in comparison to libvips itself. All calls and types described in the official libvips docs are just translated to rust types. All defaults also respected.

How the crate was written

As a first step, it runs the bindgen to generate unsafe calls to the C libvips library. After this is generated, a C code is compiled and executed. This code introspects the operations and outputs them as text. This text is parsed and then generates the error.rs and the ops.rs modules.

Those are basically safe wrappers on top of the also genereated bindings. Though not widely tested, all the memory cleaning should be working as expected. Important to note that all "vips" prefixes in the naming were removed from the operations's names.

Both the bindings and the generated operations were pushed to crates.io with most of optional dependencies from libvips included. Be careful when calling functions that are dependent on those sub-dependencies (most of them format related).

Contributing

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

A note to the maintainers

The publication of the create is done manually and requires that the Cargo.lock version be updated in the repo after this has been done. This can be changed once github actions have been added to the repo in order to publish after merge.

How to use it

The main entity from this crate is the VipsApp struct. It doesn't store any information, but as long as it is not dropped, vips should be working as expected.

Vips needs to be initialized and shut down, this struct does this job, though you don't have to shut it down, it will be done automatically when the variable holding the value of a VipsApp struct is droped.

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.

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:

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

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. Be aware that the VipsImage object is not thread safe in the moment. I'll investigate what is happening and provide a solution for it in the future.

Example

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!")
    }
}

libvips-rust-bindings's People

Contributors

alimoeeny avatar augustocdias avatar axkirillov avatar bassco avatar bigfarts avatar hbertoduarte avatar ianthetechie avatar inchkev avatar negezor avatar renovate[bot] avatar semantic-release-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

libvips-rust-bindings's Issues

segfault when using *save_buffer_with_opts and *save_buffer

Please consider the following example:

use libvips::{VipsApp, VipsImage, ops::{JpegsaveBufferOptions, Interpretation}};
use mimalloc::MiMalloc;

#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;

fn main() {
    let app = VipsApp::new(env!("CARGO_PKG_NAME"), false).unwrap();
    app.cache_set_max(0);
    app.cache_set_max_mem(0);
    app.cache_set_max_files(0);
    app.vips_cache_set_trace(false);
    app.vips_cache_set_dump(false);
    app.progress_set(false);
    app.concurrency_set(1);
    app.pipe_read_limit_set(-1);

    let data = std::fs::read("input.jpg").unwrap();
    let mut img = VipsImage::new_from_buffer(data.as_slice(), "").unwrap();
    img = libvips::ops::colourspace(&img, Interpretation::BW).unwrap();
    let output = libvips::ops::jpegsave_buffer_with_opts(
        &img,
        &JpegsaveBufferOptions {
            q: 75,
            interlace: true,
            strip: true,
            ..Default::default()
        },
    ).unwrap();
    std::fs::write("output.jpg", output.as_slice()).unwrap();
}

running the code always causes segfault:

939780 segmentation fault (core dumped)

By removing the MiMalloc it sometimes (randomly) causes segfault.

GDB Backtrace:

#0  0x000055555556187d in mi_free (p=0x5555557518f0) at c_src/mimalloc/src/alloc.c:565
#1  0x000055555555f679 in mimalloc::{impl#0}::dealloc (self=0x5555555ae027, ptr=0x5555557518f0, _layout=...) at /home/yaa110/.cargo/registry/src/index.crates.io-6f17d22bba15001f/mimalloc-0.1.37/src/lib.rs:91
#2  0x000055555555ebf3 in test_vips::_::__rg_dealloc (arg0=0x5555557518f0, arg1=31184, arg2=1) at src/main.rs:5
#3  0x0000555555578840 in alloc::alloc::dealloc (ptr=0x5555557518f0, layout=...) at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/alloc.rs:111
#4  alloc::alloc::{impl#1}::deallocate (self=0x7fffffffd9f0, ptr=..., layout=...) at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/alloc.rs:248
#5  0x0000555555577fbb in alloc::raw_vec::{impl#3}::drop<u8, alloc::alloc::Global> (self=0x7fffffffd9f0) at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/raw_vec.rs:485
#6  0x00005555555753bb in core::ptr::drop_in_place<alloc::raw_vec::RawVec<u8, alloc::alloc::Global>> () at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ptr/mod.rs:490
#7  0x0000555555575294 in core::ptr::drop_in_place<alloc::vec::Vec<u8, alloc::alloc::Global>> () at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ptr/mod.rs:490
#8  0x000055555555f985 in std::fs::write<&str, alloc::vec::Vec<u8, alloc::alloc::Global>> (path=..., contents=...) at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/fs.rs:330
#9  0x000055555555eb03 in test_vips::main () at src/main.rs:30

GDB backtrace without MiMalloc:

#0  0x00007ffff7c4855d in vips_operation_touch (operation=0x555555710d10) at ../libvips/iofuncs/cache.c:607
#1  0x00007ffff7c485cb in vips_cache_ref (operation=0x555555710d10) at ../libvips/iofuncs/cache.c:625
#2  0x00007ffff7c4865a in vips_cache_insert (operation=0x555555710d10) at ../libvips/iofuncs/cache.c:656
#3  0x00007ffff7c48b9d in vips_cache_operation_add (operation=0x555555710d10) at ../libvips/iofuncs/cache.c:868
#4  0x00007ffff7c48cc7 in vips_cache_operation_buildp (operation=0x7fffffffd4c0) at ../libvips/iofuncs/cache.c:915
#5  0x00007ffff7c528bb in vips_call_required_optional (operation=0x7fffffffd4c0, required=0x7fffffffd510, optional=0x7fffffffd630) at ../libvips/iofuncs/operation.c:913
#6  0x00007ffff7c52a28 in vips_call_by_name (operation_name=0x7ffff7cac5c5 "VipsForeignLoadJpegBuffer", option_string=0x5555556fb250 "", required=0x7fffffffd510, optional=0x7fffffffd630)
    at ../libvips/iofuncs/operation.c:953
#7  0x00007ffff7c53232 in vips_call_split_option_string (operation_name=0x7ffff7cac5c5 "VipsForeignLoadJpegBuffer", option_string=0x5555556fb250 "", optional=0x7fffffffd630) at ../libvips/iofuncs/operation.c:1072
#8  0x00007ffff7c40af0 in vips_image_new_from_buffer (buf=0x555555654160, len=57778, option_string=0x5555556fb250 "") at ../libvips/iofuncs/image.c:2169
#9  0x0000555555563a49 in libvips::image::VipsImage::new_from_buffer (buffer=..., option_str=...) at src/image.rs:125
#11 0x000055555555cafd in test_vips::main () at src/main.rs:30

Window 10 report error

https://github.com/libvips/libvips/releases/download/v8.8.4/vips-dev-w64-all-8.8.4.zip

PS Z:\rust\a031\web> vips -v
vips-8.8.4-Thu Dec 5 16:24:34 UTC 2019

vips invert D:/Personal/Pictures/01.png D:/Personal/Pictures/02.png
this is ok.
windows 10
cpu 64

[dependencies]
actix-web = "2.0"
actix-rt = "1.0"
actix-multipart = "0.2"
futures = "0.3"
libvips = "1.3"

why

error[E0308]: mismatched types
  --> C:\Users\52752\.cargo\bin\registry\src\github.com-1ecc6299db9ec823\libvips-1.3.0\src\lib.rs:46:18
   |
45 |     pub fn get_disc_threshold(&self) -> u64 {
   |                                         --- expected `u64` because of return type
46 |         unsafe { bindings::vips_get_disc_threshold() }
   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |                  |
   |                  expected `u64`, found `u32`
   |                  help: you can convert an `u32` to `u64`: `bindings::vips_get_disc_threshold().into()`

error[E0308]: mismatched types
   --> C:\Users\52752\.cargo\bin\registry\src\github.com-1ecc6299db9ec823\libvips-1.3.0\src\lib.rs:131:46
    |
131 |             bindings::vips_cache_set_max_mem(max);
    |                                              ^^^ expected `u32`, found `u64`
    |
help: you can convert an `u64` to `u32` and panic if the converted value wouldn't fit
    |
131 |             bindings::vips_cache_set_max_mem(max.try_into().unwrap());
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
   --> C:\Users\52752\.cargo\bin\registry\src\github.com-1ecc6299db9ec823\libvips-1.3.0\src\lib.rs:143:13
    |
141 |     pub fn cache_get_max_mem(&self) -> u64 {
    |                                        --- expected `u64` because of return type
142 |         unsafe {
143 |             bindings::vips_cache_get_max_mem()
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |             |
    |             expected `u64`, found `u32`
    |             help: you can convert an `u32` to `u64`: `bindings::vips_cache_get_max_mem().into()`

error[E0308]: mismatched types
   --> C:\Users\52752\.cargo\bin\registry\src\github.com-1ecc6299db9ec823\libvips-1.3.0\src\lib.rs:193:13
    |
191 |     pub fn tracked_get_mem(&self) -> u64 {
    |                                      --- expected `u64` because of return type
192 |         unsafe {
193 |             bindings::vips_tracked_get_mem()
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |             |
    |             expected `u64`, found `u32`
    |             help: you can convert an `u32` to `u64`: `bindings::vips_tracked_get_mem().into()`

error[E0308]: mismatched types
   --> C:\Users\52752\.cargo\bin\registry\src\github.com-1ecc6299db9ec823\libvips-1.3.0\src\lib.rs:199:13
    |
197 |     pub fn tracked_get_mem_highwater(&self) -> u64 {
    |                                                --- expected `u64` because of return type
198 |         unsafe {
199 |             bindings::vips_tracked_get_mem_highwater()
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |             |
    |             expected `u64`, found `u32`
    |             help: you can convert an `u32` to `u64`: `bindings::vips_tracked_get_mem_highwater().into()`

error[E0308]: mismatched types
  --> C:\Users\52752\.cargo\bin\registry\src\github.com-1ecc6299db9ec823\libvips-1.3.0\src\image.rs:77:91
   |
77 |                 bindings::vips_image_new_from_file_raw(f.as_ptr(), x_size, y_size, bands, offset);
   |                                                                                           ^^^^^^ expected `u32`, found `u64`
   |
help: you can convert an `u64` to `u32` and panic if the converted value wouldn't fit
   |
77 |                 bindings::vips_image_new_from_file_raw(f.as_ptr(), x_size, y_size, bands, offset.try_into().unwrap());
   |                                                                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
   --> C:\Users\52752\.cargo\bin\registry\src\github.com-1ecc6299db9ec823\libvips-1.3.0\src\image.rs:110:17
    |
110 |                 buffer.len() as u64,
    |                 ^^^^^^^^^^^^^^^^^^^ expected `u32`, found `u64`
    |
help: you can convert an `u64` to `u32` and panic if the converted value wouldn't fit
    |
110 |                 (buffer.len() as u64).try_into().unwrap(),
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
   --> C:\Users\52752\.cargo\bin\registry\src\github.com-1ecc6299db9ec823\libvips-1.3.0\src\image.rs:126:21
    |
126 |                     buffer.len() as u64,
    |                     ^^^^^^^^^^^^^^^^^^^ expected `u32`, found `u64`
    |
help: you can convert an `u64` to `u32` and panic if the converted value wouldn't fit
    |
126 |                     (buffer.len() as u64).try_into().unwrap(),
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
   --> C:\Users\52752\.cargo\bin\registry\src\github.com-1ecc6299db9ec823\libvips-1.3.0\src\image.rs:419:17
    |
419 |                 &mut buffer_buf_size,
    |                 ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `u64`
    |
    = note:    expected raw pointer `*mut u32`
            found mutable reference `&mut u64`

   Compiling tokio-util v0.2.0
error[E0308]: mismatched types
   --> C:\Users\52752\.cargo\bin\registry\src\github.com-1ecc6299db9ec823\libvips-1.3.0\src\image.rs:604:59
    |
604 |             let bytes = bindings::vips_blob_get(self.ctx, &mut size);
    |                                                           ^^^^^^^^^ expected `u32`, found `u64`
    |
    = note:    expected raw pointer `*mut u32`
            found mutable reference `&mut u64`

thumbnail_*_with_opts with default options cause error

Hi @augustocdias ,
here is the code of thumbnail_buffer_with_opts:

    let buffer = std::fs::read("any.jpeg").expect("hello world");
    let buffer_options = ops::ThumbnailBufferOptions::default();
    let resized = ops::thumbnail_buffer_with_opts(&buffer.as_slice(), 100, &buffer_options).expect(app.error_buffer().unwrap());

thumbnail_with_opts

let options = ops::ThumbnailOptions::default();
let resized = ops::thumbnail_with_opts("any.jpeg", 100, &options).expect(app.error_buffer().unwrap());
thread 'main' panicked at 'vips__file_read: error reading from file ""
profile_load: unable to load profile ""

vips-8.10.2-Mon Oct 12 16:43:59 UTC 2020

Could it be caused by the import_profile and export_profile?
Thanks

Use `bindings::vips_type_find` error

pub fn vips_type_find(basename: &str, nickname: &str) -> Result<i32> {
    unsafe {
        println!("{}", "xxx");
        let basename_in = utils::new_c_string(basename)?;
        let nickname_in = utils::new_c_string(nickname)?;
        let res = bindings::vips_type_find(basename_in.as_ptr(), nickname_in.as_ptr());
        println!("id: {:?}", res);
        return Ok(res as i32);
    }
}

I use vips_type_find("VipsOperation", "gifload") error:

(process:37498): GLib-GObject-WARNING **: 15:52:13.209: cannot retrieve class for invalid (unclassed) type '<invalid>'
(process:37498): GLib-GObject-WARNING **: 15:52:13.209: invalid class cast from (NULL) pointer to 'VipsObject'

I use printf("%lu", vips_type_find("VipsOperation", "gifload")) with c, is right.

ci: changelog missing content

When the semantic-release-changelog was added, the config defined for the different sections of the conventional commit prefixes did not show up on the changelog for release 1.6.1.

Only 1 of the 3 commits was added to the changelog

Optional values for command options

Hey @augustocdias,

I am to using options with the libvips commands and noticed you must specify every single option. I am forced to specify options that I want to leave as the default values programmed into libvips. For example, for arrayjoin I want to only change the value for across but I am forced to change all the other optional values. A current work around, I give a bad value for the options I do not want so libvips ignores them, e.g. hspacing I give a value of 0.

My question, did you design it this way on purpose or did bindgen force you to specify all the options?

Simple sample to resize image from file

Hi,

I would be nice to have a simple example, from example to resize a image from a file (doesn't seem very obvious to me from the current documentation).

Anyway thanks for the work.

Segmentation fault when creating image with text

First of all, thanks for the library.

I'm having trouble trying to create an image with text. The same command works in the official command line utility. If I remove TextOptions, then the Rust code also works.

Rust demo

use libvips::{ops, VipsApp};

fn main() {
    let _app = VipsApp::new("Test Libvips", false).unwrap();
    let image = ops::text_with_opts(
        "test",
        &ops::TextOptions{
            font: "Roboto 12".to_string(),
            fontfile: "roboto.ttf".to_string(),
            ..ops::TextOptions::default()
        },
    ).unwrap();
    // ops::jpegsave(&image, "test.jpg").unwrap();
}

An example of a working command

vips text test.jpg "test" --fontfile roboto.ttf --font "Roboto 12"

GDB output

Thread 1 "libvips-segfaul" received signal SIGSEGV, Segmentation fault.
0x00007ffff7f7a0e3 in ?? () from /usr/lib/libgobject-2.0.so.0
(gdb) bt
#0  0x00007ffff7f7a0e3 in  () at /usr/lib/libgobject-2.0.so.0
#1  0x00007ffff7f61c9c in g_object_get_valist () at /usr/lib/libgobject-2.0.so.0
#2  0x00007ffff7f61fc5 in g_object_get () at /usr/lib/libgobject-2.0.so.0
#3  0x00007ffff7b8bf9f in vips_operation_get_valist_optional (ap=0x7fffffffcdb0, operation=<optimized out>) at ../vips-8.14.2/libvips/iofuncs/operation.c:854
#4  vips_call_required_optional (operation=operation@entry=0x7fffffffcca0, required=required@entry=0x7fffffffccd0, optional=optional@entry=0x7fffffffcdb0)
    at ../vips-8.14.2/libvips/iofuncs/operation.c:921
#5  0x00007ffff7b8c214 in vips_call_by_name (operation_name=<optimized out>, option_string=option_string@entry=0x0, required=required@entry=0x7fffffffccd0, optional=0x7fffffffcdb0)
    at ../vips-8.14.2/libvips/iofuncs/operation.c:953
#6  0x00007ffff7b8c69d in vips_call_split (operation_name=<optimized out>, optional=<optimized out>) at ../vips-8.14.2/libvips/iofuncs/operation.c:1057
#7  0x00007ffff7bbf52b in vips_text(VipsImage**, char const*, ...) (out=<optimized out>, text=<optimized out>) at ../vips-8.14.2/libvips/create/text.c:731
#8  0x000055555555e0fa in libvips::ops::text_with_opts (text=..., text_options=0x7fffffffd7b0) at src/ops.rs:5745
#9  0x000055555555c6bf in libvips_segfault_demo::main () at src/main.rs:5

Additional Information

  • Libvips-rust version: 1.5.1
  • Libvips version: 8.14.2-1

Issue with `thumbnail_with_opts`

I'm trying to resize an image based on height and width.
If I use thumbnail (only using width) it works as intended, using thumbnail_with_opts it does not.
Note that I have moved the App into the function to be able to access the error buffer.

fn manipulate_image(path: &str, height: i32, width: i32, quality: u32) -> Result<(), ()> {
    let libvips = VipsApp::new("app", true).expect("Could not start libvips");
    libvips.concurrency_set(2);

    // TODO: Error handling
    let thumb_opts = ops::ThumbnailOptions {
        height: height,
        ..ops::ThumbnailOptions::default()
    };
    log::info!("{}", path);
    // This works
    // let image = ops::thumbnail(&path, width).unwrap();
    // This doesn't
    let image: VipsImage = match ops::thumbnail_with_opts(path, width, &thumb_opts) {
        Err(err) => {
            log::error!("{}", err);
            log::error!("{}", libvips.error_buffer().unwrap());
            return Err(());
        }
        Ok(img) => img,
    };

    image.image_write_to_file("uploads/temp.jpg").unwrap();
    return Ok(());
}

I do get the following error (the path from above does exist)

vips error: ThumbnailError. Check error buffer for more details
vips__file_read: error reading from file ""
    profile_load: unable to load profile ""
    vips__file_read: error reading from file ""
    profile_load: unable to load profile ""
    
vips_threadset_free: peak of 0 threads
memory: high-water mark 1.35 MB
error buffer: vips__file_read: error reading from file ""
profile_load: unable to load profile ""
vips__file_read: error reading from file ""
profile_load: unable to load profile ""

Am I doing something wrong? If so please tell me what the correct way is.

VipsImage::clone Segfaults

Attempting to clone a valid image seg faults.

VipsImage::new_from_buffer(data, "")?.clone()

My workaround is currently to save the image as a jpeg and then create a new image from the jpeg buffer again.

Environment:

  • vips 8.10.0 (installed from brew)
  • mac os 10.15.6
  • rust 1.45.2 (stable)

Implement new types for 8.9

libvips released a 8.9 version which contains a new type intended for streaming called VipsSource.
Special handling is needed in the generator to support this type and also the struct wrapper for its bindings in the library.

thumbnail_image_with_opts panicks an ': ThumbnailImageError'

Hi,

if i run the following code

let options = ops::ThumbnailImageOptions { height: 600, ..ops::ThumbnailImageOptions::default() };

let resized_image = ops::thumbnail_image_with_opts(&new_image, 1200,&options).expect("");

even if i just create an

let options = ops::ThumbnailImageOptions::default()

i get an

stack backtrace: 0: 0x10fb3029c - std::backtrace_rs::backtrace::libunwind::trace::hd4e4f36eb9f0f866 at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/std/src/../../backtrace/src/backtrace/libunwind.rs:90:5 1: 0x10fb3029c - std::backtrace_rs::backtrace::trace_unsynchronized::h713e8299cd20066f at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5 2: 0x10fb3029c - std::sys_common::backtrace::_print_fmt::h10db128357fb183a at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/std/src/sys_common/backtrace.rs:67:5 3: 0x10fb3029c - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::ha6f5ddd5259d3e16 at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/std/src/sys_common/backtrace.rs:46:22 4: 0x10fb42fad - core::fmt::write::hefe95a44532fe6ed at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/core/src/fmt/mod.rs:1078:17 5: 0x10fb2e3c6 - std::io::Write::write_fmt::hf513c99961415bff at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/std/src/io/mod.rs:1519:15 6: 0x10fb31ec9 - std::sys_common::backtrace::_print::he8e57200c2a0a691 at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/std/src/sys_common/backtrace.rs:49:5 7: 0x10fb31ec9 - std::sys_common::backtrace::print::hab21ea437dd3480e at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/std/src/sys_common/backtrace.rs:36:9 8: 0x10fb31ec9 - std::panicking::default_hook::{{closure}}::h70a3a940826edea5 at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/std/src/panicking.rs:208:50 9: 0x10fb31a59 - std::panicking::default_hook::h9520f36dd50be056 at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/std/src/panicking.rs:225:9 10: 0x10fb3254b - std::panicking::rust_panic_with_hook::h102f8bee4e0ef4c7 at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/std/src/panicking.rs:591:17 11: 0x10fb32075 - std::panicking::begin_panic_handler::{{closure}}::hb72eee9aad2e147c at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/std/src/panicking.rs:497:13 12: 0x10fb30758 - std::sys_common::backtrace::__rust_end_short_backtrace::h372ff87ecb2667f3 at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/std/src/sys_common/backtrace.rs:141:18 13: 0x10fb31fda - rust_begin_unwind at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/std/src/panicking.rs:493:5 14: 0x10fb4878f - core::panicking::panic_fmt::h261fd45d36f74dfa at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/core/src/panicking.rs:92:14 15: 0x10fb48695 - core::option::expect_none_failed::hf2a36714418ff407 at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/core/src/option.rs:1268:5 16: 0x10fb0cf02 - core::result::Result<T,E>::expect::h3b25c5c22e7faa0a at /Users/../.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/result.rs:933:23 17: 0x10fb0cd8c - image_scaler_rust::main::h7be8ddb99663c41b at /Users/../private_project/image-scaler-rust/src/main.rs:75:25 18: 0x10fb0cf6e - core::ops::function::FnOnce::call_once::h7cc2d67b840e39d4 at /Users/../.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5 19: 0x10fb0ce71 - std::sys_common::backtrace::__rust_begin_short_backtrace::h91e221f83582994e at /Users/../.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/std/src/sys_common/backtrace.rs:125:18 20: 0x10fb0cc44 - std::rt::lang_start::{{closure}}::h03b3e5dc117dc421 at /Users/../.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/std/src/rt.rs:66:18 21: 0x10fb328c4 - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::h4ab201f754b12ec0 at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/core/src/ops/function.rs:259:13 22: 0x10fb328c4 - std::panicking::try::do_call::h2d40bab4a9c2dc4b at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/std/src/panicking.rs:379:40 23: 0x10fb328c4 - std::panicking::try::hedf52334a975e681 at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/std/src/panicking.rs:343:19 24: 0x10fb328c4 - std::panic::catch_unwind::hb38d8390232c8f25 at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/std/src/panic.rs:396:14 25: 0x10fb328c4 - std::rt::lang_start_internal::hebea83fb59fe572e at /rustc/0b644e419681835bd0f5871c3bfbd648aa04f157/library/std/src/rt.rs:51:25 26: 0x10fb0cc21 - std::rt::lang_start::ha49e5215e73c4ec7 at /Users/../.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/std/src/rt.rs:65:5 27: 0x10fb0ce52 - _main

Am i doing something wrong or is there a bug?

Thanks for your support
Sven

svgload_buffer_with_opts is segfaulting

Using the default options like this:

        let svg = ops::svgload_buffer_with_opts(svg_str, &ops::SvgloadBufferOptions {
            dpi: 72.0,
            scale: 1.0,
            unlimited: false,
            flags: ops::ForeignFlags::None,
            memory: false,
            access: ops::Access::Random,
            fail_on: ops::FailOn::None,
        })?;

I get a SIGSEGV error. But not with svgload or svgload_with_opts.

Using this library, memory crashes

(process:120408): GLib-CRITICAL **: 10:11:24.403: g_hash_table_lookup: assertion 'hash_table != NULL' failed

(process:120408): GLib-CRITICAL **: 10:11:24.403: g_hash_table_lookup: assertion 'hash_table != NULL' failed

(process:120408): GLib-CRITICAL **: 10:11:24.403: g_hash_table_insert_internal: assertion 'hash_table != NULL' failed

(process:120408): GLib-CRITICAL **: 10:11:24.403: g_hash_table_lookup: assertion 'hash_table != NULL' failed

[Bug]The version of libvips may have been confused in version 1.7.0

In README.md, libvips is noted as 8.14.5, however, the test example in which executed failed with the following error.

error: jpegsave: no property named `keep'

The following is my vips info.
The vips jpegsave options do not exist keep.

builder@2dd7e4b7a54a:~$ vips --version
vips-8.14.5
builder@2dd7e4b7a54a:~$ vips jpegsave
save image to jpeg file
usage:
   jpegsave in filename [--option-name option-value ...]
where:
   in           - Image to save, input VipsImage
   filename     - Filename to save to, input gchararray
optional arguments:
   Q            - Q factor, input gint
                        default: 75
                        min: 1, max: 100
   profile      - ICC profile to embed, input gchararray
   optimize-coding - Compute optimal Huffman coding tables, input gboolean
                        default: false
   interlace    - Generate an interlaced (progressive) jpeg, input gboolean
                        default: false
   trellis-quant - Apply trellis quantisation to each 8x8 block, input gboolean
                        default: false
   overshoot-deringing - Apply overshooting to samples with extreme values, input gboolean
                        default: false
   optimize-scans - Split spectrum of DCT coefficients into separate scans, input gboolean
                        default: false
   quant-table  - Use predefined quantization table with given index, input gint
                        default: 0
                        min: 0, max: 8
   subsample-mode - Select chroma subsample operation mode, input VipsForeignSubsample
                        default: auto
                        allowed: auto, on, off
   restart-interval - Add restart markers every specified number of mcu, input gint
                        default: 0
                        min: 0, max: 2147483647
   strip        - Strip all metadata from image, input gboolean
                        default: false
   background   - Background value, input VipsArrayDouble
   page-height  - Set page height for multipage save, input gint
                        default: 0
                        min: 0, max: 10000000
operation flags: sequential nocache

When I using crate libvips@=1.6.1, the example executed succefully.

note: ld: library 'vips' not found

Hi, when I try to use the package and build the project, it says,
note: ld: library 'vips' not found
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Can you please let me know if there are any additional setup required?
Looking forward to hearing from you ~

pdfload operations

Safe operations for vips_pdfload/vips_pdfload_buffer/vips_pdfload_source (and the _with_opts counterparts) would be useful. The unsafe bindings are currently available, but it looks like the safe wrappers have not been generated. Were these filtered out during the generation process?

Happy to help with the implementation 😄

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • fix(generator): update rust crate num-traits to v0.2.19
  • fix(generator): update rust crate which to v6.0.1
  • chore(deps): update dependency @semantic-release-cargo/semantic-release-cargo to v2.3.24
  • chore(deps): update dependency node to v20.14.0
  • chore(docker): update rust docker tag to v1.78.0
  • ci(workflow): update amannn/action-semantic-pull-request action to v5.5.2
  • chore(deps): update dependency @commitlint/config-conventional to v19
  • 🔐 Create all rate-limited PRs at once 🔐

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

asdf
.tool-versions
  • rust 1.75.0
  • node 20.11.0
cargo
Cargo.toml
  • num-traits 0.2
  • num-derive 0.4
generator/Cargo.toml
  • num-traits 0.2.17
  • num-derive 0.4.1
  • bindgen 0.69.2
  • Inflector 0.11.4
  • cc 1.0.83
  • which 6.0.0
dockerfile
generator/Dockerfile
  • rust 1.75.0-alpine3.19
github-actions
.github/workflows/conventional-prs.yml
  • amannn/action-semantic-pull-request v5.4.0
.github/workflows/lint-pr-title-preview-outputErrorMessage.yml
  • actions/checkout v4
  • amannn/action-semantic-pull-request v5
  • marocchino/sticky-pull-request-comment v2
  • marocchino/sticky-pull-request-comment v2
.github/workflows/release.yml
  • actions/checkout v4
  • actions/setup-node v4
npm
package.json
  • @commitlint/config-conventional 18.6.3
  • @semantic-release-cargo/semantic-release-cargo 2.2.71
  • @semantic-release/changelog 6.0.3
  • @semantic-release/commit-analyzer 11.1.0
  • @semantic-release/exec 6.0.3
  • @semantic-release/git 10.0.1
  • @semantic-release/github 9.2.6
  • @semantic-release/release-notes-generator 12.1.0
  • semantic-release 22.0.12
  • semantic-release-major-tag ^0.3.2
  • node ^20.0.0

  • Check this box to trigger a request for Renovate to run again on this repository

jpegsave_*: no property named `subsample-mode'

 let image = VipsImage::new_from_buffer(&body, "").unwrap();
    let resized = ops::resize(&image, 0.5).unwrap();
    let options = ops::JpegsaveBufferOptions {
        q: 70,
        background: vec![255.0],
        strip: true,
        optimize_coding: true,
        optimize_scans: true,
        interlace: true,
        ..ops::JpegsaveBufferOptions::default()
    };
    match ops::jpegsave_buffer_with_opts(&resized, &options) {
        Err(_) => println!("error: {}", img.vips_app.error_buffer().unwrap()),
        Ok(_) => (),
    }

I get the same no matter where to save to a file or to a buffer. I also tried different propertiy: Auto, On, Off, Last.
vips version vips-8.9.1

Duplicate error messages makes debugging awkward

When debugging an error in a downstream project, it is rather painful to "guess" which method call from the library generated the error when there are duplicated error messages.

It would be nice to prefix the error messages with a method signature to aide debugging.

Need a way to _not_ pass the import/export profile.

I'm trying to use thumbnail_with_opts() and libvips is failing with profile_load: unable to load profile "". Seems that both import_profile and export_profile in ThumbnailOptions need to be set to the filename of ICC profiles. Because these fields are required I cannot not pass them to the thumbnail_with_opts() function. It would be ideal if these two fields were optional.

VipsImage thread safety

Hi! Thank you very much for providing this very pleasant to use binding crate.

It would appear this warning is directed at me and my use case:

Be aware that the VipsImage object is not thread safe in the moment. I'll investigate what is happening and provide a solution for it in the future.

Is there an update to your thoughts on this, or your general advice on working around it?

Should the Cargo.lock be removed?

The general practise for libraries is to not enforce dependencies via Cargo.lock and to leave the versioning to the applications.

Investigate the impact of removing this file from the repository.

Applications that are created should have consistent versions and their repositories should include the lock file.

Looking for `vips_image_write_to_memory`

I've noticed that the function vips_image_write_to_memory does not have a corresponding method implemented for VipsImage, like the one that can be found for vips_image_write_to_buffer.

Is there a specific reason for that?

Segmentation fault on arrayjoin

Hey @augustocdias,

Awesome work on this repo! I am using it for a personal project and noticed array join causes a segmentation fault. The segmentation fault occurs when I attempt to join a specific number of images, the example I provided shows my attempt to join 7 images. However, it also fails on a size of 8, 9, 10 and 11. If I try to join 4 images it succeeds. Very odd behaviour! I attempted to read the source code but it looks fine to me. I attempted to use the libvips command line and it works fine with any size of images in an arrayjoin. I looked at the source code for arrayjoin but saw no obvious flaws. Might be a problem with how bindgen generated the functions, not sure if it also effects other libvips commands in your library.

Example code:

fn main() {

    // Init Libvips
    let app = VipsApp::new("Libvips", false).expect("Cannot initialize libvips");

    let mut images  = vec![
        VipsImage::new_from_file("turtle.png").unwrap(),
        VipsImage::new_from_file("turtle.png").unwrap(),
        VipsImage::new_from_file("turtle.png").unwrap(),
        VipsImage::new_from_file("turtle.png").unwrap(),
        VipsImage::new_from_file("turtle.png").unwrap(),
        VipsImage::new_from_file("turtle.png").unwrap(),
        VipsImage::new_from_file("turtle.png").unwrap(),
        ];

    let result = ops::arrayjoin(&mut images[..])
            .and_then(|image| image.image_write_to_file("./output.png"));
    match result {
        Err(error) => { 
            println!("{}", error);
            println!("error: {}", app.error_buffer().unwrap());
        },
        Ok(_) => println!("Image created.")
    }
}

Output

(Test Libvips:95932): GLib-GObject-CRITICAL **: 21:46:10.231: g_object_ref: assertion 'G_IS_OBJECT (object)' failed

(Test Libvips:95932): GLib-GObject-CRITICAL **: 21:46:10.231: g_object_ref: assertion 'G_IS_OBJECT (object)' failed

(Test Libvips:95932): GLib-GObject-CRITICAL **: 21:46:10.231: g_object_ref: assertion 'G_IS_OBJECT (object)' failed

(Test Libvips:95932): GLib-GObject-CRITICAL **: 21:46:10.231: g_object_ref: assertion 'G_IS_OBJECT (object)' failed

(Test Libvips:95932): GLib-GObject-CRITICAL **: 21:46:10.231: g_object_ref: assertion 'G_IS_OBJECT (object)' failed

(Test Libvips:95932): GLib-GObject-CRITICAL **: 21:46:10.231: g_object_ref: assertion 'G_IS_OBJECT (object)' failed

(Test Libvips:95932): GLib-GObject-CRITICAL **: 21:46:10.231: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
zsh: segmentation fault  cargo run

Alpine Linux Segfault calling VipsApp::new

This runs perfectly on my Mac, but when I try running in Alpine I get a Segfault in the libvips::init

I've tried the following Docker images:

  • rust:1.46-alpine12 w/ vips 8.10.1 from edge
  • rust:1.45-alpine12 w/ vips 8.10.1 from edge
  • libvips-builder w/ vips 8.10.0 created using ./build.sh
  • libvips-builder w/ vips 8.10.1 created using ./build.sh

I reduced the app to just:

use libvips::VipsApp;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let _app = VipsApp::new("Test Libvips", true //false -> no difference).expect("Cannot initialize libvips");
    Ok(())
}

Here's the core dump I get when I try cargo run:

#0  0x0000000000000000 in ?? ()
#1  0x00007f3cb4f90df6 in libvips::init (name=..., detect_leak=true)
    at /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/libvips-1.4.2/src/lib.rs:228
#2  0x00007f3cb4f90c0b in libvips::VipsApp::new (name=..., detect_leak=true)
    at /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/libvips-1.4.2/src/lib.rs:36
#3  0x00007f3cb4f90773 in media_service::main () at service/src/main.rs:24

Libvips does not release memory

I am writing an image processing server libvips and hyper. After processing around 1k requests the memory usage climbs to ~1.2 GB and stays the same after. None of the images are larger than 500Kb. I am using the thumbnail_source_with_opts function. Disabling libvips cache has no effect. Libvips concurrency is set to 2.
Monitoring the process with top, I can see that number of threads drop down to 5-6 after the operation but the memory is not cleared. I have also tried setting the max_blocking_threads to 1 for tokio runtime to no avail.
Is there a way to lower this memory usage?

Please add usage examples

As a potential user of this library, I would like to explore some usage examples that are provided by the package maintainers and contributors.

Cargo provides the functionality to add examples to a library.

An upshot of doing so is that these examples are included when running tests or can be run in isolation too.

Here is an example to transform a jpeg to a png that is described in the current README.md and can be codifed.

cargo run --examples jpeg_to_png

VipsImage lacks bindings for `vips_image_set`

At the moment, there is no way to make a call to vips_image_set as there is no safe binding for the function, and the ctx pointer in the VipsImage struct is private, so I cannot manually call libvips::bindings::vips_image_set (and so on).

profile_load: unable to load profile when using thumbnail_image_with_opts

Hi @augustocdias I am unsure if this is related #11 but I am encountering an issue when trying to us thumbnail_image_with_opts. When I attempt to thumbnail the image I receive the following error

[src/image_utils.rs:158] &error = ThumbnailImageError
[src/image_utils.rs:159] vips_app.error_buffer().unwrap() = "vips__file_read: error reading from file \"\"\nprofile_load: unable to load profile \"\"\n"

Here is a gist of some code and a sample image I found that produces the error
https://gist.github.com/jgould22/8e3a09497e5821d9dcd0575d9c830be0

As far as I can tell I am using libvips 8.10.2 installed with

git clone --depth 1 --branch v8.10.2 https://github.com/libvips/libvips.git && \
        cd libvips && \
        ./autogen.sh && \
        make -j 15 && \
        make install

and the bindings are

libvips = "1.4.2"

Thanks for the bindings and any help with the above error is greatly appreciated!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.