libvips_rs/
lib.rs

1// (c) Copyright 2019-2025 MIT
2#![allow(non_upper_case_globals)]
3#![allow(non_camel_case_types)]
4#![allow(non_snake_case)]
5#![allow(improper_ctypes)]
6#![allow(dead_code)]
7#[macro_use]
8extern crate num_derive;
9extern crate num_traits;
10
11pub mod bindings;
12pub mod error;
13mod image;
14pub mod ops;
15mod utils;
16
17use error::Error;
18use std::ffi::*;
19
20pub use image::*;
21
22pub type Result<T> = std::result::Result<T, error::Error>;
23
24pub struct VipsApp;
25
26/// That's the main type of this crate. Use it to initialize the system
27impl VipsApp {
28    /// default constructor of a VIpsApp instance which will disable memory leak debugging
29    pub fn default(name: &str) -> Result<VipsApp> {
30        init(
31            name, false,
32        )?;
33        Ok(VipsApp)
34    }
35
36    /// new instance of VipsApp takes the application name and a flag indicating if the library should debug memory leak (good for testing purposes)
37    pub fn new(name: &str, detect_leak: bool) -> Result<VipsApp> {
38        init(
39            name,
40            detect_leak,
41        )?;
42        Ok(VipsApp)
43    }
44
45    pub fn progress_set(&self, flag: bool) {
46        unsafe {
47            bindings::vips_progress_set(if flag { 1 } else { 0 });
48        }
49    }
50
51    pub fn get_disc_threshold(&self) -> u64 {
52        unsafe { bindings::vips_get_disc_threshold() }
53    }
54
55    pub fn version_string(&self) -> Result<&str> {
56        unsafe {
57            let version = CStr::from_ptr(bindings::vips_version_string());
58            version
59                .to_str()
60                .map_err(|_| Error::InitializationError("Error initializing string"))
61        }
62    }
63
64    pub fn thread_shutdown(&self) {
65        unsafe {
66            bindings::vips_thread_shutdown();
67        }
68    }
69
70    pub fn error_buffer(&self) -> Result<&str> {
71        unsafe {
72            let buffer = CStr::from_ptr(bindings::vips_error_buffer());
73            buffer
74                .to_str()
75                .map_err(|_| Error::InitializationError("Error initializing string"))
76        }
77    }
78
79    pub fn error(&self, domain: &str, error: &str) -> Result<()> {
80        unsafe {
81            let c_str_error = utils::new_c_string(error)?;
82            let c_str_domain = utils::new_c_string(domain)?;
83            bindings::vips_error(
84                c_str_domain.as_ptr(),
85                c_str_error.as_ptr(),
86            );
87            Ok(())
88        }
89    }
90
91    pub fn error_system(&self, code: i32, domain: &str, error: &str) -> Result<()> {
92        unsafe {
93            let c_str_error = utils::new_c_string(error)?;
94            let c_str_domain = utils::new_c_string(domain)?;
95            bindings::vips_error_system(
96                code,
97                c_str_domain.as_ptr(),
98                c_str_error.as_ptr(),
99            );
100            Ok(())
101        }
102    }
103
104    pub fn freeze_error_buffer(&self) {
105        unsafe {
106            bindings::vips_error_freeze();
107        }
108    }
109
110    pub fn error_clear(&self) {
111        unsafe {
112            bindings::vips_error_clear();
113        }
114    }
115
116    pub fn error_thaw(&self) {
117        unsafe {
118            bindings::vips_error_thaw();
119        }
120    }
121
122    pub fn error_exit(&self, error: &str) -> Result<()> {
123        unsafe {
124            let c_str_error = utils::new_c_string(error)?;
125            bindings::vips_error_exit(c_str_error.as_ptr());
126        }
127    }
128
129    pub fn cache_print(&self) {
130        unsafe {
131            bindings::vips_cache_print();
132        }
133    }
134
135    pub fn cache_set_max(&self, max: i32) {
136        unsafe {
137            bindings::vips_cache_set_max(max);
138        }
139    }
140
141    pub fn cache_set_max_mem(&self, max: u64) {
142        unsafe {
143            bindings::vips_cache_set_max_mem(max);
144        }
145    }
146
147    pub fn cache_get_max(&self) -> i32 {
148        unsafe { bindings::vips_cache_get_max() }
149    }
150
151    pub fn cache_get_max_mem(&self) -> u64 {
152        unsafe { bindings::vips_cache_get_max_mem() }
153    }
154
155    pub fn cache_get_size(&self) -> i32 {
156        unsafe { bindings::vips_cache_get_size() }
157    }
158
159    pub fn cache_set_max_files(&self, max: i32) {
160        unsafe {
161            bindings::vips_cache_set_max_files(max);
162        }
163    }
164
165    pub fn cache_get_max_files(&self) -> i32 {
166        unsafe { bindings::vips_cache_get_max_files() }
167    }
168
169    pub fn vips_cache_set_dump(&self, flag: bool) {
170        unsafe {
171            bindings::vips_cache_set_dump(if flag { 1 } else { 0 });
172        }
173    }
174
175    pub fn vips_cache_set_trace(&self, flag: bool) {
176        unsafe {
177            bindings::vips_cache_set_trace(if flag { 1 } else { 0 });
178        }
179    }
180
181    /// set the number of worker threads for vips to operate
182    pub fn concurrency_set(&self, max: i32) {
183        unsafe {
184            bindings::vips_concurrency_set(max);
185        }
186    }
187
188    /// get the number of worker threads that vips is operating
189    pub fn concurrency_get(&self) -> i32 {
190        unsafe { bindings::vips_concurrency_get() }
191    }
192
193    pub fn tracked_get_mem(&self) -> u64 {
194        unsafe { bindings::vips_tracked_get_mem() }
195    }
196
197    pub fn tracked_get_mem_highwater(&self) -> u64 {
198        unsafe { bindings::vips_tracked_get_mem_highwater() }
199    }
200
201    pub fn tracked_get_allocs(&self) -> i32 {
202        unsafe { bindings::vips_tracked_get_allocs() }
203    }
204
205    pub fn pipe_read_limit_set(&self, limit: i64) {
206        unsafe {
207            bindings::vips_pipe_read_limit_set(limit);
208        }
209    }
210}
211
212impl Drop for VipsApp {
213    fn drop(&mut self) {
214        unsafe {
215            bindings::vips_shutdown();
216        }
217    }
218}
219
220fn init(name: &str, detect_leak: bool) -> Result<i32> {
221    let cstring = utils::new_c_string(name);
222    if let Ok(c_name) = cstring {
223        let res = unsafe { bindings::vips_init(c_name.as_ptr()) };
224        let result = if res == 0 {
225            Ok(res)
226        } else {
227            Err(Error::InitializationError("Failed to init libvips"))
228        };
229        unsafe {
230            if detect_leak {
231                bindings::vips_leak_set(1);
232            };
233        }
234        result
235    } else {
236        Err(Error::InitializationError("Failed to convert rust string to C string"))
237    }
238}