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