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 as_vips = array
81 .iter()
82 .map(|v| v.ctx)
83 .collect::<Vec<_>>()
84 .as_mut_ptr();
85 VipsArrayImageWrapper {
86 ctx: unsafe {
87 bindings::vips_array_image_new(
88 as_vips,
89 len,
90 )
91 },
92 }
93 }
94}
95
96pub(crate) fn vips_image_result(res: *mut bindings::VipsImage, err: Error) -> Result<VipsImage> {
97 if res.is_null() {
98 Err(err.extend())
99 } else {
100 Ok(
101 VipsImage {
102 ctx: res,
103 },
104 )
105 }
106}
107
108pub(crate) fn vips_image_result_ext(res: VipsImage, err: Error) -> Result<VipsImage> {
109 if res
110 .ctx
111 .is_null()
112 {
113 Err(err.extend())
114 } else {
115 Ok(res)
116 }
117}
118
119pub(crate) fn vips_source_result(res: *mut bindings::VipsSource, err: Error) -> Result<VipsSource> {
120 if res.is_null() {
121 Err(err.extend())
122 } else {
123 Ok(
124 VipsSource {
125 ctx: res,
126 },
127 )
128 }
129}
130
131pub(crate) fn vips_target_result(res: *mut bindings::VipsTarget, err: Error) -> Result<VipsTarget> {
132 if res.is_null() {
133 Err(err.extend())
134 } else {
135 Ok(
136 VipsTarget {
137 ctx: res,
138 },
139 )
140 }
141}
142
143#[inline]
144pub fn result<T>(res: i32, output: T, error: Error) -> Result<T> {
145 if res == 0 {
146 Ok(output)
147 } else {
148 Err(error.extend())
149 }
150}
151
152#[inline]
153pub(crate) fn safe_result<F, O, R>(res: i32, output: O, func: F, error: Error) -> Result<R>
154where
155 F: Fn(O) -> R,
156{
157 if res == 0 {
158 Ok(func(
159 output,
160 ))
161 } else {
162 Err(error.extend())
163 }
164}
165
166#[inline]
167pub(crate) fn new_c_string(string: impl Into<Vec<u8>>) -> Result<CString> {
168 CString::new(string)
169 .map_err(|_| Error::InitializationError("Error initializing C string.".to_string()))
170}
171
172#[inline]
173pub(crate) fn ensure_null_terminated(input: impl AsRef<[u8]>) -> crate::Result<CString> {
174 let bytes = input.as_ref();
175
176 if bytes.last() == Some(&0) {
178 CString::new(&bytes[..bytes.len() - 1])
179 .map_err(|_| Error::InitializationError("Error initializing C string.".to_string()))
180 } else {
181 CString::new(bytes)
183 .map_err(|_| Error::InitializationError("Error initializing C string.".to_string()))
184 }
185}
186
187#[inline]
188pub(crate) unsafe fn new_byte_array(buf: *mut c_void, size: u64) -> Vec<u8> {
189 Vec::from_raw_parts(
190 buf as *mut u8,
191 size as usize,
192 size as usize,
193 )
194}
195
196#[inline]
197pub(crate) unsafe fn new_int_array(array: *mut i32, size: u64) -> Vec<i32> {
198 Vec::from(
199 std::slice::from_raw_parts(
200 array,
201 size as usize,
202 ),
203 )
204}
205
206#[inline]
207pub(crate) unsafe fn new_double_array(array: *mut f64, size: u64) -> Vec<f64> {
208 Vec::from(
209 std::slice::from_raw_parts(
210 array,
211 size as usize,
212 ),
213 )
214}
215
216fn vips_image_sizeof_element(image: &bindings::VipsImage) -> usize {
217 unsafe { bindings::vips_format_sizeof_unsafe(image.BandFmt) as usize }
218}
219
220fn vips_image_sizeof_pel(image: &bindings::VipsImage) -> usize {
221 vips_image_sizeof_element(image) * image.Bands as usize
222}
223
224fn vips_image_sizeof_line(image: &bindings::VipsImage) -> usize {
225 vips_image_sizeof_pel(image) * image.Xsize as usize
226}
227
228unsafe fn vips_image_addr(image: &bindings::VipsImage, x: i32, y: i32) -> *mut u8 {
229 let offset =
230 y as usize * vips_image_sizeof_line(image) + x as usize * vips_image_sizeof_pel(image);
231 image
232 .data
233 .add(offset)
234}
235
236pub(crate) unsafe fn vips_matrix(image: &bindings::VipsImage, x: i32, y: i32) -> *mut f64 {
237 vips_image_addr(
238 image, x, y,
239 ) as *mut f64
240}
241
242pub(crate) const G_TYPE_BOOLEAN: &str = "gboolean";
243pub(crate) const G_TYPE_INT: &str = "gint";
244pub(crate) const G_TYPE_UINT64: &str = "guint64";
245pub(crate) const G_TYPE_DOUBLE: &str = "gdouble";
246pub(crate) const G_TYPE_STRING: &str = "gchararray";
247
248pub(crate) fn get_g_type(name: &str) -> u64 {
249 let type_name = new_c_string(name).unwrap();
250 unsafe { g_type_from_name(type_name.as_ptr()) }
251}