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_interpretation(&self) -> Result<Interpretation> {
323 unsafe {
324 let res = bindings::vips_image_get_interpretation(self.ctx);
325 let format_enum = FromPrimitive::from_i32(res);
326 format_enum.ok_or_else(|| Error::IOError("Could get format from image"))
327 }
328 }
329
330 pub fn guess_interpretation(&self) -> Result<Interpretation> {
331 unsafe {
332 let res = bindings::vips_image_guess_interpretation(self.ctx);
333 let format_enum = FromPrimitive::from_i32(res);
334 format_enum.ok_or_else(|| Error::IOError("Could get format from image"))
335 }
336 }
337
338 pub fn image_set_delete_on_close(&mut self, flag: bool) {
339 unsafe {
340 bindings::vips_image_set_delete_on_close(self.ctx, if flag { 1 } else { 0 });
341 }
342 }
343
344 pub fn image_invalidate_all(&self) {
345 unsafe {
346 bindings::vips_image_invalidate_all(self.ctx);
347 }
348 }
349
350 pub fn image_minimise_all(&self) {
351 unsafe {
352 bindings::vips_image_minimise_all(self.ctx);
353 }
354 }
355
356 pub fn image_iskilled(&self) -> bool {
357 unsafe { bindings::vips_image_iskilled(self.ctx) == 1 }
358 }
359
360 pub fn image_isMSBfirst(&self) -> bool {
361 unsafe { bindings::vips_image_isMSBfirst(self.ctx) == 1 }
362 }
363
364 pub fn image_isfile(&self) -> bool {
365 unsafe { bindings::vips_image_isfile(self.ctx) == 1 }
366 }
367
368 pub fn image_ispartial(&self) -> bool {
369 unsafe { bindings::vips_image_ispartial(self.ctx) == 1 }
370 }
371
372 pub fn image_hasalpha(&self) -> bool {
373 unsafe { bindings::vips_image_hasalpha(self.ctx) == 1 }
374 }
375
376 pub fn image_set_kill(&self, flag: bool) {
377 unsafe {
378 bindings::vips_image_set_kill(self.ctx, if flag { 1 } else { 0 });
379 }
380 }
381
382 pub fn image_set_progress(&self, flag: bool) {
383 unsafe {
384 bindings::vips_image_set_progress(self.ctx, if flag { 1 } else { 0 });
385 }
386 }
387
388 pub fn image_write(&self) -> Result<VipsImage> {
389 unsafe {
390 let out: *mut bindings::VipsImage = null_mut();
391 let res = bindings::vips_image_write(self.ctx, out);
392 utils::result(
393 res,
394 VipsImage { ctx: out },
395 Error::IOError("Cannot write input to output"),
396 )
397 }
398 }
399
400 pub fn image_pio_input(&mut self) -> Result<()> {
401 unsafe {
402 let res = bindings::vips_image_pio_input(self.ctx);
403 utils::result(res, (), Error::IOError("Cannot read image"))
404 }
405 }
406
407 pub fn image_pio_output(&mut self) -> Result<()> {
408 unsafe {
409 let res = bindings::vips_image_pio_output(self.ctx);
410 utils::result(res, (), Error::IOError("Cannot write image"))
411 }
412 }
413
414 pub fn image_inplace(&self) -> Result<()> {
415 unsafe {
416 let res = bindings::vips_image_inplace(self.ctx);
417 utils::result(res, (), Error::IOError("Cannot cannot be modified inplace"))
418 }
419 }
420
421 pub fn image_write_to_file(&self, filename: &str) -> Result<()> {
422 unsafe {
423 let file_c_str = utils::new_c_string(filename)?;
424 let res = bindings::vips_image_write_to_file(self.ctx, file_c_str.as_ptr(), NULL);
425 utils::result(res, (), Error::IOError("Cannot write to file"))
426 }
427 }
428
429 pub fn image_write_prepare(&self) -> Result<()> {
430 unsafe {
431 let res = bindings::vips_image_write_prepare(self.ctx);
432 utils::result(res, (), Error::IOError("Cannot prepare file to write"))
433 }
434 }
435
436 pub fn image_write_to_buffer(&self, suffix: &str) -> Result<Vec<u8>> {
437 unsafe {
438 let mut buffer_buf_size: u64 = 0;
439 let mut buffer_out: *mut c_void = null_mut();
440 let suffix_c_str = utils::new_c_string(suffix)?;
441 let res = bindings::vips_image_write_to_buffer(
442 self.ctx,
443 suffix_c_str.as_ptr(),
444 &mut buffer_out,
445 &mut buffer_buf_size,
446 NULL,
447 );
448 utils::result(
449 res,
450 utils::new_byte_array(buffer_out, buffer_buf_size),
451 Error::IOError("Cannot write content to buffer"),
452 )
453 }
454 }
455
456 pub fn image_write_to_memory(&self) -> Vec<u8> {
457 unsafe {
458 let mut buffer_buf_size: u64 = 0;
459 let buffer_out = bindings::vips_image_write_to_memory(self.ctx, &mut buffer_buf_size);
460 let buf = std::slice::from_raw_parts(buffer_out as *mut u8, buffer_buf_size as usize).to_vec();
461 bindings::g_free(buffer_out);
462 buf
463 }
464 }
465
466 pub fn image_decode_predict(&self) -> Result<(i32, BandFormat)> {
467 unsafe {
468 let mut out_bands = 0;
469 let mut out_format = 0;
470 let res =
471 bindings::vips_image_decode_predict(self.ctx, &mut out_bands, &mut out_format);
472 let format_enum = FromPrimitive::from_i32(out_format);
473 if format_enum.is_some() {
474 utils::result(
475 res,
476 (out_bands, format_enum.unwrap()),
477 Error::IOError("Could not predict image format"),
478 )
479 } else {
480 Err(Error::IOError("Could not predict image format"))
481 }
482 }
483 }
484
485 pub fn image_decode(&self) -> Result<VipsImage> {
486 unsafe {
487 let mut out: *mut bindings::VipsImage = null_mut();
488 let res = bindings::vips_image_decode(self.ctx, &mut out);
489 utils::result(
490 res,
491 VipsImage { ctx: out },
492 Error::IOError("Cannot decode image"),
493 )
494 }
495 }
496
497 pub fn image_encode(&self, coding: Coding) -> Result<VipsImage> {
498 unsafe {
499 let mut out: *mut bindings::VipsImage = null_mut();
500 let res = bindings::vips_image_encode(self.ctx, &mut out, coding as i32);
501 utils::result(
502 res,
503 VipsImage { ctx: out },
504 Error::IOError("Cannot encode image"),
505 )
506 }
507 }
508}
509
510impl VipsConnection {
511 pub fn connection_filename(&self) -> Option<String> {
512 unsafe {
513 let result = bindings::vips_connection_filename(self.ctx);
514 if result.is_null() {
515 None
516 } else {
517 let cstr = CStr::from_ptr(result);
518 match cstr.to_string_lossy() {
519 Cow::Borrowed(slice) => Some(slice.to_string()),
520 Cow::Owned(string) => Some(string),
521 }
522 }
523 }
524 }
525
526 pub fn connection_nick(&self) -> Option<String> {
527 unsafe {
528 let result = bindings::vips_connection_nick(self.ctx);
529 if result.is_null() {
530 None
531 } else {
532 let cstr = CStr::from_ptr(result);
533 match cstr.to_string_lossy() {
534 Cow::Borrowed(slice) => Some(slice.to_string()),
535 Cow::Owned(string) => Some(string),
536 }
537 }
538 }
539 }
540}
541
542impl VipsSource {
543 pub fn new_from_descriptor(descriptor: i32) -> Result<Self> {
544 unsafe {
545 let res = bindings::vips_source_new_from_descriptor(descriptor);
546 vips_source_result(
547 res,
548 Error::InitializationError("Could not initialise VipsSource from descriptor"),
549 )
550 }
551 }
552
553 pub fn new_from_file(filename: &str) -> Result<Self> {
554 unsafe {
555 let f = utils::new_c_string(filename)?;
556 let res = bindings::vips_source_new_from_file(f.as_ptr());
557 vips_source_result(
558 res,
559 Error::InitializationError("Could not initialise VipsSource from file"),
560 )
561 }
562 }
563
564 fn new_from_blob(blob: VipsBlob) -> Result<Self> {
567 unsafe {
568 let res = bindings::vips_source_new_from_blob(blob.ctx);
569 vips_source_result(
570 res,
571 Error::InitializationError("Could not initialise VipsSource from blob"),
572 )
573 }
574 }
575
576 pub fn new_from_memory(buffer: &[u8]) -> Result<Self> {
577 unsafe {
578 let res = bindings::vips_source_new_from_memory(
579 buffer.as_ptr() as *const c_void,
580 buffer.len() as u64,
581 );
582 vips_source_result(
583 res,
584 Error::InitializationError("Could not initialise VipsSource from memory"),
585 )
586 }
587 }
588
589 pub fn new_from_options(option_str: &str) -> Result<Self> {
590 unsafe {
591 let options = utils::new_c_string(option_str)?;
592 let res = bindings::vips_source_new_from_options(options.as_ptr());
593 vips_source_result(
594 res,
595 Error::InitializationError("Could not initialise VipsSource from options"),
596 )
597 }
598 }
599
600 pub fn minimise(&mut self) {
601 unsafe {
602 bindings::vips_source_minimise(self.ctx);
603 }
604 }
605
606 pub fn unminimise(&mut self) -> Result<()> {
607 unsafe {
608 let result = bindings::vips_source_unminimise(self.ctx);
609 utils::result(
610 result,
611 (),
612 Error::OperationError("Error on vips unminimise"),
613 )
614 }
615 }
616
617 pub fn decode(&mut self) -> Result<()> {
618 unsafe {
619 let result = bindings::vips_source_decode(self.ctx);
620 utils::result(
621 result,
622 (),
623 Error::OperationError("Error on vips decode"),
624 )
625 }
626 }
627
628 pub fn read(&mut self, length: u64) -> Result<Vec<u8>> {
629 unsafe {
630 let bytes: *mut c_void = null_mut();
631 let result = bindings::vips_source_read(self.ctx, bytes, length);
632 if result != -1 {
633 let buffer =
634 Vec::from_raw_parts(bytes as *mut u8, result as usize, result as usize);
635 Ok(buffer)
636 } else {
637 Err(Error::OperationError("Error on vips read"))
638 }
639 }
640 }
641
642 pub fn is_mappable(&self) -> bool {
643 unsafe { bindings::vips_source_is_mappable(self.ctx) == 1 }
644 }
645
646 pub fn seek(&mut self, offset: i64, whence: i32) -> Result<i64> {
647 unsafe {
648 let result = bindings::vips_source_seek(self.ctx, offset, whence);
649 if result == -1 {
650 Err(Error::OperationError("Error on vips seek"))
651 } else {
652 Ok(result)
653 }
654 }
655 }
656
657 pub fn rewind(&mut self) -> Result<()> {
658 unsafe {
659 let result = bindings::vips_source_rewind(self.ctx);
660 if result == -1 {
661 Err(Error::OperationError("Error on vips rewind"))
662 } else {
663 Ok(())
664 }
665 }
666 }
667
668 pub fn length(&self) -> Result<i64> {
669 unsafe {
670 let result = bindings::vips_source_length(self.ctx);
671 if result == -1 {
672 Err(Error::OperationError("Error on vips length"))
673 } else {
674 Ok(result)
675 }
676 }
677 }
678}
679
680impl<'a> VipsSource {
681 pub fn map(&'a self) -> Result<&'a [u8]> {
682 unsafe {
683 let length: *mut u64 = null_mut();
684 let result = bindings::vips_source_map(self.ctx, length);
685 if length.is_null() {
686 Err(Error::OperationError("Error on vips map"))
687 } else {
688 let size = (*length)
689 .try_into()
690 .map_err(|_| Error::OperationError("Can't get size of array"))?;
691 Ok(std::slice::from_raw_parts(result as *mut u8, size))
692 }
693 }
694 }
695
696 }
707
708impl VipsTarget {
709 pub fn new_to_descriptor(descriptor: i32) -> Result<Self> {
710 unsafe {
711 let res = bindings::vips_target_new_to_descriptor(descriptor);
712 vips_target_result(
713 res,
714 Error::InitializationError("Could not initialise VipsTarget from descriptor"),
715 )
716 }
717 }
718
719 pub fn new_to_file(filename: &str) -> Result<Self> {
720 unsafe {
721 let f = utils::new_c_string(filename)?;
722 let res = bindings::vips_target_new_to_file(f.as_ptr());
723 vips_target_result(
724 res,
725 Error::InitializationError("Could not initialise VipsTarget from file"),
726 )
727 }
728 }
729
730 pub fn new_to_memory() -> Result<Self> {
731 unsafe {
732 let res = bindings::vips_target_new_to_memory();
733 vips_target_result(
734 res,
735 Error::InitializationError("Could not initialise VipsTarget from memory"),
736 )
737 }
738 }
739
740 pub fn write(&mut self, buffer: &[u8]) -> Result<()> {
741 unsafe {
742 let res = bindings::vips_target_write(
743 self.ctx,
744 buffer.as_ptr() as *const c_void,
745 buffer.len() as u64,
746 );
747 if res == -1 {
748 Err(Error::OperationError("Could not write to buffer"))
749 } else {
750 Ok(())
751 }
752 }
753 }
754
755 pub fn finish(self) {
756 unsafe {
757 bindings::vips_target_finish(self.ctx);
758 }
759 }
760
761 pub fn putc(&mut self, ch: char) -> Result<()> {
762 unsafe {
763 let res = bindings::vips_target_putc(self.ctx, ch as i32);
764 if res == -1 {
765 Err(Error::OperationError("Could not write to buffer"))
766 } else {
767 Ok(())
768 }
769 }
770 }
771
772 pub fn writes(&mut self, text: &str) -> Result<()> {
773 unsafe {
774 let cstr = CString::new(text).map_err(|_| Error::OperationError("Cannot initialize C string"))?;
775 let res = bindings::vips_target_writes(self.ctx, cstr.as_ptr());
776 if res == -1 {
777 Err(Error::OperationError("Could not write to buffer"))
778 } else {
779 Ok(())
780 }
781 }
782 }
783
784 pub fn write_amp(&mut self, text: &str) -> Result<()> {
785 unsafe {
786 let cstr = CString::new(text).map_err(|_| Error::OperationError("Cannot initialize C string"))?;
787 let res = bindings::vips_target_write_amp(self.ctx, cstr.as_ptr());
788 if res == -1 {
789 Err(Error::OperationError("Could not write to buffer"))
790 } else {
791 Ok(())
792 }
793 }
794 }
795}
796
797unsafe fn vips_image_result(res: *mut bindings::VipsImage, err: Error) -> Result<VipsImage> {
798 if res.is_null() {
799 Err(err)
800 } else {
801 Ok(VipsImage { ctx: res })
802 }
803}
804
805unsafe fn vips_source_result(res: *mut bindings::VipsSource, err: Error) -> Result<VipsSource> {
806 if res.is_null() {
807 Err(err)
808 } else {
809 Ok(VipsSource { ctx: res })
810 }
811}
812
813unsafe fn vips_target_result(res: *mut bindings::VipsTarget, err: Error) -> Result<VipsTarget> {
814 if res.is_null() {
815 Err(err)
816 } else {
817 Ok(VipsTarget { ctx: res })
818 }
819}
820
821impl VipsInterpolate {
822 pub fn new() -> VipsInterpolate {
824 unsafe {
825 VipsInterpolate {
826 ctx: bindings::vips_interpolate_nearest_static(),
827 }
828 }
829 }
830
831 pub fn new_from_neasest_static() -> VipsInterpolate {
832 unsafe {
833 VipsInterpolate {
834 ctx: bindings::vips_interpolate_nearest_static(),
835 }
836 }
837 }
838
839 pub fn new_from_bilinear_static() -> VipsInterpolate {
840 unsafe {
841 VipsInterpolate {
842 ctx: bindings::vips_interpolate_bilinear_static(),
843 }
844 }
845 }
846
847 pub fn new_from_name(name: &str) -> Result<VipsInterpolate> {
848 unsafe {
849 let nickname = utils::new_c_string(name)?;
850 let res = bindings::vips_interpolate_new(nickname.as_ptr());
851 if res.is_null() {
852 Err(Error::InitializationError(
853 "Cannot initialize interpolator with provided nickname",
854 ))
855 } else {
856 Ok(VipsInterpolate { ctx: res })
857 }
858 }
859 }
860
861 pub fn get_window_size(&self) -> i32 {
862 unsafe { bindings::vips_interpolate_get_window_size(self.ctx) }
863 }
864
865 pub fn get_windows_offset(&self) -> i32 {
866 unsafe { bindings::vips_interpolate_get_window_offset(self.ctx) }
867 }
868}
869
870impl Drop for VipsImage {
871 fn drop(&mut self) {
872 unsafe {
873 if !self.ctx.is_null() {
874 bindings::g_object_unref(self.ctx as *mut c_void);
875 }
876 }
877 }
878}
879
880impl Drop for VipsInterpolate {
881 fn drop(&mut self) {
882 unsafe {
883 if !self.ctx.is_null() {
884 bindings::g_object_unref(self.ctx as *mut c_void);
885 }
886 }
887 }
888}
889
890impl Drop for VipsBlob {
891 fn drop(&mut self) {
892 unsafe {
893 if !self.ctx.is_null() {
894 bindings::g_object_unref(self.ctx as *mut c_void);
895 }
896 }
897 }
898}
899
900impl Drop for VipsConnection {
901 fn drop(&mut self) {
902 unsafe {
903 if !self.ctx.is_null() {
904 bindings::g_object_unref(self.ctx as *mut c_void);
905 }
906 }
907 }
908}
909
910impl Drop for VipsSource {
911 fn drop(&mut self) {
912 unsafe {
913 if !self.ctx.is_null() {
914 bindings::g_object_unref(self.ctx as *mut c_void);
915 }
916 }
917 }
918}
919
920impl Drop for VipsTarget {
921 fn drop(&mut self) {
922 unsafe {
923 if !self.ctx.is_null() {
924 bindings::g_object_unref(self.ctx as *mut c_void);
925 }
926 }
927 }
928}
929
930impl Into<Vec<u8>> for VipsBlob {
931 fn into(self) -> Vec<u8> {
932 unsafe {
933 let mut size: u64 = 0;
934 let bytes = bindings::vips_blob_get(self.ctx, &mut size);
935 Vec::from_raw_parts(bytes as *mut u8, size as usize, size as usize)
936 }
937 }
938}