rs_vips/
utils.rs

1use crate::bindings::{self, g_type_from_name};
2use crate::bindings::{VipsArrayDouble, VipsArrayImage, VipsArrayInt};
3use crate::error::Error;
4use crate::VipsImage;
5use crate::{
6    connection::{VipsSource, VipsTarget},
7    Result,
8};
9use std::ffi::c_void;
10use std::ffi::CString;
11
12pub(crate) struct VipsArrayIntWrapper {
13    pub ctx: *mut VipsArrayInt,
14}
15pub(crate) struct VipsArrayDoubleWrapper {
16    pub ctx: *mut VipsArrayDouble,
17}
18pub(crate) struct VipsArrayImageWrapper {
19    pub ctx: *mut VipsArrayImage,
20}
21
22impl Drop for VipsArrayIntWrapper {
23    fn drop(&mut self) {
24        unsafe {
25            bindings::vips_area_unref(self.ctx as *mut bindings::VipsArea);
26        }
27    }
28}
29
30impl Drop for VipsArrayDoubleWrapper {
31    fn drop(&mut self) {
32        unsafe {
33            bindings::vips_area_unref(self.ctx as *mut bindings::VipsArea);
34        }
35    }
36}
37
38impl Drop for VipsArrayImageWrapper {
39    fn drop(&mut self) {
40        unsafe {
41            bindings::vips_area_unref(self.ctx as *mut bindings::VipsArea);
42        }
43    }
44}
45
46impl From<&[i32]> for VipsArrayIntWrapper {
47    #[inline]
48    fn from(array: &[i32]) -> Self {
49        VipsArrayIntWrapper {
50            ctx: unsafe {
51                bindings::vips_array_int_new(
52                    array.as_ptr(),
53                    array.len() as i32,
54                )
55            },
56        }
57    }
58}
59
60impl From<&[f64]> for VipsArrayDoubleWrapper {
61    #[inline]
62    fn from(array: &[f64]) -> Self {
63        VipsArrayDoubleWrapper {
64            ctx: unsafe {
65                bindings::vips_array_double_new(
66                    array.as_ptr(),
67                    array.len() as i32,
68                )
69            },
70        }
71    }
72}
73
74impl From<&[VipsImage]> for VipsArrayImageWrapper {
75    #[inline]
76    fn from(array: &[VipsImage]) -> Self {
77        let len = array.len() as i32;
78        let as_vips = array
79            .iter()
80            .map(|v| v.ctx)
81            .collect::<Vec<_>>()
82            .as_mut_ptr();
83        VipsArrayImageWrapper {
84            ctx: unsafe {
85                bindings::vips_array_image_new(
86                    as_vips,
87                    len,
88                )
89            },
90        }
91    }
92}
93
94pub(crate) fn vips_image_result(res: *mut bindings::VipsImage, err: Error) -> Result<VipsImage> {
95    if res.is_null() {
96        Err(err.extend())
97    } else {
98        Ok(
99            VipsImage {
100                ctx: res,
101            },
102        )
103    }
104}
105
106pub(crate) fn vips_image_result_ext(res: VipsImage, err: Error) -> Result<VipsImage> {
107    if res
108        .ctx
109        .is_null()
110    {
111        Err(err.extend())
112    } else {
113        Ok(res)
114    }
115}
116
117pub(crate) fn vips_source_result(res: *mut bindings::VipsSource, err: Error) -> Result<VipsSource> {
118    if res.is_null() {
119        Err(err.extend())
120    } else {
121        Ok(
122            VipsSource {
123                ctx: res,
124            },
125        )
126    }
127}
128
129pub(crate) fn vips_target_result(res: *mut bindings::VipsTarget, err: Error) -> Result<VipsTarget> {
130    if res.is_null() {
131        Err(err.extend())
132    } else {
133        Ok(
134            VipsTarget {
135                ctx: res,
136            },
137        )
138    }
139}
140
141#[inline]
142pub fn result<T>(res: i32, output: T, error: Error) -> Result<T> {
143    if res == 0 {
144        Ok(output)
145    } else {
146        Err(error.extend())
147    }
148}
149
150#[inline]
151pub(crate) fn safe_result<F, O, R>(res: i32, output: O, func: F, error: Error) -> Result<R>
152where
153    F: Fn(O) -> R,
154{
155    if res == 0 {
156        Ok(func(
157            output,
158        ))
159    } else {
160        Err(error.extend())
161    }
162}
163
164#[inline]
165pub(crate) fn new_c_string(string: impl Into<Vec<u8>>) -> Result<CString> {
166    CString::new(string)
167        .map_err(|_| Error::InitializationError("Error initializing C string.".to_string()))
168}
169
170#[inline]
171pub(crate) fn ensure_null_terminated(input: impl AsRef<[u8]>) -> crate::Result<CString> {
172    let bytes = input.as_ref();
173
174    // Check if already null-terminated
175    if bytes.last() == Some(&0) {
176        CString::new(&bytes[..bytes.len() - 1])
177            .map_err(|_| Error::InitializationError("Error initializing C string.".to_string()))
178    } else {
179        // Not null-terminated, append 0 and create CString
180        CString::new(bytes)
181            .map_err(|_| Error::InitializationError("Error initializing C string.".to_string()))
182    }
183}
184
185#[inline]
186pub(crate) unsafe fn new_byte_array(buf: *mut c_void, size: u64) -> Vec<u8> {
187    Vec::from_raw_parts(
188        buf as *mut u8,
189        size as usize,
190        size as usize,
191    )
192}
193
194#[inline]
195pub(crate) unsafe fn new_int_array(array: *mut i32, size: u64) -> Vec<i32> {
196    Vec::from(
197        std::slice::from_raw_parts(
198            array,
199            size as usize,
200        ),
201    )
202}
203
204#[inline]
205pub(crate) unsafe fn new_double_array(array: *mut f64, size: u64) -> Vec<f64> {
206    Vec::from(
207        std::slice::from_raw_parts(
208            array,
209            size as usize,
210        ),
211    )
212}
213
214fn vips_image_sizeof_element(image: &bindings::VipsImage) -> usize {
215    unsafe { bindings::vips_format_sizeof_unsafe(image.BandFmt) as usize }
216}
217
218fn vips_image_sizeof_pel(image: &bindings::VipsImage) -> usize {
219    vips_image_sizeof_element(image) * image.Bands as usize
220}
221
222fn vips_image_sizeof_line(image: &bindings::VipsImage) -> usize {
223    vips_image_sizeof_pel(image) * image.Xsize as usize
224}
225
226unsafe fn vips_image_addr(image: &bindings::VipsImage, x: i32, y: i32) -> *mut u8 {
227    let offset =
228        y as usize * vips_image_sizeof_line(image) + x as usize * vips_image_sizeof_pel(image);
229    image
230        .data
231        .add(offset)
232}
233
234pub(crate) unsafe fn vips_matrix(image: &bindings::VipsImage, x: i32, y: i32) -> *mut f64 {
235    vips_image_addr(
236        image, x, y,
237    ) as *mut f64
238}
239
240pub(crate) const G_TYPE_BOOLEAN: &str = "gboolean";
241pub(crate) const G_TYPE_INT: &str = "gint";
242pub(crate) const G_TYPE_UINT64: &str = "guint64";
243pub(crate) const G_TYPE_DOUBLE: &str = "gdouble";
244pub(crate) const G_TYPE_STRING: &str = "gchararray";
245
246pub(crate) fn get_g_type(name: &str) -> u64 {
247    let type_name = new_c_string(name).unwrap();
248    unsafe { g_type_from_name(type_name.as_ptr()) }
249}