1use crate::bindings;
3use crate::error::Error;
4use crate::ops::*;
5use crate::utils;
6use crate::Result;
7
8use num_traits::{FromPrimitive, ToPrimitive};
9use std::borrow::Cow;
10use std::convert::TryInto;
11use std::ffi::*;
12use std::ptr::null_mut;
13
14const NULL: *const c_void = null_mut();
15
16#[derive(Debug, Clone)]
17pub struct VipsImage {
18 pub(crate) ctx: *mut bindings::VipsImage,
19}
20
21#[derive(Debug, Clone)]
22pub struct VipsInterpolate {
23 pub(crate) ctx: *mut bindings::VipsInterpolate,
24}
25
26#[derive(Debug, Clone)]
27pub struct VipsBlob {
28 pub(crate) ctx: *mut bindings::VipsBlob,
29}
30
31#[derive(Debug, Clone)]
32pub struct VipsConnection {
33 pub(crate) ctx: *mut bindings::VipsConnection,
34}
35
36#[derive(Debug, Clone)]
37pub struct VipsSource {
38 pub(crate) ctx: *mut bindings::VipsSource,
39}
40
41#[derive(Debug, Clone)]
42pub struct VipsTarget {
43 pub(crate) ctx: *mut bindings::VipsTarget,
44}
45
46impl VipsImage {
49 pub fn new() -> VipsImage {
50 VipsImage {
51 ctx: unsafe { bindings::vips_image_new() },
52 }
53 }
54
55 pub fn new_memory() -> Result<VipsImage> {
56 unsafe {
57 let res = bindings::vips_image_new_memory();
58 vips_image_result(
59 res,
60 Error::InitializationError("Could not generate object"),
61 )
62 }
63 }
64
65 pub fn new_from_file(filename: &str) -> Result<VipsImage> {
66 unsafe {
67 let f = utils::new_c_string(filename)?;
68 let res = bindings::vips_image_new_from_file(
69 f.as_ptr(),
70 NULL,
71 );
72 vips_image_result(
73 res,
74 Error::InitializationError("Could not initialise VipsImage from file"),
75 )
76 }
77 }
78
79 pub fn new_from_file_rw(filename: &str) -> Result<VipsImage> {
80 unsafe {
81 let f = utils::new_c_string(filename)?;
82 let res = bindings::vips_image_new_from_file_RW(f.as_ptr());
83 vips_image_result(
84 res,
85 Error::InitializationError("Could not initialise VipsImage from file"),
86 )
87 }
88 }
89
90 pub fn new_from_file_raw(
91 filename: &str,
92 x_size: i32,
93 y_size: i32,
94 bands: i32,
95 offset: u64,
96 ) -> Result<VipsImage> {
97 unsafe {
98 let f = utils::new_c_string(filename)?;
99 let res = bindings::vips_image_new_from_file_raw(
100 f.as_ptr(),
101 x_size,
102 y_size,
103 bands,
104 offset,
105 );
106 vips_image_result(
107 res,
108 Error::InitializationError("Could not initialise VipsImage from file"),
109 )
110 }
111 }
112
113 pub fn new_from_file_access(filename: &str, access: Access, memory: bool) -> Result<VipsImage> {
114 unsafe {
115 let access_str = utils::new_c_string("access")?;
116 let memory_str = utils::new_c_string("memory")?;
117 let f = utils::new_c_string(filename)?;
118 let res = bindings::vips_image_new_from_file(
119 f.as_ptr(),
120 access_str.as_ptr(),
121 access as i32,
122 memory_str.as_ptr(),
123 if memory { 1 } else { 0 },
124 NULL,
125 );
126 vips_image_result(
127 res,
128 Error::InitializationError("Could not initialise VipsImage from file"),
129 )
130 }
131 }
132
133 pub fn new_from_buffer(buffer: &[u8], option_str: &str) -> Result<VipsImage> {
134 unsafe {
135 let options = utils::new_c_string(option_str)?;
136 let res = bindings::vips_image_new_from_buffer(
137 buffer.as_ptr() as *const c_void,
138 buffer.len() as u64,
139 options.as_ptr(),
140 NULL,
141 );
142 vips_image_result(
143 res,
144 Error::InitializationError("Could not initialise VipsImage from file"),
145 )
146 }
147 }
148
149 pub fn new_from_memory(
150 buffer: &[u8],
151 width: i32,
152 height: i32,
153 bands: i32,
154 format: BandFormat,
155 ) -> Result<VipsImage> {
156 unsafe {
157 if let Some(format) = format.to_i32() {
158 let res = bindings::vips_image_new_from_memory(
159 buffer.as_ptr() as *const c_void,
160 buffer.len() as u64,
161 width,
162 height,
163 bands,
164 format,
165 );
166 vips_image_result(
167 res,
168 Error::InitializationError("Could not initialise VipsImage from memory"),
169 )
170 } else {
171 Err(Error::InitializationError(
172 "Invalid BandFormat. Please file a bug report, as this should never happen.",
173 ))
174 }
175 }
176 }
177
178 pub fn image_new_matrix(width: i32, height: i32) -> Result<VipsImage> {
179 unsafe {
180 let res = bindings::vips_image_new_matrix(
181 width,
182 height,
183 );
184 vips_image_result(
185 res,
186 Error::InitializationError("Could not initialise VipsImage from file"),
187 )
188 }
189 }
190
191 pub fn image_new_matrix_from_array(
192 width: i32,
193 height: i32,
194 array: &[f64],
195 ) -> Result<VipsImage> {
196 unsafe {
197 let res = bindings::vips_image_new_matrix_from_array(
198 width,
199 height,
200 array.as_ptr(),
201 array.len() as i32,
202 );
203 vips_image_result(
204 res,
205 Error::InitializationError("Could not initialise VipsImage from file"),
206 )
207 }
208 }
209
210 pub fn new_from_image(image: &VipsImage, array: &[f64]) -> Result<VipsImage> {
211 unsafe {
212 let res = bindings::vips_image_new_from_image(
213 image.ctx,
214 array.as_ptr(),
215 array.len() as i32,
216 );
217 vips_image_result(
218 res,
219 Error::InitializationError("Could not initialise VipsImage from Object"),
220 )
221 }
222 }
223
224 pub fn new_from_image1(image: &VipsImage, c: f64) -> Result<VipsImage> {
225 unsafe {
226 let res = bindings::vips_image_new_from_image1(
227 image.ctx,
228 c,
229 );
230 vips_image_result(
231 res,
232 Error::InitializationError("Could not initialise VipsImage from Object"),
233 )
234 }
235 }
236
237 pub fn image_new_temp_file(format: &str) -> Result<VipsImage> {
238 unsafe {
239 let format_c_str = utils::new_c_string(format)?;
240 let res = bindings::vips_image_new_temp_file(format_c_str.as_ptr());
241 vips_image_result(
242 res,
243 Error::InitializationError("Could not initialise VipsImage from format"),
244 )
245 }
246 }
247
248 pub fn image_copy_memory(image: VipsImage) -> Result<VipsImage> {
249 unsafe {
250 let result = bindings::vips_image_copy_memory(image.ctx);
251 vips_image_result(
252 result,
253 Error::OperationError("Could not copy memory"),
254 )
255 }
256 }
257
258 pub fn image_wio_input(&mut self) -> Result<()> {
259 unsafe {
260 let result = bindings::vips_image_wio_input(self.ctx);
261 utils::result(
262 result,
263 (),
264 Error::OperationError("Error on vips image_wio_input"),
265 )
266 }
267 }
268
269 pub fn get_filename(&self) -> std::result::Result<&str, std::str::Utf8Error> {
270 unsafe {
271 let filename = bindings::vips_image_get_filename(self.ctx);
272 let res = CStr::from_ptr(filename);
273 res.to_str()
274 }
275 }
276
277 pub fn get_width(&self) -> i32 {
278 unsafe { bindings::vips_image_get_width(self.ctx) }
279 }
280
281 pub fn get_height(&self) -> i32 {
282 unsafe { bindings::vips_image_get_height(self.ctx) }
283 }
284
285 pub fn get_xoffset(&self) -> i32 {
286 unsafe { bindings::vips_image_get_xoffset(self.ctx) }
287 }
288
289 pub fn get_yoffset(&self) -> i32 {
290 unsafe { bindings::vips_image_get_yoffset(self.ctx) }
291 }
292
293 pub fn get_scale(&self) -> f64 {
294 unsafe { bindings::vips_image_get_scale(self.ctx) }
295 }
296
297 pub fn get_offset(&self) -> f64 {
298 unsafe { bindings::vips_image_get_offset(self.ctx) }
299 }
300
301 pub fn get_xres(&self) -> f64 {
302 unsafe { bindings::vips_image_get_xres(self.ctx) }
303 }
304
305 pub fn get_yres(&self) -> f64 {
306 unsafe { bindings::vips_image_get_yres(self.ctx) }
307 }
308
309 pub fn get_bands(&self) -> i32 {
310 unsafe { bindings::vips_image_get_bands(self.ctx) }
311 }
312
313 pub fn get_page_height(&self) -> i32 {
314 unsafe { bindings::vips_image_get_page_height(self.ctx) }
315 }
316
317 pub fn get_n_pages(&self) -> i32 {
318 unsafe { bindings::vips_image_get_n_pages(self.ctx) }
319 }
320
321 pub fn get_coding(&self) -> Result<Coding> {
322 unsafe {
323 let res = bindings::vips_image_get_format(self.ctx);
324 let format_enum = FromPrimitive::from_i32(res);
325 format_enum.ok_or_else(|| Error::IOError("Could get format from image"))
326 }
327 }
328
329 pub fn get_format(&self) -> Result<BandFormat> {
330 unsafe {
331 let res = bindings::vips_image_get_format(self.ctx);
332 let format_enum = FromPrimitive::from_i32(res);
333 format_enum.ok_or_else(|| Error::IOError("Could get format from image"))
334 }
335 }
336
337 pub fn guess_format(&self) -> Result<BandFormat> {
338 unsafe {
339 let res = bindings::vips_image_guess_format(self.ctx);
340 let format_enum = FromPrimitive::from_i32(res);
341 format_enum.ok_or_else(|| Error::IOError("Could get format from image"))
342 }
343 }
344
345 pub fn get_orientation(&self) -> i32 {
346 unsafe { bindings::vips_image_get_orientation(self.ctx) }
347 }
348
349 pub fn get_interpretation(&self) -> Result<Interpretation> {
350 unsafe {
351 let res = bindings::vips_image_get_interpretation(self.ctx);
352 let format_enum = FromPrimitive::from_i32(res);
353 format_enum.ok_or_else(|| Error::IOError("Could get format from image"))
354 }
355 }
356
357 pub fn guess_interpretation(&self) -> Result<Interpretation> {
358 unsafe {
359 let res = bindings::vips_image_guess_interpretation(self.ctx);
360 let format_enum = FromPrimitive::from_i32(res);
361 format_enum.ok_or_else(|| Error::IOError("Could get format from image"))
362 }
363 }
364
365 pub fn image_set_delete_on_close(&mut self, flag: bool) {
366 unsafe {
367 bindings::vips_image_set_delete_on_close(
368 self.ctx,
369 if flag { 1 } else { 0 },
370 );
371 }
372 }
373
374 pub fn image_invalidate_all(&self) {
375 unsafe {
376 bindings::vips_image_invalidate_all(self.ctx);
377 }
378 }
379
380 pub fn image_minimise_all(&self) {
381 unsafe {
382 bindings::vips_image_minimise_all(self.ctx);
383 }
384 }
385
386 pub fn image_iskilled(&self) -> bool {
387 unsafe { bindings::vips_image_iskilled(self.ctx) == 1 }
388 }
389
390 pub fn image_isMSBfirst(&self) -> bool {
391 unsafe { bindings::vips_image_isMSBfirst(self.ctx) == 1 }
392 }
393
394 pub fn image_isfile(&self) -> bool {
395 unsafe { bindings::vips_image_isfile(self.ctx) == 1 }
396 }
397
398 pub fn image_ispartial(&self) -> bool {
399 unsafe { bindings::vips_image_ispartial(self.ctx) == 1 }
400 }
401
402 pub fn image_hasalpha(&self) -> bool {
403 unsafe { bindings::vips_image_hasalpha(self.ctx) == 1 }
404 }
405
406 pub fn image_set_kill(&self, flag: bool) {
407 unsafe {
408 bindings::vips_image_set_kill(
409 self.ctx,
410 if flag { 1 } else { 0 },
411 );
412 }
413 }
414
415 pub fn image_set_progress(&self, flag: bool) {
416 unsafe {
417 bindings::vips_image_set_progress(
418 self.ctx,
419 if flag { 1 } else { 0 },
420 );
421 }
422 }
423
424 pub fn image_write(&self) -> Result<VipsImage> {
425 unsafe {
426 let out: *mut bindings::VipsImage = null_mut();
427 let res = bindings::vips_image_write(
428 self.ctx,
429 out,
430 );
431 utils::result(
432 res,
433 VipsImage {
434 ctx: out,
435 },
436 Error::IOError("Cannot write input to output"),
437 )
438 }
439 }
440
441 pub fn image_pio_input(&mut self) -> Result<()> {
442 unsafe {
443 let res = bindings::vips_image_pio_input(self.ctx);
444 utils::result(
445 res,
446 (),
447 Error::IOError("Cannot read image"),
448 )
449 }
450 }
451
452 pub fn image_pio_output(&mut self) -> Result<()> {
453 unsafe {
454 let res = bindings::vips_image_pio_output(self.ctx);
455 utils::result(
456 res,
457 (),
458 Error::IOError("Cannot write image"),
459 )
460 }
461 }
462
463 pub fn image_inplace(&self) -> Result<()> {
464 unsafe {
465 let res = bindings::vips_image_inplace(self.ctx);
466 utils::result(
467 res,
468 (),
469 Error::IOError("Cannot cannot be modified inplace"),
470 )
471 }
472 }
473
474 pub fn image_write_to_file(&self, filename: &str) -> Result<()> {
475 unsafe {
476 let file_c_str = utils::new_c_string(filename)?;
477 let res = bindings::vips_image_write_to_file(
478 self.ctx,
479 file_c_str.as_ptr(),
480 NULL,
481 );
482 utils::result(
483 res,
484 (),
485 Error::IOError("Cannot write to file"),
486 )
487 }
488 }
489
490 pub fn image_write_prepare(&self) -> Result<()> {
491 unsafe {
492 let res = bindings::vips_image_write_prepare(self.ctx);
493 utils::result(
494 res,
495 (),
496 Error::IOError("Cannot prepare file to write"),
497 )
498 }
499 }
500
501 pub fn image_write_to_buffer(&self, suffix: &str) -> Result<Vec<u8>> {
502 unsafe {
503 let mut buffer_buf_size: u64 = 0;
504 let mut buffer_out: *mut c_void = null_mut();
505 let suffix_c_str = utils::new_c_string(suffix)?;
506 let res = bindings::vips_image_write_to_buffer(
507 self.ctx,
508 suffix_c_str.as_ptr(),
509 &mut buffer_out,
510 &mut buffer_buf_size,
511 NULL,
512 );
513 utils::result(
514 res,
515 utils::new_byte_array(
516 buffer_out,
517 buffer_buf_size,
518 ),
519 Error::IOError("Cannot write content to buffer"),
520 )
521 }
522 }
523
524 pub fn image_write_to_memory(&self) -> Vec<u8> {
525 unsafe {
526 let mut buffer_buf_size: u64 = 0;
527 let buffer_out = bindings::vips_image_write_to_memory(
528 self.ctx,
529 &mut buffer_buf_size,
530 );
531 let buf = std::slice::from_raw_parts(
532 buffer_out as *mut u8,
533 buffer_buf_size as usize,
534 )
535 .to_vec();
536 bindings::g_free(buffer_out);
537 buf
538 }
539 }
540
541 pub fn image_decode_predict(
542 &self,
543 ) -> Result<(
544 i32,
545 BandFormat,
546 )> {
547 unsafe {
548 let mut out_bands = 0;
549 let mut out_format = 0;
550 let res = bindings::vips_image_decode_predict(
551 self.ctx,
552 &mut out_bands,
553 &mut out_format,
554 );
555 let format_enum = FromPrimitive::from_i32(out_format);
556 if format_enum.is_some() {
557 utils::result(
558 res,
559 (
560 out_bands,
561 format_enum.unwrap(),
562 ),
563 Error::IOError("Could not predict image format"),
564 )
565 } else {
566 Err(Error::IOError("Could not predict image format"))
567 }
568 }
569 }
570
571 pub fn image_decode(&self) -> Result<VipsImage> {
572 unsafe {
573 let mut out: *mut bindings::VipsImage = null_mut();
574 let res = bindings::vips_image_decode(
575 self.ctx,
576 &mut out,
577 );
578 utils::result(
579 res,
580 VipsImage {
581 ctx: out,
582 },
583 Error::IOError("Cannot decode image"),
584 )
585 }
586 }
587
588 pub fn image_encode(&self, coding: Coding) -> Result<VipsImage> {
589 unsafe {
590 let mut out: *mut bindings::VipsImage = null_mut();
591 let res = bindings::vips_image_encode(
592 self.ctx,
593 &mut out,
594 coding as i32,
595 );
596 utils::result(
597 res,
598 VipsImage {
599 ctx: out,
600 },
601 Error::IOError("Cannot encode image"),
602 )
603 }
604 }
605}
606
607impl VipsConnection {
608 pub fn connection_filename(&self) -> Option<String> {
609 unsafe {
610 let result = bindings::vips_connection_filename(self.ctx);
611 if result.is_null() {
612 None
613 } else {
614 let cstr = CStr::from_ptr(result);
615 match cstr.to_string_lossy() {
616 Cow::Borrowed(slice) => Some(slice.to_string()),
617 Cow::Owned(string) => Some(string),
618 }
619 }
620 }
621 }
622
623 pub fn connection_nick(&self) -> Option<String> {
624 unsafe {
625 let result = bindings::vips_connection_nick(self.ctx);
626 if result.is_null() {
627 None
628 } else {
629 let cstr = CStr::from_ptr(result);
630 match cstr.to_string_lossy() {
631 Cow::Borrowed(slice) => Some(slice.to_string()),
632 Cow::Owned(string) => Some(string),
633 }
634 }
635 }
636 }
637}
638
639impl VipsSource {
640 pub fn new_from_descriptor(descriptor: i32) -> Result<Self> {
641 unsafe {
642 let res = bindings::vips_source_new_from_descriptor(descriptor);
643 vips_source_result(
644 res,
645 Error::InitializationError("Could not initialise VipsSource from descriptor"),
646 )
647 }
648 }
649
650 pub fn new_from_file(filename: &str) -> Result<Self> {
651 unsafe {
652 let f = utils::new_c_string(filename)?;
653 let res = bindings::vips_source_new_from_file(f.as_ptr());
654 vips_source_result(
655 res,
656 Error::InitializationError("Could not initialise VipsSource from file"),
657 )
658 }
659 }
660
661 fn new_from_blob(blob: VipsBlob) -> Result<Self> {
664 unsafe {
665 let res = bindings::vips_source_new_from_blob(blob.ctx);
666 vips_source_result(
667 res,
668 Error::InitializationError("Could not initialise VipsSource from blob"),
669 )
670 }
671 }
672
673 pub fn new_from_memory(buffer: &[u8]) -> Result<Self> {
674 unsafe {
675 let res = bindings::vips_source_new_from_memory(
676 buffer.as_ptr() as *const c_void,
677 buffer.len() as u64,
678 );
679 vips_source_result(
680 res,
681 Error::InitializationError("Could not initialise VipsSource from memory"),
682 )
683 }
684 }
685
686 pub fn new_from_options(option_str: &str) -> Result<Self> {
687 unsafe {
688 let options = utils::new_c_string(option_str)?;
689 let res = bindings::vips_source_new_from_options(options.as_ptr());
690 vips_source_result(
691 res,
692 Error::InitializationError("Could not initialise VipsSource from options"),
693 )
694 }
695 }
696
697 pub fn minimise(&mut self) {
698 unsafe {
699 bindings::vips_source_minimise(self.ctx);
700 }
701 }
702
703 pub fn unminimise(&mut self) -> Result<()> {
704 unsafe {
705 let result = bindings::vips_source_unminimise(self.ctx);
706 utils::result(
707 result,
708 (),
709 Error::OperationError("Error on vips unminimise"),
710 )
711 }
712 }
713
714 pub fn decode(&mut self) -> Result<()> {
715 unsafe {
716 let result = bindings::vips_source_decode(self.ctx);
717 utils::result(
718 result,
719 (),
720 Error::OperationError("Error on vips decode"),
721 )
722 }
723 }
724
725 pub fn read(&mut self, length: u64) -> Result<Vec<u8>> {
726 unsafe {
727 let bytes: *mut c_void = null_mut();
728 let result = bindings::vips_source_read(
729 self.ctx,
730 bytes,
731 length,
732 );
733 if result != -1 {
734 let buffer = Vec::from_raw_parts(
735 bytes as *mut u8,
736 result as usize,
737 result as usize,
738 );
739 Ok(buffer)
740 } else {
741 Err(Error::OperationError("Error on vips read"))
742 }
743 }
744 }
745
746 pub fn is_mappable(&self) -> bool {
747 unsafe { bindings::vips_source_is_mappable(self.ctx) == 1 }
748 }
749
750 pub fn seek(&mut self, offset: i64, whence: i32) -> Result<i64> {
751 unsafe {
752 let result = bindings::vips_source_seek(
753 self.ctx,
754 offset,
755 whence,
756 );
757 if result == -1 {
758 Err(Error::OperationError("Error on vips seek"))
759 } else {
760 Ok(result)
761 }
762 }
763 }
764
765 pub fn rewind(&mut self) -> Result<()> {
766 unsafe {
767 let result = bindings::vips_source_rewind(self.ctx);
768 if result == -1 {
769 Err(Error::OperationError("Error on vips rewind"))
770 } else {
771 Ok(())
772 }
773 }
774 }
775
776 pub fn length(&self) -> Result<i64> {
777 unsafe {
778 let result = bindings::vips_source_length(self.ctx);
779 if result == -1 {
780 Err(Error::OperationError("Error on vips length"))
781 } else {
782 Ok(result)
783 }
784 }
785 }
786}
787
788impl<'a> VipsSource {
789 pub fn map(&'a self) -> Result<&'a [u8]> {
790 unsafe {
791 let length: *mut u64 = null_mut();
792 let result = bindings::vips_source_map(
793 self.ctx,
794 length,
795 );
796 if length.is_null() {
797 Err(Error::OperationError("Error on vips map"))
798 } else {
799 let size = (*length)
800 .try_into()
801 .map_err(|_| Error::OperationError("Can't get size of array"))?;
802 Ok(
803 std::slice::from_raw_parts(
804 result as *mut u8,
805 size,
806 ),
807 )
808 }
809 }
810 }
811
812 }
823
824impl VipsTarget {
825 pub fn new_to_descriptor(descriptor: i32) -> Result<Self> {
826 unsafe {
827 let res = bindings::vips_target_new_to_descriptor(descriptor);
828 vips_target_result(
829 res,
830 Error::InitializationError("Could not initialise VipsTarget from descriptor"),
831 )
832 }
833 }
834
835 pub fn new_to_file(filename: &str) -> Result<Self> {
836 unsafe {
837 let f = utils::new_c_string(filename)?;
838 let res = bindings::vips_target_new_to_file(f.as_ptr());
839 vips_target_result(
840 res,
841 Error::InitializationError("Could not initialise VipsTarget from file"),
842 )
843 }
844 }
845
846 pub fn new_to_memory() -> Result<Self> {
847 unsafe {
848 let res = bindings::vips_target_new_to_memory();
849 vips_target_result(
850 res,
851 Error::InitializationError("Could not initialise VipsTarget from memory"),
852 )
853 }
854 }
855
856 pub fn write(&mut self, buffer: &[u8]) -> Result<()> {
857 unsafe {
858 let res = bindings::vips_target_write(
859 self.ctx,
860 buffer.as_ptr() as *const c_void,
861 buffer.len() as u64,
862 );
863 if res == -1 {
864 Err(Error::OperationError("Could not write to buffer"))
865 } else {
866 Ok(())
867 }
868 }
869 }
870
871 pub fn finish(self) {
872 unsafe {
873 bindings::vips_target_finish(self.ctx);
874 }
875 }
876
877 pub fn putc(&mut self, ch: char) -> Result<()> {
878 unsafe {
879 let res = bindings::vips_target_putc(
880 self.ctx,
881 ch as i32,
882 );
883 if res == -1 {
884 Err(Error::OperationError("Could not write to buffer"))
885 } else {
886 Ok(())
887 }
888 }
889 }
890
891 pub fn writes(&mut self, text: &str) -> Result<()> {
892 unsafe {
893 let cstr = CString::new(text)
894 .map_err(|_| Error::OperationError("Cannot initialize C string"))?;
895 let res = bindings::vips_target_writes(
896 self.ctx,
897 cstr.as_ptr(),
898 );
899 if res == -1 {
900 Err(Error::OperationError("Could not write to buffer"))
901 } else {
902 Ok(())
903 }
904 }
905 }
906
907 pub fn write_amp(&mut self, text: &str) -> Result<()> {
908 unsafe {
909 let cstr = CString::new(text)
910 .map_err(|_| Error::OperationError("Cannot initialize C string"))?;
911 let res = bindings::vips_target_write_amp(
912 self.ctx,
913 cstr.as_ptr(),
914 );
915 if res == -1 {
916 Err(Error::OperationError("Could not write to buffer"))
917 } else {
918 Ok(())
919 }
920 }
921 }
922}
923
924unsafe fn vips_image_result(res: *mut bindings::VipsImage, err: Error) -> Result<VipsImage> {
925 if res.is_null() {
926 Err(err)
927 } else {
928 Ok(
929 VipsImage {
930 ctx: res,
931 },
932 )
933 }
934}
935
936unsafe fn vips_source_result(res: *mut bindings::VipsSource, err: Error) -> Result<VipsSource> {
937 if res.is_null() {
938 Err(err)
939 } else {
940 Ok(
941 VipsSource {
942 ctx: res,
943 },
944 )
945 }
946}
947
948unsafe fn vips_target_result(res: *mut bindings::VipsTarget, err: Error) -> Result<VipsTarget> {
949 if res.is_null() {
950 Err(err)
951 } else {
952 Ok(
953 VipsTarget {
954 ctx: res,
955 },
956 )
957 }
958}
959
960impl VipsInterpolate {
961 pub fn new() -> VipsInterpolate {
963 unsafe {
964 VipsInterpolate {
965 ctx: bindings::vips_interpolate_nearest_static(),
966 }
967 }
968 }
969
970 pub fn new_from_neasest_static() -> VipsInterpolate {
971 unsafe {
972 VipsInterpolate {
973 ctx: bindings::vips_interpolate_nearest_static(),
974 }
975 }
976 }
977
978 pub fn new_from_bilinear_static() -> VipsInterpolate {
979 unsafe {
980 VipsInterpolate {
981 ctx: bindings::vips_interpolate_bilinear_static(),
982 }
983 }
984 }
985
986 pub fn new_from_name(name: &str) -> Result<VipsInterpolate> {
987 unsafe {
988 let nickname = utils::new_c_string(name)?;
989 let res = bindings::vips_interpolate_new(nickname.as_ptr());
990 if res.is_null() {
991 Err(
992 Error::InitializationError(
993 "Cannot initialize interpolator with provided nickname",
994 ),
995 )
996 } else {
997 Ok(
998 VipsInterpolate {
999 ctx: res,
1000 },
1001 )
1002 }
1003 }
1004 }
1005
1006 pub fn get_window_size(&self) -> i32 {
1007 unsafe { bindings::vips_interpolate_get_window_size(self.ctx) }
1008 }
1009
1010 pub fn get_windows_offset(&self) -> i32 {
1011 unsafe { bindings::vips_interpolate_get_window_offset(self.ctx) }
1012 }
1013}
1014
1015impl Drop for VipsImage {
1016 fn drop(&mut self) {
1017 unsafe {
1018 if !self
1019 .ctx
1020 .is_null()
1021 {
1022 bindings::g_object_unref(self.ctx as *mut c_void);
1023 }
1024 }
1025 }
1026}
1027
1028impl Drop for VipsInterpolate {
1029 fn drop(&mut self) {
1030 unsafe {
1031 if !self
1032 .ctx
1033 .is_null()
1034 {
1035 bindings::g_object_unref(self.ctx as *mut c_void);
1036 }
1037 }
1038 }
1039}
1040
1041impl Drop for VipsBlob {
1042 fn drop(&mut self) {
1043 unsafe {
1044 if !self
1045 .ctx
1046 .is_null()
1047 {
1048 bindings::g_object_unref(self.ctx as *mut c_void);
1049 }
1050 }
1051 }
1052}
1053
1054impl Drop for VipsConnection {
1055 fn drop(&mut self) {
1056 unsafe {
1057 if !self
1058 .ctx
1059 .is_null()
1060 {
1061 bindings::g_object_unref(self.ctx as *mut c_void);
1062 }
1063 }
1064 }
1065}
1066
1067impl Drop for VipsSource {
1068 fn drop(&mut self) {
1069 unsafe {
1070 if !self
1071 .ctx
1072 .is_null()
1073 {
1074 bindings::g_object_unref(self.ctx as *mut c_void);
1075 }
1076 }
1077 }
1078}
1079
1080impl Drop for VipsTarget {
1081 fn drop(&mut self) {
1082 unsafe {
1083 if !self
1084 .ctx
1085 .is_null()
1086 {
1087 bindings::g_object_unref(self.ctx as *mut c_void);
1088 }
1089 }
1090 }
1091}
1092
1093impl Into<Vec<u8>> for VipsBlob {
1094 fn into(self) -> Vec<u8> {
1095 unsafe {
1096 let mut size: u64 = 0;
1097 let bytes = bindings::vips_blob_get(
1098 self.ctx,
1099 &mut size,
1100 );
1101 Vec::from_raw_parts(
1102 bytes as *mut u8,
1103 size as usize,
1104 size as usize,
1105 )
1106 }
1107 }
1108}