vips/
buffer.rs

1use crate::{take_vips_error, Error, Result, VipsImage};
2use std::os::raw::{c_char, c_int, c_void};
3use std::ptr::null;
4
5/// Extension trait for thumbnailing from a byte buffer
6///
7/// # Example
8/// ```no_run
9/// use vips::*;
10///
11/// fn main() -> Result<()> {
12///     let _instance = VipsInstance::new("app_test", true)?;
13///     let binding = std::fs::read("./examples/images/kodim01.png")?;
14///     let img_data: &[u8] = binding.as_slice();
15///     let thumbnail = img_data.thumbnail(100, 100)?;
16///     thumbnail.write_to_file("kodim01_thumb.png")?;
17///     Ok(())
18/// }
19/// ```
20///
21pub trait VipsBuffer {
22    fn thumbnail(&self, width: u32, height: u32) -> Result<VipsImage<'_>>;
23}
24
25impl VipsBuffer for &[u8] {
26    /// Create a thumbnail VipsImage from the byte buffer
27    ///
28    /// # Arguments
29    /// * `width` - The desired thumbnail width
30    /// * `height` - The desired thumbnail height
31    ///
32    /// # Errors
33    /// Returns an error if the thumbnail creation fails
34    ///
35    /// # Example
36    /// ```no_run
37    /// use vips::*;
38    ///
39    /// fn main() -> Result<()> {
40    ///     let _instance = VipsInstance::new("app_test", true)?;
41    ///     let binding = std::fs::read("./examples/images/kodim01.png")?;
42    ///     let img_data: &[u8] = binding.as_slice();
43    ///     let thumbnail = img_data.thumbnail(100, 100)?;
44    ///     thumbnail.write_to_file("kodim01_thumb.png")?;
45    ///     Ok(())
46    /// }
47    /// ```
48    ///
49    /// # Safety Note
50    /// The input byte slice must contain valid image data that libvips can decode.
51    /// Providing invalid or corrupted data may lead to undefined behavior.
52    /// Ensure that the data is properly validated before calling this method.
53    ///
54    fn thumbnail(&self, width: u32, height: u32) -> Result<VipsImage<'_>> {
55        unsafe {
56            let mut out = VipsImage::new_memory()?;
57            let ret: c_int = vips_sys::vips_thumbnail_buffer(
58                self.as_ptr() as *mut c_void,
59                self.len(),
60                &mut out.c,
61                width as c_int,
62                c"height".as_ptr(),
63                height as c_int,
64                c"size".as_ptr(),
65                vips_sys::VipsSize::VIPS_SIZE_FORCE,
66                null() as *const c_char,
67            );
68            if ret == 0 {
69                Ok(out)
70            } else {
71                Err(Error::Vips(take_vips_error().unwrap_or_else(|| {
72                    "Unknown error from libvips".to_string()
73                })))
74            }
75        }
76    }
77}