vips/
interpolate.rs

1use crate::{take_vips_error, Error, Result, VipsRegion};
2use std::ffi::CString;
3use std::os::raw::c_void;
4
5/// VipsInterpolate struct wrapping libvips VipsInterpolate
6///
7/// # Example
8/// ```no_run
9/// use vips::*;
10///
11/// fn main() -> Result<()> {
12///     let _instance = VipsInstance::new("app_test", true)?;
13///     let interpolate = VipsInterpolate::bilinear_static();
14///     let method = interpolate.method();
15///     let img = VipsImage::from_file("examples/images/kodim01.png")?;
16///     let region = VipsRegion::new(&img);
17///     let mut out = vec![0u8; 3]; // assuming 3 channels
18///     method.call(&interpolate, &region, &mut out, 1.5, 1.5);
19///     Ok(())
20/// }
21/// ```
22pub struct VipsInterpolate {
23    pub c: *mut vips_sys::VipsInterpolate,
24    is_static: bool,
25}
26
27impl Drop for VipsInterpolate {
28    fn drop(&mut self) {
29        if !self.is_static {
30            unsafe {
31                vips_sys::g_object_unref(self.c as *mut c_void);
32            }
33        }
34    }
35}
36
37impl VipsInterpolate {
38    //
39    // ─── STATIC ─────────────────────────────────────────────────────────────────────
40    //
41
42    // will not implement: vips_interpolate ()
43
44    //
45    // ─── CONSTRUCTORS ───────────────────────────────────────────────────────────────
46    //
47
48    /// Create a new VipsInterpolate by nickname
49    ///
50    /// # Arguments
51    /// * `nickname` - The nickname of the interpolation method
52    ///
53    /// # Errors
54    /// Returns an error if the nickname is invalid
55    ///
56    /// # Example
57    /// ```no_run
58    /// use vips::*;
59    /// fn main() -> Result<()> {
60    ///     let _instance = VipsInstance::new("app_test", true)?;
61    ///     let interpolate = VipsInterpolate::new("bilinear")?;
62    ///     let method = interpolate.method();
63    ///     let img = VipsImage::from_file("examples/images/kodim01.png")?;
64    ///     let region = VipsRegion::new(&img);
65    ///     let mut out = vec![0u8; 3]; // assuming 3 channels
66    ///     method.call(&interpolate, &region, &mut out, 1.5, 1.5);
67    ///     Ok(())
68    /// }
69    /// ```
70    pub fn new(nickname: &str) -> Result<VipsInterpolate> {
71        let nickname = CString::new(nickname)
72            .map_err(|_| Error::Other("Invalid nickname: contains null byte".to_string()))?;
73        let c = unsafe { vips_sys::vips_interpolate_new(nickname.as_ptr()) };
74        if c.is_null() {
75            Err(Error::Vips(take_vips_error().unwrap_or_else(|| {
76                "Unknown error from libvips".to_string()
77            })))
78        } else {
79            Ok(VipsInterpolate {
80                c,
81                is_static: false,
82            })
83        }
84    }
85
86    /// Create a new nearest static VipsInterpolate
87    ///
88    /// # Returns
89    /// A VipsInterpolate instance for nearest neighbor interpolation
90    ///
91    /// # Example
92    /// ```no_run
93    /// use vips::*;
94    /// fn main() -> Result<()> {
95    ///     let _instance = VipsInstance::new("app_test", true)?;
96    ///     let interpolate = VipsInterpolate::nearest_static();
97    ///     let method = interpolate.method();
98    ///     let img = VipsImage::from_file("examples/images/kodim01.png")?;
99    ///     let region = VipsRegion::new(&img);
100    ///     let mut out = vec![0u8; 3]; // assuming 3 channels
101    ///     method.call(&interpolate, &region, &mut out, 1.5, 1.5);
102    ///     Ok(())
103    /// }
104    /// ```
105    ///
106    pub fn nearest_static() -> VipsInterpolate {
107        let c = unsafe { vips_sys::vips_interpolate_nearest_static() };
108        VipsInterpolate { c, is_static: true }
109    }
110
111    /// Create a new bilinear static VipsInterpolate
112    ///
113    /// # Returns
114    /// A VipsInterpolate instance for bilinear interpolation
115    ///
116    /// # Example
117    /// ```no_run
118    /// use vips::*;
119    ///
120    /// fn main() -> Result<()> {
121    ///     let _instance = VipsInstance::new("app_test", true)?;
122    ///     let interpolate = VipsInterpolate::bilinear_static();
123    ///     let method = interpolate.method();
124    ///     let img = VipsImage::from_file("examples/images/kodim01.png")?;
125    ///     let region = VipsRegion::new(&img);
126    ///     let mut out = vec![0u8; 3]; // assuming 3 channels
127    ///     method.call(&interpolate, &region, &mut out, 1.5, 1.5);
128    ///     Ok(())
129    /// }
130    /// ```
131    pub fn bilinear_static() -> VipsInterpolate {
132        let c = unsafe { vips_sys::vips_interpolate_bilinear_static() };
133        VipsInterpolate { c, is_static: true }
134    }
135
136    //
137    // ─── PROPERTIES ─────────────────────────────────────────────────────────────────
138    //
139
140    /// Get the interpolation method
141    ///
142    /// # Returns
143    /// A VipsInterpolateMethod instance representing the interpolation method
144    ///
145    /// # Example
146    /// ```no_run
147    /// use vips::*;
148    ///
149    /// fn main() -> Result<()> {
150    ///     let _instance = VipsInstance::new("app_test", true)?;
151    ///     let interpolate = VipsInterpolate::bilinear_static();
152    ///     let method = interpolate.method();
153    ///     let img = VipsImage::from_file("examples/images/kodim01.png")?;
154    ///     let region = VipsRegion::new(&img);
155    ///     let mut out = vec![0u8; 3]; // assuming 3 channels
156    ///     method.call(&interpolate, &region, &mut out, 1.5, 1.5);
157    ///     Ok(())
158    /// }
159    /// ```
160    pub fn method(&self) -> VipsInterpolateMethod {
161        let c = unsafe { vips_sys::vips_interpolate_get_method(self.c) };
162        VipsInterpolateMethod { c }
163    }
164
165    /// Get the window size
166    ///
167    /// # Returns
168    /// The window size used by the interpolation method
169    ///
170    /// # Example
171    /// ```no_run
172    /// use vips::*;
173    ///
174    /// fn main() -> Result<()> {
175    ///    let interpolate = VipsInterpolate::bilinear_static();
176    ///    let window_size = interpolate.window_size();
177    ///     println!("Window size: {}", window_size);
178    ///     Ok(())
179    /// }
180    /// ```
181    pub fn window_size(&self) -> i32 {
182        unsafe { vips_sys::vips_interpolate_get_window_size(self.c) }
183    }
184
185    /// Get the window offset
186    ///
187    /// # Returns
188    /// The window offset used by the interpolation method
189    ///
190    /// # Example
191    /// ```no_run
192    /// use vips::*;
193    ///
194    /// fn main() -> Result<()> {
195    ///     let interpolate = VipsInterpolate::bilinear_static();
196    ///     let window_offset = interpolate.window_offset();
197    ///     println!("Window offset: {}", window_offset);
198    ///     Ok(())
199    /// }
200    /// ```
201    pub fn window_offset(&self) -> i32 {
202        unsafe { vips_sys::vips_interpolate_get_window_offset(self.c) }
203    }
204}
205
206/// Function pointer type for VipsInterpolateMethod
207///
208/// # Example
209/// ```no_run
210/// use vips::*;
211///
212/// fn main() -> Result<()> {
213///     let _instance = VipsInstance::new("app_test", true)?;
214///     let interpolate = VipsInterpolate::bilinear_static();
215///     let method = interpolate.method();
216///     let img = VipsImage::from_file("examples/images/kodim01.png")?;
217///     let region = VipsRegion::new(&img);
218///     let mut out = vec![0u8; 3]; // assuming 3 channels
219///     method.call(&interpolate, &region, &mut out, 1.5, 1.5);
220///     Ok(())
221/// }
222/// ```
223pub struct VipsInterpolateMethod {
224    c: vips_sys::VipsInterpolateMethod,
225}
226
227impl VipsInterpolateMethod {
228    /// Call the interpolation method
229    ///
230    /// # Arguments
231    /// * `interpolate` - The VipsInterpolate instance
232    /// * `in_` - The input VipsRegion
233    /// * `out` - The output buffer to write the interpolated pixel
234    /// * `x` - The x coordinate to interpolate
235    /// * `y` - The y coordinate to interpolate
236    ///
237    /// # Example
238    /// ```no_run
239    /// use vips::*;
240    /// fn main() -> Result<()> {
241    ///     let interpolate = VipsInterpolate::bilinear_static();
242    ///     let _instance = VipsInstance::new("app_test", true)?;
243    ///     let img = VipsImage::from_file("examples/images/kodim01.png")?;
244    ///     let region = VipsRegion::new(&img);
245    ///     let mut out = vec![0u8; 3]; // assuming 3 channels
246    ///     let method = interpolate.method();
247    ///     method.call(&interpolate, &region, &mut out, 1.5, 1.5);
248    ///     Ok(())
249    /// }
250    /// ```
251    ///
252    pub fn call(
253        &self,
254        interpolate: &VipsInterpolate,
255        in_: &VipsRegion,
256        out: &mut [u8],
257        x: f64,
258        y: f64,
259    ) {
260        unsafe { self.c.unwrap()(interpolate.c, out.as_mut_ptr() as *mut c_void, in_.c, x, y) }
261    }
262}