1use crate::ffi;
2use crate::{Error, Result, VipsInterpolate, take_vips_error};
3use std::ffi::CString;
4use std::marker::PhantomData;
5use std::os::raw::{c_char, c_int, c_void};
6use std::path::Path;
7use std::ptr::{null, null_mut};
8use vips_sys::{
9 VipsBandFormat, VipsCombineMode, VipsCompassDirection, VipsDirection, VipsExtend,
10 VipsInteresting, VipsKernel, VipsSize,
11};
12
13#[cfg(feature = "v8_18")]
14mod v8_18;
15
16#[cfg(feature = "v8_18")]
18pub fn interpretation_bands(interpretation: vips_sys::VipsInterpretation) -> i32 {
19 unsafe { vips_sys::vips_interpretation_bands(interpretation) }
21}
22
23fn path_to_cstring(path: &Path) -> Result<CString> {
25 #[cfg(unix)]
26 {
27 use std::os::unix::ffi::OsStrExt;
28 CString::new(path.as_os_str().as_bytes())
29 .map_err(|e| Error::InitFailed(format!("invalid path: {e}")))
30 }
31 #[cfg(not(unix))]
32 {
33 CString::new(path.to_string_lossy().as_bytes())
34 .map_err(|e| Error::InitFailed(format!("invalid path: {e}")))
35 }
36}
37
38fn validate_memory(
39 buf: &[u8],
40 width: u32,
41 height: u32,
42 bands: u8,
43 format: VipsBandFormat,
44) -> Result<()> {
45 use VipsBandFormat::*;
46 let (sample_bytes, alignment) = match format {
47 VIPS_FORMAT_UCHAR | VIPS_FORMAT_CHAR => (1, 1),
48 VIPS_FORMAT_USHORT | VIPS_FORMAT_SHORT => (2, 2),
49 VIPS_FORMAT_UINT | VIPS_FORMAT_INT | VIPS_FORMAT_FLOAT => (4, 4),
50 VIPS_FORMAT_COMPLEX => (8, 4),
51 VIPS_FORMAT_DOUBLE => (8, 8),
52 VIPS_FORMAT_DPCOMPLEX => (16, 8),
53 _ => return Err(Error::Other("invalid memory image band format".into())),
54 };
55 let required = (width as usize)
56 .checked_mul(height as usize)
57 .and_then(|n| n.checked_mul(bands as usize))
58 .and_then(|n| n.checked_mul(sample_bytes));
59 if width == 0
60 || height == 0
61 || bands == 0
62 || width > i32::MAX as u32
63 || height > i32::MAX as u32
64 || required.is_none_or(|n| n > buf.len())
65 || buf.as_ptr().align_offset(alignment) != 0
66 {
67 return Err(Error::Other(
68 "memory image requires positive i32 dimensions, enough bytes, and aligned samples"
69 .into(),
70 ));
71 }
72 Ok(())
73}
74
75pub struct VipsImage<'a> {
100 c: std::ptr::NonNull<vips_sys::VipsImage>,
102 marker: PhantomData<&'a ()>,
103 writable: bool,
105}
106
107impl<'a> Drop for VipsImage<'a> {
108 fn drop(&mut self) {
109 unsafe { ffi::unref(self.c.as_ptr().cast()) };
111 }
112}
113
114unsafe extern "C" fn image_postclose(_ptr: *mut vips_sys::VipsImage, user_data: *mut c_void) {
120 if user_data.is_null() {
121 return;
122 }
123 let b: Box<Vec<u8>> = unsafe { Box::from_raw(user_data as *mut Vec<u8>) };
125 drop(b);
126}
127
128impl<'a> VipsImage<'a> {
129 #[inline]
133 pub fn as_ptr(&self) -> *mut vips_sys::VipsImage {
134 self.c.as_ptr()
135 }
136
137 pub(crate) unsafe fn from_raw(ptr: *mut vips_sys::VipsImage) -> VipsImage<'a> {
143 let c = std::ptr::NonNull::new(ptr).expect("VipsImage::from_raw(null)");
144 VipsImage {
145 c,
146 marker: PhantomData,
147 writable: false,
148 }
149 }
150
151 fn ensure_writable(&mut self) -> Result<()> {
155 if !self.writable {
156 let mut copy = Self::new_memory()?;
157 let ret = unsafe { vips_sys::vips_image_write(self.as_ptr(), copy.as_ptr()) };
159 ffi::ret_to_result(ret)?;
160 copy.writable = true;
161 *self = copy;
162 }
163 Ok(())
164 }
165
166 pub fn new() -> Result<VipsImage<'a>> {
186 let c = unsafe { vips_sys::vips_image_new() };
188 result(c)
189 }
190
191 pub fn new_memory() -> Result<VipsImage<'a>> {
207 let c = unsafe { vips_sys::vips_image_new_memory() };
209 result(c)
210 }
211
212 pub fn from_file(path: impl AsRef<Path>) -> Result<VipsImage<'a>> {
234 let path = path_to_cstring(path.as_ref())?;
235 unsafe {
236 let ptr = vips_sys::vips_image_new_from_file(path.as_ptr(), null() as *const c_char);
237 result(ptr)
238 }
239 }
240
241 pub fn from_file_with_access(
244 path: impl AsRef<Path>,
245 access: vips_sys::VipsAccess,
246 ) -> Result<VipsImage<'a>> {
247 let path = path_to_cstring(path.as_ref())?;
248 let ptr = unsafe {
250 vips_sys::vips_image_new_from_file(
251 path.as_ptr(),
252 c"access".as_ptr(),
253 access,
254 null() as *const c_char,
255 )
256 };
257 result(ptr)
258 }
259
260 pub fn from_memory(
285 buf: Vec<u8>,
286 width: u32,
287 height: u32,
288 bands: u8,
289 format: VipsBandFormat,
290 ) -> Result<VipsImage<'a>> {
291 validate_memory(&buf, width, height, bands, format)?;
292 let b = buf;
293 let c = unsafe {
294 vips_sys::vips_image_new_from_memory(
295 b.as_ptr() as *const c_void,
296 b.len(),
297 width as i32,
298 height as i32,
299 bands as i32,
300 format,
301 )
302 };
303
304 if c.is_null() {
305 return Err(Error::Vips(
306 take_vips_error().unwrap_or_else(|| "Unknown error from libvips".to_string()),
307 ));
308 }
309
310 let bb: Box<Vec<u8>> = Box::new(b);
311 let raw: *mut c_void = Box::into_raw(bb) as *mut c_void;
312
313 unsafe {
315 let callback: unsafe extern "C" fn() =
316 std::mem::transmute(image_postclose as *const ());
317 vips_sys::g_signal_connect_data(
318 c as *mut c_void,
319 c"postclose".as_ptr(),
320 Some(callback),
321 raw,
322 None,
323 vips_sys::GConnectFlags::G_CONNECT_AFTER,
324 );
325 };
326
327 let mut image = unsafe { VipsImage::from_raw(c) };
329 image.writable = true;
330 Ok(image)
331 }
332
333 pub fn from_memory_reference(
361 buf: &'a [u8],
362 width: u32,
363 height: u32,
364 bands: u8,
365 format: VipsBandFormat,
366 ) -> Result<VipsImage<'a>> {
367 validate_memory(buf, width, height, bands, format)?;
368 let c = unsafe {
369 vips_sys::vips_image_new_from_memory(
370 buf.as_ptr() as *const c_void,
371 buf.len(),
372 width as i32,
373 height as i32,
374 bands as i32,
375 format,
376 )
377 };
378
379 result(c)
380 }
381
382 pub fn from_buffer(buf: &'a [u8]) -> Result<VipsImage<'a>> {
405 let c = unsafe {
406 vips_sys::vips_image_new_from_buffer(
407 buf.as_ptr() as *const c_void,
408 buf.len(),
409 null(),
410 null() as *const c_char,
411 )
412 };
413
414 result(c)
415 }
416
417 pub fn from_buffer_with_access(
420 buf: &'a [u8],
421 access: vips_sys::VipsAccess,
422 ) -> Result<VipsImage<'a>> {
423 let ptr = unsafe {
425 vips_sys::vips_image_new_from_buffer(
426 buf.as_ptr().cast(),
427 buf.len(),
428 c"".as_ptr(),
429 c"access".as_ptr(),
430 access,
431 null() as *const c_char,
432 )
433 };
434 result(ptr)
435 }
436
437 pub fn draw_rect(
469 &mut self,
470 ink: &[f64],
471 left: u32,
472 top: u32,
473 width: u32,
474 height: u32,
475 ) -> Result<()> {
476 self.ensure_writable()?;
477 let ret = unsafe {
478 vips_sys::vips_draw_rect(
479 self.c.as_ptr(),
480 ink.as_ptr() as *mut f64,
481 ink.len() as i32,
482 left as i32,
483 top as i32,
484 width as i32,
485 height as i32,
486 null() as *const c_char,
487 )
488 };
489 result_draw(ret)
490 }
491 pub fn draw_rect1(
492 &mut self,
493 ink: f64,
494 left: u32,
495 top: u32,
496 width: u32,
497 height: u32,
498 ) -> Result<()> {
499 self.ensure_writable()?;
500 let ret = unsafe {
501 vips_sys::vips_draw_rect1(
502 self.c.as_ptr(),
503 ink,
504 left as i32,
505 top as i32,
506 width as i32,
507 height as i32,
508 null() as *const c_char,
509 )
510 };
511 result_draw(ret)
512 }
513 pub fn draw_point(&mut self, ink: &[f64], x: i32, y: i32) -> Result<()> {
514 self.ensure_writable()?;
515 let ret = unsafe {
516 vips_sys::vips_draw_point(
517 self.c.as_ptr(),
518 ink.as_ptr() as *mut f64,
519 ink.len() as i32,
520 x,
521 y,
522 null() as *const c_char,
523 )
524 };
525 result_draw(ret)
526 }
527 pub fn draw_point1(&mut self, ink: f64, x: i32, y: i32) -> Result<()> {
528 self.ensure_writable()?;
529 let ret = unsafe {
530 vips_sys::vips_draw_point1(self.c.as_ptr(), ink, x, y, null() as *const c_char)
531 };
532 result_draw(ret)
533 }
534 pub fn draw_image(
535 &mut self,
536 img: &VipsImage,
537 x: i32,
538 y: i32,
539 mode: VipsCombineMode,
540 ) -> Result<()> {
541 self.ensure_writable()?;
542 let ret = unsafe {
543 vips_sys::vips_draw_image(
544 self.c.as_ptr(),
545 img.as_ptr(),
546 x,
547 y,
548 c"mode".as_ptr(),
549 mode,
550 null() as *const c_char,
551 )
552 };
553 result_draw(ret)
554 }
555 pub fn draw_mask(&mut self, ink: &[f64], mask: &VipsImage, x: i32, y: i32) -> Result<()> {
556 self.ensure_writable()?;
557 let ret = unsafe {
558 vips_sys::vips_draw_mask(
559 self.c.as_ptr(),
560 ink.as_ptr() as *mut f64,
561 ink.len() as i32,
562 mask.as_ptr(),
563 x,
564 y,
565 null() as *const c_char,
566 )
567 };
568 result_draw(ret)
569 }
570 pub fn draw_mask1(&mut self, ink: f64, mask: &VipsImage, x: i32, y: i32) -> Result<()> {
571 self.ensure_writable()?;
572 let ret = unsafe {
573 vips_sys::vips_draw_mask1(
574 self.c.as_ptr(),
575 ink,
576 mask.as_ptr(),
577 x,
578 y,
579 null() as *const c_char,
580 )
581 };
582 result_draw(ret)
583 }
584 pub fn draw_line(&mut self, ink: &[f64], x1: i32, y1: i32, x2: i32, y2: i32) -> Result<()> {
585 self.ensure_writable()?;
586 let ret = unsafe {
587 vips_sys::vips_draw_line(
588 self.c.as_ptr(),
589 ink.as_ptr() as *mut f64,
590 ink.len() as i32,
591 x1,
592 y1,
593 x2,
594 y2,
595 null() as *const c_char,
596 )
597 };
598 result_draw(ret)
599 }
600 pub fn draw_line1(&mut self, ink: f64, x1: i32, y1: i32, x2: i32, y2: i32) -> Result<()> {
601 self.ensure_writable()?;
602 let ret = unsafe {
603 vips_sys::vips_draw_line1(
604 self.c.as_ptr(),
605 ink,
606 x1,
607 y1,
608 x2,
609 y2,
610 null() as *const c_char,
611 )
612 };
613 result_draw(ret)
614 }
615 pub fn draw_circle(&mut self, ink: &[f64], cx: i32, cy: i32, r: i32, fill: bool) -> Result<()> {
616 self.ensure_writable()?;
617 let ret = unsafe {
618 vips_sys::vips_draw_circle(
619 self.c.as_ptr(),
620 ink.as_ptr() as *mut f64,
621 ink.len() as i32,
622 cx,
623 cy,
624 r,
625 c"fill".as_ptr(),
626 fill as i32,
627 null() as *const c_char,
628 )
629 };
630 result_draw(ret)
631 }
632 pub fn draw_circle1(&mut self, ink: f64, cx: i32, cy: i32, r: i32, fill: bool) -> Result<()> {
633 self.ensure_writable()?;
634 let ret = unsafe {
635 vips_sys::vips_draw_circle1(
636 self.c.as_ptr(),
637 ink,
638 cx,
639 cy,
640 r,
641 c"fill".as_ptr(),
642 fill as i32,
643 null() as *const c_char,
644 )
645 };
646 result_draw(ret)
647 }
648 pub fn draw_flood(&mut self, ink: &[f64], x: i32, y: i32) -> Result<()> {
649 self.ensure_writable()?;
650 let ret = unsafe {
651 vips_sys::vips_draw_flood(
652 self.c.as_ptr(),
653 ink.as_ptr() as *mut f64,
654 ink.len() as i32,
655 x,
656 y,
657 null() as *const c_char,
658 )
659 };
660 result_draw(ret)
661 }
662 pub fn draw_flood1(&mut self, ink: f64, x: i32, y: i32) -> Result<()> {
663 self.ensure_writable()?;
664 let ret = unsafe {
665 vips_sys::vips_draw_flood1(self.c.as_ptr(), ink, x, y, null() as *const c_char)
666 };
667 result_draw(ret)
668 }
669 pub fn draw_smudge(&mut self, left: u32, top: u32, width: u32, height: u32) -> Result<()> {
670 self.ensure_writable()?;
671 let ret = unsafe {
672 vips_sys::vips_draw_smudge(
673 self.c.as_ptr(),
674 left as i32,
675 top as i32,
676 width as i32,
677 height as i32,
678 null() as *const c_char,
679 )
680 };
681 result_draw(ret)
682 }
683
684 pub fn merge(
689 &self,
690 another: &VipsImage<'a>,
691 direction: VipsDirection,
692 dx: i32,
693 dy: i32,
694 mblend: Option<i32>,
695 ) -> Result<VipsImage<'a>> {
696 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
697 let ret = unsafe {
698 match mblend {
699 Some(mblend) => vips_sys::vips_merge(
700 self.c.as_ptr(),
701 another.as_ptr(),
702 &mut out_ptr,
703 direction,
704 dx,
705 dy,
706 c"mblend".as_ptr(),
707 mblend,
708 null() as *const c_char,
709 ),
710 None => vips_sys::vips_merge(
711 self.c.as_ptr(),
712 another.as_ptr(),
713 &mut out_ptr,
714 direction,
715 dx,
716 dy,
717 null() as *const c_char,
718 ),
719 }
720 };
721 result_with_ret(out_ptr, ret)
722 }
723
724 #[allow(clippy::too_many_arguments)]
725 pub fn mosaic(
726 &self,
727 sec: &VipsImage<'a>,
728 direction: VipsDirection,
729 xref: i32,
730 yref: i32,
731 xsec: i32,
732 ysec: i32,
733 bandno: Option<i32>,
734 hwindow: Option<i32>,
735 harea: Option<i32>,
736 mblend: Option<i32>,
737 ) -> Result<VipsImage<'a>> {
738 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
739 let ret = unsafe {
740 vips_sys::vips_mosaic(
741 self.c.as_ptr(),
742 sec.as_ptr(),
743 &mut out_ptr,
744 direction,
745 xref,
746 yref,
747 xsec,
748 ysec,
749 c"bandno".as_ptr(),
750 bandno.unwrap_or(-1),
751 c"hwindow".as_ptr(),
752 hwindow.unwrap_or(5),
753 c"harea".as_ptr(),
754 harea.unwrap_or(2),
755 c"mblend".as_ptr(),
756 mblend.unwrap_or(-1),
757 null() as *const c_char,
758 )
759 };
760 result_with_ret(out_ptr, ret)
761 }
762
763 #[allow(clippy::too_many_arguments)]
764 pub fn mosaic1(
765 &self,
766 sec: &VipsImage<'a>,
767 direction: VipsDirection,
768 xr1: i32,
769 yr1: i32,
770 xs1: i32,
771 ys1: i32,
772 xr2: i32,
773 yr2: i32,
774 xs2: i32,
775 ys2: i32,
776 search: Option<bool>,
777 hwindow: Option<i32>,
778 harea: Option<i32>,
779 interpolate: Option<VipsInterpolate>,
780 mblend: Option<i32>,
781 bandno: Option<i32>,
782 ) -> Result<VipsImage<'a>> {
783 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
784 let ret = unsafe {
785 match interpolate {
786 Some(interpolate) => vips_sys::vips_mosaic1(
787 self.c.as_ptr(),
788 sec.as_ptr(),
789 &mut out_ptr,
790 direction,
791 xr1,
792 yr1,
793 xs1,
794 ys1,
795 xr2,
796 yr2,
797 xs2,
798 ys2,
799 c"search".as_ptr(),
800 search.unwrap_or(false) as i32,
801 c"hwindow".as_ptr(),
802 hwindow.unwrap_or(5),
803 c"harea".as_ptr(),
804 harea.unwrap_or(2),
805 c"interpolate".as_ptr(),
806 interpolate.as_ptr(),
807 c"mblend".as_ptr(),
808 mblend.unwrap_or(-1),
809 c"bandno".as_ptr(),
810 bandno.unwrap_or(-1),
811 null() as *const c_char,
812 ),
813 None => vips_sys::vips_mosaic1(
814 self.c.as_ptr(),
815 sec.as_ptr(),
816 &mut out_ptr,
817 direction,
818 xr1,
819 yr1,
820 xs1,
821 ys1,
822 xr2,
823 yr2,
824 xs2,
825 ys2,
826 c"search".as_ptr(),
827 search.unwrap_or(false) as i32,
828 c"hwindow".as_ptr(),
829 hwindow.unwrap_or(5),
830 c"harea".as_ptr(),
831 harea.unwrap_or(2),
832 c"mblend".as_ptr(),
833 mblend.unwrap_or(-1),
834 c"bandno".as_ptr(),
835 bandno.unwrap_or(-1),
836 null() as *const c_char,
837 ),
838 }
839 };
840 result_with_ret(out_ptr, ret)
841 }
842
843 #[allow(clippy::too_many_arguments)]
844 pub fn match_(
845 &self,
846 sec: &VipsImage<'a>,
847 xr1: i32,
848 yr1: i32,
849 xs1: i32,
850 ys1: i32,
851 xr2: i32,
852 yr2: i32,
853 xs2: i32,
854 ys2: i32,
855 search: Option<bool>,
856 hwindow: Option<i32>,
857 harea: Option<i32>,
858 interpolate: Option<VipsInterpolate>,
859 ) -> Result<VipsImage<'a>> {
860 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
861 let ret = unsafe {
862 match interpolate {
863 Some(interpolate) => vips_sys::vips_match(
864 self.c.as_ptr(),
865 sec.as_ptr(),
866 &mut out_ptr,
867 xr1,
868 yr1,
869 xs1,
870 ys1,
871 xr2,
872 yr2,
873 xs2,
874 ys2,
875 c"search".as_ptr(),
876 search.unwrap_or(false) as i32,
877 c"hwindow".as_ptr(),
878 hwindow.unwrap_or(5),
879 c"harea".as_ptr(),
880 harea.unwrap_or(2),
881 c"interpolate".as_ptr(),
882 interpolate.as_ptr(),
883 null() as *const c_char,
884 ),
885 None => vips_sys::vips_match(
886 self.c.as_ptr(),
887 sec.as_ptr(),
888 &mut out_ptr,
889 xr1,
890 yr1,
891 xs1,
892 ys1,
893 xr2,
894 yr2,
895 xs2,
896 ys2,
897 c"search".as_ptr(),
898 search.unwrap_or(false) as i32,
899 c"hwindow".as_ptr(),
900 hwindow.unwrap_or(5),
901 c"harea".as_ptr(),
902 harea.unwrap_or(2),
903 null() as *const c_char,
904 ),
905 }
906 };
907 result_with_ret(out_ptr, ret)
908 }
909
910 pub fn globalbalance(
911 &self,
912 gamma: Option<f64>,
913 int_output: Option<bool>,
914 ) -> Result<VipsImage<'a>> {
915 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
916 let ret = unsafe {
917 vips_sys::vips_globalbalance(
918 self.c.as_ptr(),
919 &mut out_ptr,
920 c"gamma".as_ptr(),
921 gamma.unwrap_or(1.6),
922 c"int_output".as_ptr(),
923 int_output.unwrap_or(false) as i32,
924 null() as *const c_char,
925 )
926 };
927 result_with_ret(out_ptr, ret)
928 }
929
930 pub fn remosaic(&self, old_str: &str, new_str: &str) -> Result<VipsImage<'a>> {
931 let old_str = CString::new(old_str)
932 .map_err(|e| Error::InitFailed(format!("invalid old_str: {e}")))?;
933 let new_str = CString::new(new_str)
934 .map_err(|e| Error::InitFailed(format!("invalid new_str: {e}")))?;
935 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
936 let ret = unsafe {
937 vips_sys::vips_remosaic(
938 self.c.as_ptr(),
939 &mut out_ptr,
940 old_str.as_ptr(),
941 new_str.as_ptr(),
942 null() as *const c_char,
943 )
944 };
945 result_with_ret(out_ptr, ret)
946 }
947
948 #[inline]
954 pub fn width(&self) -> u32 {
955 unsafe { (*self.c.as_ptr()).Xsize as u32 }
957 }
958
959 #[inline]
961 pub fn height(&self) -> u32 {
962 unsafe { (*self.c.as_ptr()).Ysize as u32 }
964 }
965
966 #[inline]
968 pub fn size(&self) -> (u32, u32) {
969 (self.width(), self.height())
970 }
971
972 #[inline]
974 pub fn bands(&self) -> u32 {
975 unsafe { (*self.c.as_ptr()).Bands as u32 }
977 }
978
979 pub fn thumbnail(&self, width: u32, height: u32, size: VipsSize) -> Result<VipsImage<'a>> {
1013 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1014 let ret = unsafe {
1015 vips_sys::vips_thumbnail_image(
1016 self.c.as_ptr(),
1017 &mut out_ptr,
1018 width as i32,
1019 c"height".as_ptr(),
1020 height as i32,
1021 c"size".as_ptr(),
1022 size,
1023 null() as *const c_char,
1024 )
1025 };
1026 result_with_ret(out_ptr, ret)
1027 }
1028
1029 pub fn thumbnail_file(
1056 path: impl AsRef<Path>,
1057 width: u32,
1058 height: u32,
1059 size: VipsSize,
1060 ) -> Result<VipsImage<'static>> {
1061 let path = path_to_cstring(path.as_ref())?;
1062 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1063 let ret = unsafe {
1065 vips_sys::vips_thumbnail(
1066 path.as_ptr(),
1067 &mut out_ptr,
1068 width as c_int,
1069 c"height".as_ptr(),
1070 height as c_int,
1071 c"size".as_ptr(),
1072 size,
1073 null() as *const c_char,
1074 )
1075 };
1076 result_with_ret(out_ptr, ret)
1077 }
1078
1079 pub fn thumbnail_buffer(
1110 buf: &'a [u8],
1111 width: u32,
1112 height: u32,
1113 size: VipsSize,
1114 ) -> Result<VipsImage<'a>> {
1115 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1116 let ret = unsafe {
1118 vips_sys::vips_thumbnail_buffer(
1119 buf.as_ptr() as *mut c_void,
1120 buf.len(),
1121 &mut out_ptr,
1122 width as c_int,
1123 c"height".as_ptr(),
1124 height as c_int,
1125 c"size".as_ptr(),
1126 size,
1127 null() as *const c_char,
1128 )
1129 };
1130 result_with_ret(out_ptr, ret)
1131 }
1132
1133 pub fn resize(
1159 &self,
1160 scale: f64,
1161 vscale: Option<f64>,
1162 kernel: Option<VipsKernel>,
1163 ) -> Result<VipsImage<'a>> {
1164 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1165 let ret = unsafe {
1166 vips_sys::vips_resize(
1167 self.c.as_ptr(),
1168 &mut out_ptr,
1169 scale,
1170 c"vscale".as_ptr(),
1171 vscale.unwrap_or(scale),
1172 c"kernel".as_ptr(),
1173 kernel.unwrap_or(VipsKernel::VIPS_KERNEL_LANCZOS3),
1174 null() as *const c_char,
1175 )
1176 };
1177 result_with_ret(out_ptr, ret)
1178 }
1179
1180 pub fn resize_reduce(
1186 &self,
1187 scale: f64,
1188 vscale: Option<f64>,
1189 kernel: Option<VipsKernel>,
1190 ) -> Result<VipsImage<'a>> {
1191 let vscale = vscale.unwrap_or(scale);
1192 if scale >= 1.0 && vscale >= 1.0 {
1193 return self.resize(scale, Some(vscale), kernel);
1194 }
1195
1196 let hscale = scale.max(f64::EPSILON);
1197 let vscale = vscale.max(f64::EPSILON);
1198 let pixels = self.width() as u64 * self.height() as u64;
1199 if pixels < 4_000_000 {
1201 return self.resize(hscale, Some(vscale), kernel);
1202 }
1203
1204 let hshrink = if hscale < 0.5 {
1205 (1.0 / hscale / 2.0).floor().max(1.0)
1206 } else {
1207 1.0
1208 };
1209 let vshrink = if vscale < 0.5 {
1210 (1.0 / vscale / 2.0).floor().max(1.0)
1211 } else {
1212 1.0
1213 };
1214
1215 let pre = if hshrink > 1.0 || vshrink > 1.0 {
1216 Some(self.shrink_box(hshrink, vshrink)?)
1217 } else {
1218 None
1219 };
1220 let base = pre.as_ref().unwrap_or(self);
1221 base.resize(hscale * hshrink, Some(vscale * vshrink), kernel)
1222 }
1223
1224 pub fn shrink_box(&self, xshrink: f64, yshrink: f64) -> Result<VipsImage<'a>> {
1226 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1227 let ret = unsafe {
1228 vips_sys::vips_shrink(
1229 self.c.as_ptr(),
1230 &mut out_ptr,
1231 xshrink,
1232 yshrink,
1233 null() as *const c_char,
1234 )
1235 };
1236 result_with_ret(out_ptr, ret)
1237 }
1238
1239 pub fn reduce(
1241 &self,
1242 hshrink: f64,
1243 vshrink: f64,
1244 kernel: Option<VipsKernel>,
1245 centre: Option<bool>,
1246 ) -> Result<VipsImage<'a>> {
1247 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1248 let ret = unsafe {
1249 vips_sys::vips_reduce(
1250 self.c.as_ptr(),
1251 &mut out_ptr,
1252 hshrink,
1253 vshrink,
1254 c"kernel".as_ptr(),
1255 kernel.unwrap_or(VipsKernel::VIPS_KERNEL_LANCZOS3),
1256 c"centre".as_ptr(),
1257 centre.unwrap_or(false) as i32,
1258 null() as *const c_char,
1259 )
1260 };
1261 result_with_ret(out_ptr, ret)
1262 }
1263
1264 pub fn crop(&self, left: i32, top: i32, width: i32, height: i32) -> Result<VipsImage<'a>> {
1270 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1271 let ret = unsafe {
1273 vips_sys::vips_crop(
1274 self.c.as_ptr(),
1275 &mut out_ptr,
1276 left,
1277 top,
1278 width,
1279 height,
1280 null() as *const c_char,
1281 )
1282 };
1283 result_with_ret(out_ptr, ret)
1284 }
1285
1286 #[inline]
1288 pub fn extract_area(
1289 &self,
1290 left: i32,
1291 top: i32,
1292 width: i32,
1293 height: i32,
1294 ) -> Result<VipsImage<'a>> {
1295 self.crop(left, top, width, height)
1296 }
1297
1298 pub fn embed(
1300 &self,
1301 x: i32,
1302 y: i32,
1303 width: i32,
1304 height: i32,
1305 extend: Option<VipsExtend>,
1306 ) -> Result<VipsImage<'a>> {
1307 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1308 let ret = unsafe {
1310 vips_sys::vips_embed(
1311 self.c.as_ptr(),
1312 &mut out_ptr,
1313 x,
1314 y,
1315 width,
1316 height,
1317 c"extend".as_ptr(),
1318 extend.unwrap_or(VipsExtend::VIPS_EXTEND_BLACK),
1319 null() as *const c_char,
1320 )
1321 };
1322 result_with_ret(out_ptr, ret)
1323 }
1324
1325 pub fn gravity(
1327 &self,
1328 direction: VipsCompassDirection,
1329 width: i32,
1330 height: i32,
1331 extend: Option<VipsExtend>,
1332 ) -> Result<VipsImage<'a>> {
1333 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1334 let ret = unsafe {
1336 vips_sys::vips_gravity(
1337 self.c.as_ptr(),
1338 &mut out_ptr,
1339 direction,
1340 width,
1341 height,
1342 c"extend".as_ptr(),
1343 extend.unwrap_or(VipsExtend::VIPS_EXTEND_BLACK),
1344 null() as *const c_char,
1345 )
1346 };
1347 result_with_ret(out_ptr, ret)
1348 }
1349
1350 pub fn insert(&self, sub: &VipsImage<'a>, x: i32, y: i32) -> Result<VipsImage<'a>> {
1352 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1353 let ret = unsafe {
1355 vips_sys::vips_insert(
1356 self.c.as_ptr(),
1357 sub.as_ptr(),
1358 &mut out_ptr,
1359 x,
1360 y,
1361 null() as *const c_char,
1362 )
1363 };
1364 result_with_ret(out_ptr, ret)
1365 }
1366
1367 pub fn flip(&self, direction: VipsDirection) -> Result<VipsImage<'a>> {
1369 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1370 let ret = unsafe {
1372 vips_sys::vips_flip(
1373 self.c.as_ptr(),
1374 &mut out_ptr,
1375 direction,
1376 null() as *const c_char,
1377 )
1378 };
1379 result_with_ret(out_ptr, ret)
1380 }
1381
1382 #[inline]
1384 pub fn fliphor(&self) -> Result<VipsImage<'a>> {
1385 self.flip(VipsDirection::VIPS_DIRECTION_HORIZONTAL)
1386 }
1387
1388 #[inline]
1390 pub fn flipver(&self) -> Result<VipsImage<'a>> {
1391 self.flip(VipsDirection::VIPS_DIRECTION_VERTICAL)
1392 }
1393
1394 pub fn rot(&self, angle: vips_sys::VipsAngle) -> Result<VipsImage<'a>> {
1396 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1397 let ret = unsafe {
1399 vips_sys::vips_rot(
1400 self.c.as_ptr(),
1401 &mut out_ptr,
1402 angle,
1403 null() as *const c_char,
1404 )
1405 };
1406 result_with_ret(out_ptr, ret)
1407 }
1408
1409 #[inline]
1411 pub fn rot90(&self) -> Result<VipsImage<'a>> {
1412 self.rot(vips_sys::VipsAngle::VIPS_ANGLE_D90)
1413 }
1414
1415 #[inline]
1417 pub fn rot180(&self) -> Result<VipsImage<'a>> {
1418 self.rot(vips_sys::VipsAngle::VIPS_ANGLE_D180)
1419 }
1420
1421 #[inline]
1423 pub fn rot270(&self) -> Result<VipsImage<'a>> {
1424 self.rot(vips_sys::VipsAngle::VIPS_ANGLE_D270)
1425 }
1426
1427 pub fn rotate(&self, angle: f64) -> Result<VipsImage<'a>> {
1429 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1430 let ret = unsafe {
1432 vips_sys::vips_rotate(
1433 self.c.as_ptr(),
1434 &mut out_ptr,
1435 angle,
1436 null() as *const c_char,
1437 )
1438 };
1439 result_with_ret(out_ptr, ret)
1440 }
1441
1442 pub fn autorot(&self) -> Result<VipsImage<'a>> {
1444 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1445 let ret = unsafe {
1447 vips_sys::vips_autorot(self.c.as_ptr(), &mut out_ptr, null() as *const c_char)
1448 };
1449 result_with_ret(out_ptr, ret)
1450 }
1451
1452 pub fn zoom(&self, xfac: i32, yfac: i32) -> Result<VipsImage<'a>> {
1454 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1455 let ret = unsafe {
1457 vips_sys::vips_zoom(
1458 self.c.as_ptr(),
1459 &mut out_ptr,
1460 xfac,
1461 yfac,
1462 null() as *const c_char,
1463 )
1464 };
1465 result_with_ret(out_ptr, ret)
1466 }
1467
1468 pub fn extract_band(&self, band: i32) -> Result<VipsImage<'a>> {
1470 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1471 let ret = unsafe {
1473 vips_sys::vips_extract_band(
1474 self.c.as_ptr(),
1475 &mut out_ptr,
1476 band,
1477 null() as *const c_char,
1478 )
1479 };
1480 result_with_ret(out_ptr, ret)
1481 }
1482
1483 pub fn bandjoin2(&self, other: &VipsImage<'a>) -> Result<VipsImage<'a>> {
1485 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1486 let ret = unsafe {
1488 vips_sys::vips_bandjoin2(
1489 self.c.as_ptr(),
1490 other.as_ptr(),
1491 &mut out_ptr,
1492 null() as *const c_char,
1493 )
1494 };
1495 result_with_ret(out_ptr, ret)
1496 }
1497
1498 pub fn bandjoin_const(&self, constants: &[f64]) -> Result<VipsImage<'a>> {
1500 if constants.is_empty() {
1501 return self.copy();
1502 }
1503 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1504 let ret = unsafe {
1506 vips_sys::vips_bandjoin_const(
1507 self.c.as_ptr(),
1508 &mut out_ptr,
1509 constants.as_ptr() as *mut f64,
1510 constants.len() as i32,
1511 null() as *const c_char,
1512 )
1513 };
1514 result_with_ret(out_ptr, ret)
1515 }
1516
1517 pub fn copy_memory(&self) -> Result<VipsImage<'a>> {
1520 let ptr = unsafe { vips_sys::vips_image_copy_memory(self.c.as_ptr()) };
1522 result(ptr)
1523 }
1524
1525 pub fn copy(&self) -> Result<VipsImage<'a>> {
1527 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1528 let ret =
1530 unsafe { vips_sys::vips_copy(self.c.as_ptr(), &mut out_ptr, null() as *const c_char) };
1531 result_with_ret(out_ptr, ret)
1532 }
1533
1534 pub fn add(&self, other: &VipsImage<'a>) -> Result<VipsImage<'a>> {
1540 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1541 let ret = unsafe {
1543 vips_sys::vips_add(
1544 self.c.as_ptr(),
1545 other.as_ptr(),
1546 &mut out_ptr,
1547 null() as *const c_char,
1548 )
1549 };
1550 result_with_ret(out_ptr, ret)
1551 }
1552
1553 pub fn subtract(&self, other: &VipsImage<'a>) -> Result<VipsImage<'a>> {
1555 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1556 let ret = unsafe {
1558 vips_sys::vips_subtract(
1559 self.c.as_ptr(),
1560 other.as_ptr(),
1561 &mut out_ptr,
1562 null() as *const c_char,
1563 )
1564 };
1565 result_with_ret(out_ptr, ret)
1566 }
1567
1568 pub fn multiply(&self, other: &VipsImage<'a>) -> Result<VipsImage<'a>> {
1570 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1571 let ret = unsafe {
1573 vips_sys::vips_multiply(
1574 self.c.as_ptr(),
1575 other.as_ptr(),
1576 &mut out_ptr,
1577 null() as *const c_char,
1578 )
1579 };
1580 result_with_ret(out_ptr, ret)
1581 }
1582
1583 pub fn divide(&self, other: &VipsImage<'a>) -> Result<VipsImage<'a>> {
1585 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1586 let ret = unsafe {
1588 vips_sys::vips_divide(
1589 self.c.as_ptr(),
1590 other.as_ptr(),
1591 &mut out_ptr,
1592 null() as *const c_char,
1593 )
1594 };
1595 result_with_ret(out_ptr, ret)
1596 }
1597
1598 pub fn linear1(&self, a: f64, b: f64) -> Result<VipsImage<'a>> {
1600 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1601 let ret = unsafe {
1603 vips_sys::vips_linear1(self.c.as_ptr(), &mut out_ptr, a, b, null() as *const c_char)
1604 };
1605 result_with_ret(out_ptr, ret)
1606 }
1607
1608 pub fn linear(&self, a: &[f64], b: &[f64]) -> Result<VipsImage<'a>> {
1610 if a.is_empty() || a.len() != b.len() || a.len() > i32::MAX as usize {
1611 return Err(Error::Other(
1612 "linear requires equal nonempty a/b arrays with an i32 length".into(),
1613 ));
1614 }
1615 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1616 let ret = unsafe {
1618 vips_sys::vips_linear(
1619 self.c.as_ptr(),
1620 &mut out_ptr,
1621 a.as_ptr(),
1622 b.as_ptr(),
1623 a.len() as i32,
1624 null() as *const c_char,
1625 )
1626 };
1627 result_with_ret(out_ptr, ret)
1628 }
1629
1630 pub fn invert(&self) -> Result<VipsImage<'a>> {
1632 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1633 let ret = unsafe {
1635 vips_sys::vips_invert(self.c.as_ptr(), &mut out_ptr, null() as *const c_char)
1636 };
1637 result_with_ret(out_ptr, ret)
1638 }
1639
1640 pub fn cast(&self, format: VipsBandFormat) -> Result<VipsImage<'a>> {
1642 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1643 let ret = unsafe {
1645 vips_sys::vips_cast(
1646 self.c.as_ptr(),
1647 &mut out_ptr,
1648 format,
1649 null() as *const c_char,
1650 )
1651 };
1652 result_with_ret(out_ptr, ret)
1653 }
1654
1655 pub fn colourspace(
1657 &self,
1658 interpretation: vips_sys::VipsInterpretation,
1659 ) -> Result<VipsImage<'a>> {
1660 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1661 let ret = unsafe {
1663 vips_sys::vips_colourspace(
1664 self.c.as_ptr(),
1665 &mut out_ptr,
1666 interpretation,
1667 null() as *const c_char,
1668 )
1669 };
1670 result_with_ret(out_ptr, ret)
1671 }
1672
1673 pub fn gaussblur(&self, sigma: f64) -> Result<VipsImage<'a>> {
1675 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1676 let ret = unsafe {
1678 vips_sys::vips_gaussblur(
1679 self.c.as_ptr(),
1680 &mut out_ptr,
1681 sigma,
1682 null() as *const c_char,
1683 )
1684 };
1685 result_with_ret(out_ptr, ret)
1686 }
1687
1688 pub fn sharpen(&self, sigma: f64) -> Result<VipsImage<'a>> {
1690 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1691 let ret = unsafe {
1693 vips_sys::vips_sharpen(
1694 self.c.as_ptr(),
1695 &mut out_ptr,
1696 c"sigma".as_ptr(),
1697 sigma,
1698 null() as *const c_char,
1699 )
1700 };
1701 result_with_ret(out_ptr, ret)
1702 }
1703
1704 pub fn avg(&self) -> Result<f64> {
1710 let mut out: f64 = 0.0;
1711 let ret = unsafe { vips_sys::vips_avg(self.c.as_ptr(), &mut out, null() as *const c_char) };
1713 ffi::ret_to_result(ret)?;
1714 Ok(out)
1715 }
1716
1717 pub fn min_value(&self) -> Result<f64> {
1719 let mut out: f64 = 0.0;
1720 let ret = unsafe { vips_sys::vips_min(self.c.as_ptr(), &mut out, null() as *const c_char) };
1722 ffi::ret_to_result(ret)?;
1723 Ok(out)
1724 }
1725
1726 pub fn max_value(&self) -> Result<f64> {
1728 let mut out: f64 = 0.0;
1729 let ret = unsafe { vips_sys::vips_max(self.c.as_ptr(), &mut out, null() as *const c_char) };
1731 ffi::ret_to_result(ret)?;
1732 Ok(out)
1733 }
1734
1735 pub fn getpoint(&self, x: i32, y: i32) -> Result<Vec<f64>> {
1737 let mut vector: *mut f64 = null_mut();
1738 let mut n: c_int = 0;
1739 let ret = unsafe {
1741 vips_sys::vips_getpoint(
1742 self.c.as_ptr(),
1743 &mut vector,
1744 &mut n,
1745 x,
1746 y,
1747 null() as *const c_char,
1748 )
1749 };
1750 ffi::ret_to_result(ret)?;
1751 if vector.is_null() || n <= 0 {
1752 return Ok(Vec::new());
1753 }
1754 let values = unsafe {
1756 let slice = std::slice::from_raw_parts(vector as *const f64, n as usize);
1757 let owned = slice.to_vec();
1758 vips_sys::g_free(vector.cast());
1759 owned
1760 };
1761 Ok(values)
1762 }
1763
1764 pub fn deviate(&self) -> Result<f64> {
1766 let mut out: f64 = 0.0;
1767 let ret =
1769 unsafe { vips_sys::vips_deviate(self.c.as_ptr(), &mut out, null() as *const c_char) };
1770 ffi::ret_to_result(ret)?;
1771 Ok(out)
1772 }
1773
1774 pub fn percent(&self, percent: f64) -> Result<i32> {
1776 let mut threshold: c_int = 0;
1777 let ret = unsafe {
1779 vips_sys::vips_percent(
1780 self.c.as_ptr(),
1781 percent,
1782 &mut threshold,
1783 null() as *const c_char,
1784 )
1785 };
1786 ffi::ret_to_result(ret)?;
1787 Ok(threshold)
1788 }
1789
1790 pub fn find_trim(
1792 &self,
1793 threshold: Option<f64>,
1794 background: Option<&[f64]>,
1795 ) -> Result<(i32, i32, i32, i32)> {
1796 let mut left = 0;
1797 let mut top = 0;
1798 let mut width = 0;
1799 let mut height = 0;
1800 let ret = unsafe {
1803 match (threshold, background) {
1804 (Some(t), Some(bg)) => vips_sys::vips_find_trim(
1805 self.c.as_ptr(),
1806 &mut left,
1807 &mut top,
1808 &mut width,
1809 &mut height,
1810 c"threshold".as_ptr(),
1811 t,
1812 c"background".as_ptr(),
1813 bg.as_ptr() as *mut f64,
1814 bg.len() as i32,
1815 null() as *const c_char,
1816 ),
1817 (Some(t), None) => vips_sys::vips_find_trim(
1818 self.c.as_ptr(),
1819 &mut left,
1820 &mut top,
1821 &mut width,
1822 &mut height,
1823 c"threshold".as_ptr(),
1824 t,
1825 null() as *const c_char,
1826 ),
1827 (None, Some(bg)) => vips_sys::vips_find_trim(
1828 self.c.as_ptr(),
1829 &mut left,
1830 &mut top,
1831 &mut width,
1832 &mut height,
1833 c"background".as_ptr(),
1834 bg.as_ptr() as *mut f64,
1835 bg.len() as i32,
1836 null() as *const c_char,
1837 ),
1838 (None, None) => vips_sys::vips_find_trim(
1839 self.c.as_ptr(),
1840 &mut left,
1841 &mut top,
1842 &mut width,
1843 &mut height,
1844 null() as *const c_char,
1845 ),
1846 }
1847 };
1848 ffi::ret_to_result(ret)?;
1849 Ok((left, top, width, height))
1850 }
1851
1852 pub fn math(&self, op: vips_sys::VipsOperationMath) -> Result<VipsImage<'a>> {
1858 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1859 let ret = unsafe {
1861 vips_sys::vips_math(self.c.as_ptr(), &mut out_ptr, op, null() as *const c_char)
1862 };
1863 result_with_ret(out_ptr, ret)
1864 }
1865
1866 #[inline]
1868 pub fn sin(&self) -> Result<VipsImage<'a>> {
1869 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1870 let ret =
1872 unsafe { vips_sys::vips_sin(self.c.as_ptr(), &mut out_ptr, null() as *const c_char) };
1873 result_with_ret(out_ptr, ret)
1874 }
1875
1876 #[inline]
1878 pub fn cos(&self) -> Result<VipsImage<'a>> {
1879 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1880 let ret =
1882 unsafe { vips_sys::vips_cos(self.c.as_ptr(), &mut out_ptr, null() as *const c_char) };
1883 result_with_ret(out_ptr, ret)
1884 }
1885
1886 #[inline]
1888 pub fn tan(&self) -> Result<VipsImage<'a>> {
1889 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1890 let ret =
1892 unsafe { vips_sys::vips_tan(self.c.as_ptr(), &mut out_ptr, null() as *const c_char) };
1893 result_with_ret(out_ptr, ret)
1894 }
1895
1896 #[inline]
1898 pub fn ln(&self) -> Result<VipsImage<'a>> {
1899 self.math(vips_sys::VipsOperationMath::VIPS_OPERATION_MATH_LOG)
1900 }
1901
1902 #[inline]
1904 pub fn log10(&self) -> Result<VipsImage<'a>> {
1905 self.math(vips_sys::VipsOperationMath::VIPS_OPERATION_MATH_LOG10)
1906 }
1907
1908 #[inline]
1910 pub fn exp(&self) -> Result<VipsImage<'a>> {
1911 self.math(vips_sys::VipsOperationMath::VIPS_OPERATION_MATH_EXP)
1912 }
1913
1914 #[inline]
1916 pub fn exp10(&self) -> Result<VipsImage<'a>> {
1917 self.math(vips_sys::VipsOperationMath::VIPS_OPERATION_MATH_EXP10)
1918 }
1919
1920 pub fn floor(&self) -> Result<VipsImage<'a>> {
1922 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1923 let ret =
1925 unsafe { vips_sys::vips_floor(self.c.as_ptr(), &mut out_ptr, null() as *const c_char) };
1926 result_with_ret(out_ptr, ret)
1927 }
1928
1929 pub fn ceil(&self) -> Result<VipsImage<'a>> {
1931 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1932 let ret =
1934 unsafe { vips_sys::vips_ceil(self.c.as_ptr(), &mut out_ptr, null() as *const c_char) };
1935 result_with_ret(out_ptr, ret)
1936 }
1937
1938 pub fn rint(&self) -> Result<VipsImage<'a>> {
1940 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1941 let ret =
1943 unsafe { vips_sys::vips_rint(self.c.as_ptr(), &mut out_ptr, null() as *const c_char) };
1944 result_with_ret(out_ptr, ret)
1945 }
1946
1947 pub fn abs(&self) -> Result<VipsImage<'a>> {
1949 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1950 let ret =
1952 unsafe { vips_sys::vips_abs(self.c.as_ptr(), &mut out_ptr, null() as *const c_char) };
1953 result_with_ret(out_ptr, ret)
1954 }
1955
1956 pub fn sign(&self) -> Result<VipsImage<'a>> {
1958 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1959 let ret =
1961 unsafe { vips_sys::vips_sign(self.c.as_ptr(), &mut out_ptr, null() as *const c_char) };
1962 result_with_ret(out_ptr, ret)
1963 }
1964
1965 pub fn clamp(&self) -> Result<VipsImage<'a>> {
1967 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1968 let ret =
1970 unsafe { vips_sys::vips_clamp(self.c.as_ptr(), &mut out_ptr, null() as *const c_char) };
1971 result_with_ret(out_ptr, ret)
1972 }
1973
1974 pub fn pow_const(&self, exp: f64) -> Result<VipsImage<'a>> {
1976 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1977 let ret = unsafe {
1979 vips_sys::vips_pow_const1(self.c.as_ptr(), &mut out_ptr, exp, null() as *const c_char)
1980 };
1981 result_with_ret(out_ptr, ret)
1982 }
1983
1984 pub fn relational_const(
1986 &self,
1987 op: vips_sys::VipsOperationRelational,
1988 c: f64,
1989 ) -> Result<VipsImage<'a>> {
1990 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
1991 let ret = unsafe {
1993 vips_sys::vips_relational_const1(
1994 self.c.as_ptr(),
1995 &mut out_ptr,
1996 op,
1997 c,
1998 null() as *const c_char,
1999 )
2000 };
2001 result_with_ret(out_ptr, ret)
2002 }
2003
2004 #[inline]
2006 pub fn less(&self, c: f64) -> Result<VipsImage<'a>> {
2007 self.relational_const(
2008 vips_sys::VipsOperationRelational::VIPS_OPERATION_RELATIONAL_LESS,
2009 c,
2010 )
2011 }
2012
2013 #[inline]
2015 pub fn lesseq(&self, c: f64) -> Result<VipsImage<'a>> {
2016 self.relational_const(
2017 vips_sys::VipsOperationRelational::VIPS_OPERATION_RELATIONAL_LESSEQ,
2018 c,
2019 )
2020 }
2021
2022 #[inline]
2024 pub fn more(&self, c: f64) -> Result<VipsImage<'a>> {
2025 self.relational_const(
2026 vips_sys::VipsOperationRelational::VIPS_OPERATION_RELATIONAL_MORE,
2027 c,
2028 )
2029 }
2030
2031 #[inline]
2033 pub fn moreeq(&self, c: f64) -> Result<VipsImage<'a>> {
2034 self.relational_const(
2035 vips_sys::VipsOperationRelational::VIPS_OPERATION_RELATIONAL_MOREEQ,
2036 c,
2037 )
2038 }
2039
2040 #[inline]
2042 pub fn equal_const(&self, c: f64) -> Result<VipsImage<'a>> {
2043 self.relational_const(
2044 vips_sys::VipsOperationRelational::VIPS_OPERATION_RELATIONAL_EQUAL,
2045 c,
2046 )
2047 }
2048
2049 #[inline]
2051 pub fn notequal_const(&self, c: f64) -> Result<VipsImage<'a>> {
2052 self.relational_const(
2053 vips_sys::VipsOperationRelational::VIPS_OPERATION_RELATIONAL_NOTEQ,
2054 c,
2055 )
2056 }
2057
2058 pub fn boolean_const(
2060 &self,
2061 op: vips_sys::VipsOperationBoolean,
2062 c: f64,
2063 ) -> Result<VipsImage<'a>> {
2064 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2065 let ret = unsafe {
2067 vips_sys::vips_boolean_const1(
2068 self.c.as_ptr(),
2069 &mut out_ptr,
2070 op,
2071 c,
2072 null() as *const c_char,
2073 )
2074 };
2075 result_with_ret(out_ptr, ret)
2076 }
2077
2078 #[inline]
2080 pub fn and_const(&self, c: f64) -> Result<VipsImage<'a>> {
2081 self.boolean_const(
2082 vips_sys::VipsOperationBoolean::VIPS_OPERATION_BOOLEAN_AND,
2083 c,
2084 )
2085 }
2086
2087 #[inline]
2089 pub fn or_const(&self, c: f64) -> Result<VipsImage<'a>> {
2090 self.boolean_const(vips_sys::VipsOperationBoolean::VIPS_OPERATION_BOOLEAN_OR, c)
2091 }
2092
2093 #[inline]
2095 pub fn eor_const(&self, c: f64) -> Result<VipsImage<'a>> {
2096 self.boolean_const(
2097 vips_sys::VipsOperationBoolean::VIPS_OPERATION_BOOLEAN_EOR,
2098 c,
2099 )
2100 }
2101
2102 pub fn lshift_const(&self, c: f64) -> Result<VipsImage<'a>> {
2104 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2105 let ret = unsafe {
2107 vips_sys::vips_lshift_const1(self.c.as_ptr(), &mut out_ptr, c, null() as *const c_char)
2108 };
2109 result_with_ret(out_ptr, ret)
2110 }
2111
2112 pub fn rshift_const(&self, c: f64) -> Result<VipsImage<'a>> {
2114 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2115 let ret = unsafe {
2117 vips_sys::vips_rshift_const1(self.c.as_ptr(), &mut out_ptr, c, null() as *const c_char)
2118 };
2119 result_with_ret(out_ptr, ret)
2120 }
2121
2122 pub fn bandbool(&self, op: vips_sys::VipsOperationBoolean) -> Result<VipsImage<'a>> {
2124 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2125 let ret = unsafe {
2127 vips_sys::vips_bandbool(self.c.as_ptr(), &mut out_ptr, op, null() as *const c_char)
2128 };
2129 result_with_ret(out_ptr, ret)
2130 }
2131
2132 #[inline]
2134 pub fn bandand(&self) -> Result<VipsImage<'a>> {
2135 self.bandbool(vips_sys::VipsOperationBoolean::VIPS_OPERATION_BOOLEAN_AND)
2136 }
2137
2138 #[inline]
2140 pub fn bandor(&self) -> Result<VipsImage<'a>> {
2141 self.bandbool(vips_sys::VipsOperationBoolean::VIPS_OPERATION_BOOLEAN_OR)
2142 }
2143
2144 #[inline]
2146 pub fn bando(&self) -> Result<VipsImage<'a>> {
2147 self.bandbool(vips_sys::VipsOperationBoolean::VIPS_OPERATION_BOOLEAN_EOR)
2148 }
2149
2150 pub fn bandmean(&self) -> Result<VipsImage<'a>> {
2152 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2153 let ret = unsafe {
2155 vips_sys::vips_bandmean(self.c.as_ptr(), &mut out_ptr, null() as *const c_char)
2156 };
2157 result_with_ret(out_ptr, ret)
2158 }
2159
2160 pub fn bandsplit(&self) -> Result<Vec<VipsImage<'a>>> {
2162 let n = self.bands() as i32;
2163 let mut out = Vec::with_capacity(n as usize);
2164 for band in 0..n {
2165 out.push(self.extract_band(band)?);
2166 }
2167 Ok(out)
2168 }
2169
2170 pub fn conv(&self, mask: &VipsImage<'a>) -> Result<VipsImage<'a>> {
2176 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2177 let ret = unsafe {
2179 vips_sys::vips_conv(
2180 self.c.as_ptr(),
2181 &mut out_ptr,
2182 mask.as_ptr(),
2183 null() as *const c_char,
2184 )
2185 };
2186 result_with_ret(out_ptr, ret)
2187 }
2188
2189 pub fn morph(
2191 &self,
2192 mask: &VipsImage<'a>,
2193 op: vips_sys::VipsOperationMorphology,
2194 ) -> Result<VipsImage<'a>> {
2195 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2196 let ret = unsafe {
2198 vips_sys::vips_morph(
2199 self.c.as_ptr(),
2200 &mut out_ptr,
2201 mask.as_ptr(),
2202 op,
2203 null() as *const c_char,
2204 )
2205 };
2206 result_with_ret(out_ptr, ret)
2207 }
2208
2209 #[inline]
2211 pub fn erode(&self, mask: &VipsImage<'a>) -> Result<VipsImage<'a>> {
2212 self.morph(
2213 mask,
2214 vips_sys::VipsOperationMorphology::VIPS_OPERATION_MORPHOLOGY_ERODE,
2215 )
2216 }
2217
2218 #[inline]
2220 pub fn dilate(&self, mask: &VipsImage<'a>) -> Result<VipsImage<'a>> {
2221 self.morph(
2222 mask,
2223 vips_sys::VipsOperationMorphology::VIPS_OPERATION_MORPHOLOGY_DILATE,
2224 )
2225 }
2226
2227 pub fn rank(&self, width: i32, height: i32, index: i32) -> Result<VipsImage<'a>> {
2229 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2230 let ret = unsafe {
2232 vips_sys::vips_rank(
2233 self.c.as_ptr(),
2234 &mut out_ptr,
2235 width,
2236 height,
2237 index,
2238 null() as *const c_char,
2239 )
2240 };
2241 result_with_ret(out_ptr, ret)
2242 }
2243
2244 #[inline]
2246 pub fn median(&self, size: i32) -> Result<VipsImage<'a>> {
2247 let area = size.checked_mul(size).filter(|_| size > 0).ok_or_else(|| {
2248 Error::Other("median size must be positive and its square must fit i32".into())
2249 })?;
2250 let index = area / 2;
2251 self.rank(size, size, index)
2252 }
2253
2254 pub fn sobel(&self) -> Result<VipsImage<'a>> {
2256 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2257 let ret =
2259 unsafe { vips_sys::vips_sobel(self.c.as_ptr(), &mut out_ptr, null() as *const c_char) };
2260 result_with_ret(out_ptr, ret)
2261 }
2262
2263 pub fn canny(&self, sigma: Option<f64>) -> Result<VipsImage<'a>> {
2265 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2266 let ret = unsafe {
2268 match sigma {
2269 Some(s) => vips_sys::vips_canny(
2270 self.c.as_ptr(),
2271 &mut out_ptr,
2272 c"sigma".as_ptr(),
2273 s,
2274 null() as *const c_char,
2275 ),
2276 None => {
2277 vips_sys::vips_canny(self.c.as_ptr(), &mut out_ptr, null() as *const c_char)
2278 }
2279 }
2280 };
2281 result_with_ret(out_ptr, ret)
2282 }
2283
2284 pub fn ifthenelse(&self, then: &VipsImage<'a>, els: &VipsImage<'a>) -> Result<VipsImage<'a>> {
2290 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2291 let ret = unsafe {
2293 vips_sys::vips_ifthenelse(
2294 self.c.as_ptr(),
2295 then.as_ptr(),
2296 els.as_ptr(),
2297 &mut out_ptr,
2298 null() as *const c_char,
2299 )
2300 };
2301 result_with_ret(out_ptr, ret)
2302 }
2303
2304 pub fn smartcrop(
2306 &self,
2307 width: i32,
2308 height: i32,
2309 interesting: Option<VipsInteresting>,
2310 ) -> Result<VipsImage<'a>> {
2311 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2312 let ret = unsafe {
2314 match interesting {
2315 Some(i) => vips_sys::vips_smartcrop(
2316 self.c.as_ptr(),
2317 &mut out_ptr,
2318 width,
2319 height,
2320 c"interesting".as_ptr(),
2321 i,
2322 null() as *const c_char,
2323 ),
2324 None => vips_sys::vips_smartcrop(
2325 self.c.as_ptr(),
2326 &mut out_ptr,
2327 width,
2328 height,
2329 null() as *const c_char,
2330 ),
2331 }
2332 };
2333 result_with_ret(out_ptr, ret)
2334 }
2335
2336 pub fn falsecolour(&self) -> Result<VipsImage<'a>> {
2338 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2339 let ret = unsafe {
2341 vips_sys::vips_falsecolour(self.c.as_ptr(), &mut out_ptr, null() as *const c_char)
2342 };
2343 result_with_ret(out_ptr, ret)
2344 }
2345
2346 pub fn premultiply(&self, max_alpha: Option<f64>) -> Result<VipsImage<'a>> {
2348 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2349 let ret = unsafe {
2351 match max_alpha {
2352 Some(m) => vips_sys::vips_premultiply(
2353 self.c.as_ptr(),
2354 &mut out_ptr,
2355 c"max-alpha".as_ptr(),
2356 m,
2357 null() as *const c_char,
2358 ),
2359 None => vips_sys::vips_premultiply(
2360 self.c.as_ptr(),
2361 &mut out_ptr,
2362 null() as *const c_char,
2363 ),
2364 }
2365 };
2366 result_with_ret(out_ptr, ret)
2367 }
2368
2369 pub fn unpremultiply(&self, max_alpha: Option<f64>) -> Result<VipsImage<'a>> {
2371 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2372 let ret = unsafe {
2374 match max_alpha {
2375 Some(m) => vips_sys::vips_unpremultiply(
2376 self.c.as_ptr(),
2377 &mut out_ptr,
2378 c"max-alpha".as_ptr(),
2379 m,
2380 null() as *const c_char,
2381 ),
2382 None => vips_sys::vips_unpremultiply(
2383 self.c.as_ptr(),
2384 &mut out_ptr,
2385 null() as *const c_char,
2386 ),
2387 }
2388 };
2389 result_with_ret(out_ptr, ret)
2390 }
2391
2392 pub fn sequential(&self) -> Result<VipsImage<'a>> {
2394 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2395 let ret = unsafe {
2397 vips_sys::vips_sequential(self.c.as_ptr(), &mut out_ptr, null() as *const c_char)
2398 };
2399 result_with_ret(out_ptr, ret)
2400 }
2401
2402 pub fn wrap(&self) -> Result<VipsImage<'a>> {
2404 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2405 let ret =
2407 unsafe { vips_sys::vips_wrap(self.c.as_ptr(), &mut out_ptr, null() as *const c_char) };
2408 result_with_ret(out_ptr, ret)
2409 }
2410
2411 pub fn replicate(&self, across: i32, down: i32) -> Result<VipsImage<'a>> {
2413 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2414 let ret = unsafe {
2416 vips_sys::vips_replicate(
2417 self.c.as_ptr(),
2418 &mut out_ptr,
2419 across,
2420 down,
2421 null() as *const c_char,
2422 )
2423 };
2424 result_with_ret(out_ptr, ret)
2425 }
2426
2427 pub fn grid(&self, tile_height: i32, across: i32, down: i32) -> Result<VipsImage<'a>> {
2429 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2430 let ret = unsafe {
2432 vips_sys::vips_grid(
2433 self.c.as_ptr(),
2434 &mut out_ptr,
2435 tile_height,
2436 across,
2437 down,
2438 null() as *const c_char,
2439 )
2440 };
2441 result_with_ret(out_ptr, ret)
2442 }
2443
2444 pub fn copy_file(&self) -> Result<VipsImage<'a>> {
2446 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2447 let ret = unsafe {
2449 vips_sys::vips_copy_file(self.c.as_ptr(), &mut out_ptr, null() as *const c_char)
2450 };
2451 result_with_ret(out_ptr, ret)
2452 }
2453
2454 pub fn gamma(&self, exponent: Option<f64>) -> Result<VipsImage<'a>> {
2460 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2461 let ret = unsafe {
2463 match exponent {
2464 Some(e) => vips_sys::vips_gamma(
2465 self.c.as_ptr(),
2466 &mut out_ptr,
2467 c"exponent".as_ptr(),
2468 e,
2469 null() as *const c_char,
2470 ),
2471 None => {
2472 vips_sys::vips_gamma(self.c.as_ptr(), &mut out_ptr, null() as *const c_char)
2473 }
2474 }
2475 };
2476 result_with_ret(out_ptr, ret)
2477 }
2478
2479 pub fn hist_find(&self) -> Result<VipsImage<'a>> {
2481 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2482 let ret = unsafe {
2484 vips_sys::vips_hist_find(self.c.as_ptr(), &mut out_ptr, null() as *const c_char)
2485 };
2486 result_with_ret(out_ptr, ret)
2487 }
2488
2489 pub fn hist_local(&self, width: i32, height: i32) -> Result<VipsImage<'a>> {
2491 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2492 let ret = unsafe {
2494 vips_sys::vips_hist_local(
2495 self.c.as_ptr(),
2496 &mut out_ptr,
2497 width,
2498 height,
2499 null() as *const c_char,
2500 )
2501 };
2502 result_with_ret(out_ptr, ret)
2503 }
2504
2505 pub fn hist_equal(&self) -> Result<VipsImage<'a>> {
2507 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2508 let ret = unsafe {
2510 vips_sys::vips_hist_equal(self.c.as_ptr(), &mut out_ptr, null() as *const c_char)
2511 };
2512 result_with_ret(out_ptr, ret)
2513 }
2514
2515 pub fn hist_entropy(&self) -> Result<f64> {
2517 let mut out: f64 = 0.0;
2518 let ret = unsafe {
2520 vips_sys::vips_hist_entropy(self.c.as_ptr(), &mut out, null() as *const c_char)
2521 };
2522 ffi::ret_to_result(ret)?;
2523 Ok(out)
2524 }
2525
2526 pub fn maplut(&self, lut: &VipsImage<'a>) -> Result<VipsImage<'a>> {
2528 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2529 let ret = unsafe {
2531 vips_sys::vips_maplut(
2532 self.c.as_ptr(),
2533 &mut out_ptr,
2534 lut.as_ptr(),
2535 null() as *const c_char,
2536 )
2537 };
2538 result_with_ret(out_ptr, ret)
2539 }
2540
2541 pub fn bandfold(&self) -> Result<VipsImage<'a>> {
2543 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2544 let ret = unsafe {
2546 vips_sys::vips_bandfold(self.c.as_ptr(), &mut out_ptr, null() as *const c_char)
2547 };
2548 result_with_ret(out_ptr, ret)
2549 }
2550
2551 pub fn bandunfold(&self) -> Result<VipsImage<'a>> {
2553 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2554 let ret = unsafe {
2556 vips_sys::vips_bandunfold(self.c.as_ptr(), &mut out_ptr, null() as *const c_char)
2557 };
2558 result_with_ret(out_ptr, ret)
2559 }
2560
2561 pub fn labelregions(&self) -> Result<VipsImage<'a>> {
2563 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2564 let ret = unsafe {
2566 vips_sys::vips_labelregions(self.c.as_ptr(), &mut out_ptr, null() as *const c_char)
2567 };
2568 result_with_ret(out_ptr, ret)
2569 }
2570
2571 pub fn write_to_file(&self, path: impl AsRef<Path>) -> Result<()> {
2577 let path = path_to_cstring(path.as_ref())?;
2578 let ret = unsafe {
2579 vips_sys::vips_image_write_to_file(
2580 self.c.as_ptr(),
2581 path.as_ptr(),
2582 null() as *const c_char,
2583 )
2584 };
2585 result_draw(ret)
2586 }
2587
2588 pub fn write_to_memory(&self) -> Result<Vec<u8>> {
2594 Ok(self.write_to_memory_owned()?.as_slice().to_vec())
2595 }
2596
2597 pub fn write_to_memory_owned(&self) -> Result<crate::VipsOwnedBuffer> {
2600 let mut size = 0;
2601 let ptr = unsafe { vips_sys::vips_image_write_to_memory(self.as_ptr(), &mut size) };
2603 if ptr.is_null() {
2604 return Err(Error::Vips(
2605 take_vips_error().unwrap_or_else(|| "could not export image pixels".into()),
2606 ));
2607 }
2608 unsafe { crate::VipsOwnedBuffer::from_raw(ptr, size) }
2610 }
2611
2612 pub fn write_to_buffer(&self, suffix: &str) -> Result<Vec<u8>> {
2614 Ok(self.write_to_buffer_owned(suffix)?.as_slice().to_vec())
2615 }
2616
2617 pub fn write_to_buffer_owned(&self, suffix: &str) -> Result<crate::VipsOwnedBuffer> {
2619 let suffix = CString::new(suffix)
2620 .map_err(|_| Error::Other("invalid suffix: contains NUL".into()))?;
2621 let mut buf: *mut c_void = null_mut();
2622 let mut size = 0;
2623 let ret = unsafe {
2625 vips_sys::vips_image_write_to_buffer(
2626 self.as_ptr(),
2627 suffix.as_ptr(),
2628 &mut buf,
2629 &mut size,
2630 null() as *const c_char,
2631 )
2632 };
2633 let buffer = unsafe { crate::VipsOwnedBuffer::from_raw(buf, size) }?;
2635 ffi::ret_to_result(ret)?;
2636 Ok(buffer)
2637 }
2638
2639 pub fn write_jpeg(&self, path: impl AsRef<Path>, q: Option<i32>) -> Result<()> {
2641 let path = path_to_cstring(path.as_ref())?;
2642 let ret = unsafe {
2643 match q {
2644 Some(q) => vips_sys::vips_jpegsave(
2645 self.c.as_ptr(),
2646 path.as_ptr(),
2647 c"Q".as_ptr(),
2648 q,
2649 null() as *const c_char,
2650 ),
2651 None => {
2652 vips_sys::vips_jpegsave(self.c.as_ptr(), path.as_ptr(), null() as *const c_char)
2653 }
2654 }
2655 };
2656 result_draw(ret)
2657 }
2658}
2659
2660fn result<'a>(ptr: *mut vips_sys::VipsImage) -> Result<VipsImage<'a>> {
2661 let owned = ffi::image_from_ptr(ptr)?;
2662 Ok(unsafe { VipsImage::from_raw(owned.into_ptr()) })
2664}
2665
2666fn result_with_ret<'a>(ptr: *mut vips_sys::VipsImage, ret: c_int) -> Result<VipsImage<'a>> {
2667 let owned = ffi::image_from_ret(ptr, ret)?;
2668 Ok(unsafe { VipsImage::from_raw(owned.into_ptr()) })
2670}
2671
2672fn result_draw(ret: c_int) -> Result<()> {
2673 ffi::ret_to_result(ret)
2674}
2675
2676pub fn find_load(path: impl AsRef<Path>) -> Option<String> {
2680 let path = path_to_cstring(path.as_ref()).ok()?;
2681 let ptr = unsafe { vips_sys::vips_foreign_find_load(path.as_ptr()) };
2683 if ptr.is_null() {
2684 return None;
2685 }
2686 let s = unsafe { std::ffi::CStr::from_ptr(ptr) };
2688 s.to_str().ok().map(str::to_owned)
2689}
2690
2691pub fn find_save(path: impl AsRef<Path>) -> Option<String> {
2693 let path = path_to_cstring(path.as_ref()).ok()?;
2694 let ptr = unsafe { vips_sys::vips_foreign_find_save(path.as_ptr()) };
2696 if ptr.is_null() {
2697 return None;
2698 }
2699 let s = unsafe { std::ffi::CStr::from_ptr(ptr) };
2701 s.to_str().ok().map(str::to_owned)
2702}
2703
2704pub fn black(width: u32, height: u32) -> Result<VipsImage<'static>> {
2706 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2707 let ret = unsafe {
2709 vips_sys::vips_black(
2710 &mut out_ptr,
2711 width as i32,
2712 height as i32,
2713 null() as *const c_char,
2714 )
2715 };
2716 result_with_ret(out_ptr, ret)
2717}
2718
2719pub fn xyz(width: u32, height: u32) -> Result<VipsImage<'static>> {
2721 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2722 let ret = unsafe {
2724 vips_sys::vips_xyz(
2725 &mut out_ptr,
2726 width as i32,
2727 height as i32,
2728 null() as *const c_char,
2729 )
2730 };
2731 result_with_ret(out_ptr, ret)
2732}
2733
2734pub fn grey(width: u32, height: u32) -> Result<VipsImage<'static>> {
2736 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2737 let ret = unsafe {
2739 vips_sys::vips_grey(
2740 &mut out_ptr,
2741 width as i32,
2742 height as i32,
2743 null() as *const c_char,
2744 )
2745 };
2746 result_with_ret(out_ptr, ret)
2747}
2748
2749pub fn sines(width: u32, height: u32) -> Result<VipsImage<'static>> {
2751 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2752 let ret = unsafe {
2754 vips_sys::vips_sines(
2755 &mut out_ptr,
2756 width as i32,
2757 height as i32,
2758 null() as *const c_char,
2759 )
2760 };
2761 result_with_ret(out_ptr, ret)
2762}
2763
2764pub fn zone(width: u32, height: u32) -> Result<VipsImage<'static>> {
2766 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2767 let ret = unsafe {
2769 vips_sys::vips_zone(
2770 &mut out_ptr,
2771 width as i32,
2772 height as i32,
2773 null() as *const c_char,
2774 )
2775 };
2776 result_with_ret(out_ptr, ret)
2777}
2778
2779pub fn perlin(width: u32, height: u32) -> Result<VipsImage<'static>> {
2781 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2782 let ret = unsafe {
2784 vips_sys::vips_perlin(
2785 &mut out_ptr,
2786 width as i32,
2787 height as i32,
2788 null() as *const c_char,
2789 )
2790 };
2791 result_with_ret(out_ptr, ret)
2792}
2793
2794pub fn gaussnoise(width: u32, height: u32) -> Result<VipsImage<'static>> {
2796 let mut out_ptr: *mut vips_sys::VipsImage = null_mut();
2797 let ret = unsafe {
2799 vips_sys::vips_gaussnoise(
2800 &mut out_ptr,
2801 width as i32,
2802 height as i32,
2803 null() as *const c_char,
2804 )
2805 };
2806 result_with_ret(out_ptr, ret)
2807}