libvips_rs/
lib.rs

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