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