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 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 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}