1#![allow(unused_imports)]
2use crate::{
3 bindings::{
4 g_log, g_object_get_property, g_object_ref, g_object_set_property, g_object_unref,
5 g_type_check_instance_is_a, g_value_dup_boxed, g_value_get_boolean, g_value_get_double,
6 g_value_get_int, g_value_get_object, g_value_get_string, g_value_init, g_value_set_boolean,
7 g_value_set_boxed, g_value_set_double, g_value_set_enum, g_value_set_int,
8 g_value_set_object, g_value_set_string, g_value_set_uint64, g_value_unset, vips_area_unref,
9 vips_array_double_get_type, vips_array_image_get_type, vips_array_int_get_type,
10 vips_blob_get_type, vips_cache_operation_buildp, vips_enum_from_nick, vips_error_buffer,
11 vips_error_clear, vips_image_get_type, vips_interpolate_get_type, vips_object_get_argument,
12 vips_object_set_from_string, vips_object_unref_outputs, vips_operation_new,
13 vips_source_get_type, vips_target_get_type, vips_value_get_array_double,
14 vips_value_get_array_image, vips_value_set_array_double, vips_value_set_array_image,
15 vips_value_set_array_int, GLogLevelFlags_G_LOG_LEVEL_WARNING, GParamSpec, GTypeInstance,
16 GValue, VipsArgumentClass, VipsArgumentInstance, VipsBlob, VipsImage, VipsObject,
17 VipsOperation,
18 },
19 unref_area,
20 utils::{
21 get_g_type, new_c_string, G_TYPE_BOOLEAN, G_TYPE_DOUBLE, G_TYPE_INT, G_TYPE_STRING,
22 G_TYPE_UINT64,
23 },
24};
25use std::{mem::MaybeUninit, os::raw::c_void};
26
27pub fn call(operation: &str, option: VOption) -> std::os::raw::c_int {
29 call_option_string(
30 operation,
31 "",
32 option,
33 )
34}
35
36pub fn call_option_string(
38 operation: &str,
39 option_string: &str,
40 option: VOption,
41) -> std::os::raw::c_int {
42 let operation = new_c_string(operation).unwrap();
43 let option_string = new_c_string(option_string).unwrap();
44 call_option_string_(
45 operation.as_ptr(),
46 option_string.as_ptr() as _,
47 option,
48 )
49}
50
51pub(crate) fn call_option_string_(
52 operation: *const i8,
53 option_string: *mut i8,
54 option: VOption,
55) -> std::os::raw::c_int {
56 unsafe {
57 let mut vips_operation = vips_operation_new(operation);
58
59 if !option_string.is_null()
60 && vips_object_set_from_string(
61 vips_operation as _,
62 option_string,
63 ) < 0
64 {
65 vips_object_unref_outputs(vips_operation as _);
66 g_object_unref(vips_operation as _);
67 return 1;
68 }
69
70 set_opreration(
71 vips_operation,
72 &option,
73 );
74
75 let result = vips_cache_operation_buildp(&mut vips_operation);
76
77 if result < 0 {
78 vips_object_unref_outputs(vips_operation as _);
79 g_object_unref(vips_operation as _);
80 return 1;
81 }
82
83 get_operation(
84 vips_operation,
85 option,
86 );
87
88 g_object_unref(vips_operation as _);
89
90 result
91 }
92}
93
94enum VipsValue<'a> {
95 Bool(bool),
96 MutBool(&'a mut bool),
97 Int(i32),
98 MutInt(&'a mut i32),
99 Uint(u64),
100 Double(f64),
101 MutDouble(&'a mut f64),
102 Str(&'a str),
103 Image(&'a crate::VipsImage),
104 MutImage(&'a mut crate::VipsImage),
105 IntArray(&'a [i32]),
106 DoubleArray(&'a [f64]),
107 DoubleVec(Vec<f64>),
108 MutDoubleArray(&'a mut Vec<f64>),
109 ImageArray(&'a [crate::VipsImage]),
110 Blob(&'a crate::region::VipsBlob),
111 MutBlob(&'a mut crate::region::VipsBlob),
112 Target(&'a crate::connection::VipsTarget),
113 Source(&'a crate::connection::VipsSource),
114 Interpolate(&'a crate::interpolate::VipsInterpolate),
115}
116
117struct Pair<'a> {
118 input: bool,
119 name: String,
120 value: VipsValue<'a>,
121}
122
123impl<'a> Pair<'a> {
124 fn input(name: &str, value: VipsValue<'a>) -> Self {
125 Self {
126 input: true,
127 name: name.to_string(),
128 value,
129 }
130 }
131
132 fn output(name: &str, value: VipsValue<'a>) -> Self {
133 Self {
134 input: false,
135 name: name.to_string(),
136 value,
137 }
138 }
139}
140
141#[derive(Default)]
143pub struct VOption<'a> {
144 options: Vec<Pair<'a>>,
145}
146
147impl<'a> VOption<'a> {
148 pub fn new() -> Self {
149 Self {
150 options: Vec::new(),
151 }
152 }
153}
154
155fn get_operation(vips_operation: *mut VipsOperation, option: VOption) {
156 unsafe {
157 for opt in option.options {
158 if opt.input {
159 continue;
160 }
161
162 let mut gvalue = MaybeUninit::<GValue>::zeroed();
163 let gvalue_ptr = gvalue.as_mut_ptr();
164 let name = new_c_string(opt.name).unwrap();
165
166 match opt.value {
167 VipsValue::MutBool(out) => {
168 g_value_init(
169 gvalue_ptr,
170 get_g_type(G_TYPE_BOOLEAN),
171 );
172 g_object_get_property(
173 vips_operation.cast(),
174 name.as_ptr(),
175 gvalue_ptr,
176 );
177 *out = g_value_get_boolean(gvalue_ptr) != 0;
178 }
179 VipsValue::MutInt(out) => {
180 g_value_init(
181 gvalue_ptr,
182 get_g_type(G_TYPE_INT),
183 );
184 g_object_get_property(
185 vips_operation.cast(),
186 name.as_ptr(),
187 gvalue_ptr,
188 );
189 *out = g_value_get_int(gvalue_ptr);
190 }
191 VipsValue::MutDouble(out) => {
192 g_value_init(
193 gvalue_ptr,
194 get_g_type(G_TYPE_DOUBLE),
195 );
196 g_object_get_property(
197 vips_operation.cast(),
198 name.as_ptr(),
199 gvalue_ptr,
200 );
201 *out = g_value_get_double(gvalue_ptr);
202 }
203 VipsValue::MutDoubleArray(out) => {
204 g_value_init(
205 gvalue_ptr,
206 vips_array_double_get_type(),
207 );
208 g_object_get_property(
209 vips_operation.cast(),
210 name.as_ptr(),
211 gvalue_ptr,
212 );
213 let mut len: i32 = 0;
214 let array = vips_value_get_array_double(
215 gvalue_ptr,
216 &mut len,
217 );
218 let result = std::slice::from_raw_parts(
219 array,
220 len as usize,
221 );
222 out.extend(result);
223 }
224 VipsValue::MutBlob(out) => {
225 g_value_init(
226 gvalue_ptr,
227 vips_blob_get_type(),
228 );
229 g_object_get_property(
230 vips_operation.cast(),
231 name.as_ptr(),
232 gvalue_ptr,
233 );
234 let out_blob: *mut VipsBlob = g_value_dup_boxed(gvalue_ptr).cast();
235 out.ctx = out_blob;
236 }
237 VipsValue::MutImage(out) => {
238 g_value_init(
239 gvalue_ptr,
240 vips_image_get_type(),
241 );
242 g_object_get_property(
243 vips_operation.cast(),
244 name.as_ptr(),
245 gvalue_ptr,
246 );
247 let out_image: *mut VipsImage = g_value_get_object(gvalue_ptr).cast();
248 out.ctx = out_image;
249 }
250 _ => {}
251 }
252 g_value_unset(gvalue_ptr);
253 }
254 }
255}
256
257fn set_opreration(operation: *mut VipsOperation, option: &VOption) {
258 unsafe {
259 for pair in &option.options {
260 if !pair.input {
261 continue;
262 }
263
264 let mut gvalue = MaybeUninit::<GValue>::zeroed();
265 let gvalue_ptr = gvalue.as_mut_ptr();
266
267 match pair.value {
268 VipsValue::Bool(value) => {
269 g_value_init(
270 gvalue_ptr,
271 get_g_type(G_TYPE_BOOLEAN),
272 );
273 g_value_set_boolean(
274 gvalue_ptr,
275 value.into(),
276 );
277 }
278 VipsValue::Int(value) => {
279 g_value_init(
280 gvalue_ptr,
281 get_g_type(G_TYPE_INT),
282 );
283 g_value_set_int(
284 gvalue_ptr,
285 value,
286 );
287 }
288 VipsValue::Uint(value) => {
289 g_value_init(
290 gvalue_ptr,
291 get_g_type(G_TYPE_UINT64),
292 );
293 g_value_set_uint64(
294 gvalue_ptr,
295 value,
296 );
297 }
298 VipsValue::Double(value) => {
299 g_value_init(
300 gvalue_ptr,
301 get_g_type(G_TYPE_DOUBLE),
302 );
303 g_value_set_double(
304 gvalue_ptr,
305 value,
306 );
307 }
308 VipsValue::Str(value) => {
309 let str = new_c_string(value).unwrap();
310 g_value_init(
311 gvalue_ptr,
312 get_g_type(G_TYPE_STRING),
313 );
314 g_value_set_string(
315 gvalue_ptr,
316 str.as_ptr(),
317 );
318 }
319 VipsValue::IntArray(value) => {
320 g_value_init(
321 gvalue_ptr,
322 vips_array_int_get_type(),
323 );
324 vips_value_set_array_int(
325 gvalue_ptr,
326 value.as_ptr(),
327 value.len() as _,
328 );
329 }
330 VipsValue::DoubleArray(value) => {
331 g_value_init(
332 gvalue_ptr,
333 vips_array_double_get_type(),
334 );
335 vips_value_set_array_double(
336 gvalue_ptr,
337 value.as_ptr(),
338 value.len() as _,
339 );
340 }
341 VipsValue::Image(value) => {
342 g_value_init(
343 gvalue_ptr,
344 vips_image_get_type(),
345 );
346 g_value_set_object(
347 gvalue_ptr,
348 value.ctx as *mut c_void,
349 );
350 }
351 VipsValue::ImageArray(value) => {
352 g_value_init(
353 gvalue_ptr,
354 vips_array_image_get_type(),
355 );
356 vips_value_set_array_image(
357 gvalue_ptr,
358 value.len() as _,
359 );
360 let array = vips_value_get_array_image(
361 gvalue_ptr,
362 &mut 0,
363 );
364 let array = std::slice::from_raw_parts_mut(
365 array,
366 value.len() as _,
367 );
368 for i in 0..value.len() {
369 g_object_ref(value[i].ctx as _);
370 array[i] = value[i].ctx;
371 }
372 }
373 VipsValue::Blob(value) => {
374 g_value_init(
375 gvalue_ptr,
376 vips_blob_get_type(),
377 );
378 g_value_set_boxed(
379 gvalue_ptr,
380 value.ctx as *const c_void,
381 );
382 }
383 VipsValue::Source(value) => {
384 g_value_init(
385 gvalue_ptr,
386 vips_source_get_type(),
387 );
388 g_value_set_object(
389 gvalue_ptr,
390 value.ctx as *mut c_void,
391 );
392 }
393 VipsValue::Target(value) => {
394 g_value_init(
395 gvalue_ptr,
396 vips_target_get_type(),
397 );
398 g_value_set_object(
399 gvalue_ptr,
400 value.ctx as *mut c_void,
401 );
402 }
403 VipsValue::Interpolate(value) => {
404 g_value_init(
405 gvalue_ptr,
406 vips_interpolate_get_type(),
407 );
408 g_value_set_object(
409 gvalue_ptr,
410 value.ctx as *mut c_void,
411 );
412 }
413 _ => {}
414 }
415
416 set_property(
417 operation,
418 &pair.name,
419 gvalue_ptr,
420 );
421 g_value_unset(gvalue_ptr);
422 }
423 }
424}
425
426fn set_property(operation: *mut VipsOperation, name: &str, value: *mut GValue) {
427 unsafe {
428 let object: *mut VipsObject = operation.cast();
429 let name = new_c_string(name).unwrap();
430
431 let mut pspec: *mut GParamSpec = std::ptr::null_mut();
432 let mut argument_class: *mut VipsArgumentClass = std::ptr::null_mut();
433 let mut argument_instance: *mut VipsArgumentInstance = std::ptr::null_mut();
434 if vips_object_get_argument(
435 object,
436 name.as_ptr(),
437 &mut pspec,
438 &mut argument_class,
439 &mut argument_instance,
440 ) < 0
441 {
442 g_warning();
443 vips_error_clear();
444 return;
445 }
446
447 let is_param_spec_enum = g_type_check_instance_is_a(
448 pspec as *mut GTypeInstance,
449 get_g_type("GParamEnum"),
450 ) != 0;
451
452 if is_param_spec_enum && (*value).g_type == get_g_type(G_TYPE_STRING) {
453 let pspec_type = (*pspec).value_type;
454 let enum_value = vips_enum_from_nick(
455 (*object).nickname,
456 pspec_type,
457 g_value_get_string(value),
458 );
459 if enum_value < 0 {
460 g_warning();
461 vips_error_clear();
462 return;
463 }
464
465 let mut gvalue = MaybeUninit::<GValue>::zeroed();
466 let value2 = gvalue.as_mut_ptr();
467 g_value_init(
468 value2,
469 pspec_type,
470 );
471 g_value_set_enum(
472 value2,
473 enum_value,
474 );
475 g_object_set_property(
476 object.cast(),
477 name.as_ptr(),
478 value2,
479 );
480 g_value_unset(value2);
481 } else {
482 g_object_set_property(
483 object.cast(),
484 name.as_ptr(),
485 value,
486 );
487 }
488 }
489}
490
491fn g_warning() {
492 let domain = new_c_string("GLib-GObject").unwrap();
493 let format = new_c_string("%s").unwrap();
494 unsafe {
495 g_log(
496 domain.as_ptr(),
497 GLogLevelFlags_G_LOG_LEVEL_WARNING,
498 format.as_ptr(),
499 vips_error_buffer(),
500 )
501 };
502}
503
504pub trait Setter<'a, T> {
506 fn set(self, name: &str, value: T) -> VOption<'a>;
507 fn add(&mut self, name: &str, value: T);
508}
509
510impl<'a> Setter<'a, bool> for VOption<'a> {
512 fn set(mut self, name: &str, value: bool) -> VOption<'a> {
513 self.options
514 .push(
515 Pair::input(
516 name,
517 VipsValue::Bool(value),
518 ),
519 );
520 self
521 }
522 fn add(&mut self, name: &str, value: bool) {
523 self.options
524 .push(
525 Pair::input(
526 name,
527 VipsValue::Bool(value),
528 ),
529 );
530 }
531}
532
533impl<'a> Setter<'a, i32> for VOption<'a> {
535 fn set(mut self, name: &str, value: i32) -> VOption<'a> {
536 self.options
537 .push(
538 Pair::input(
539 name,
540 VipsValue::Int(value),
541 ),
542 );
543 self
544 }
545 fn add(&mut self, name: &str, value: i32) {
546 self.options
547 .push(
548 Pair::input(
549 name,
550 VipsValue::Int(value),
551 ),
552 );
553 }
554}
555
556impl<'a> Setter<'a, u64> for VOption<'a> {
558 fn set(mut self, name: &str, value: u64) -> VOption<'a> {
559 self.options
560 .push(
561 Pair::input(
562 name,
563 VipsValue::Uint(value),
564 ),
565 );
566 self
567 }
568 fn add(&mut self, name: &str, value: u64) {
569 self.options
570 .push(
571 Pair::input(
572 name,
573 VipsValue::Uint(value),
574 ),
575 );
576 }
577}
578
579impl<'a> Setter<'a, f64> for VOption<'a> {
581 fn set(mut self, name: &str, value: f64) -> VOption<'a> {
582 self.options
583 .push(
584 Pair::input(
585 name,
586 VipsValue::Double(value),
587 ),
588 );
589 self
590 }
591 fn add(&mut self, name: &str, value: f64) {
592 self.options
593 .push(
594 Pair::input(
595 name,
596 VipsValue::Double(value),
597 ),
598 );
599 }
600}
601
602impl<'a> Setter<'a, &'a str> for VOption<'a> {
604 fn set(mut self, name: &str, value: &'a str) -> VOption<'a> {
605 self.options
606 .push(
607 Pair::input(
608 name,
609 VipsValue::Str(value),
610 ),
611 );
612 self
613 }
614 fn add(&mut self, name: &str, value: &'a str) {
615 self.options
616 .push(
617 Pair::input(
618 name,
619 VipsValue::Str(value),
620 ),
621 );
622 }
623}
624
625impl<'a> Setter<'a, &'a String> for VOption<'a> {
626 fn set(mut self, name: &str, value: &'a String) -> VOption<'a> {
627 self.options
628 .push(
629 Pair::input(
630 name,
631 VipsValue::Str(value),
632 ),
633 );
634 self
635 }
636 fn add(&mut self, name: &str, value: &'a String) {
637 self.options
638 .push(
639 Pair::input(
640 name,
641 VipsValue::Str(value),
642 ),
643 );
644 }
645}
646
647impl<'a> Setter<'a, &'a crate::VipsImage> for VOption<'a> {
649 fn set(mut self, name: &str, value: &'a crate::VipsImage) -> VOption<'a> {
650 self.options
651 .push(
652 Pair::input(
653 name,
654 VipsValue::Image(value),
655 ),
656 );
657 self
658 }
659 fn add(&mut self, name: &str, value: &'a crate::VipsImage) {
660 self.options
661 .push(
662 Pair::input(
663 name,
664 VipsValue::Image(value),
665 ),
666 );
667 }
668}
669
670impl<'a> Setter<'a, &'a [i32]> for VOption<'a> {
672 fn set(mut self, name: &str, value: &'a [i32]) -> VOption<'a> {
673 self.options
674 .push(
675 Pair::input(
676 name,
677 VipsValue::IntArray(value),
678 ),
679 );
680 self
681 }
682 fn add(&mut self, name: &str, value: &'a [i32]) {
683 self.options
684 .push(
685 Pair::input(
686 name,
687 VipsValue::IntArray(value),
688 ),
689 );
690 }
691}
692
693impl<'a, const N: usize> Setter<'a, &'a [i32; N]> for VOption<'a> {
694 fn set(mut self, name: &str, value: &'a [i32; N]) -> VOption<'a> {
695 self.options
696 .push(
697 Pair::input(
698 name,
699 VipsValue::IntArray(value),
700 ),
701 );
702 self
703 }
704 fn add(&mut self, name: &str, value: &'a [i32; N]) {
705 self.options
706 .push(
707 Pair::input(
708 name,
709 VipsValue::IntArray(value),
710 ),
711 );
712 }
713}
714
715impl<'a> Setter<'a, &'a [f64]> for VOption<'a> {
717 fn set(mut self, name: &str, value: &'a [f64]) -> VOption<'a> {
718 self.options
719 .push(
720 Pair::input(
721 name,
722 VipsValue::DoubleArray(value),
723 ),
724 );
725 self
726 }
727 fn add(&mut self, name: &str, value: &'a [f64]) {
728 self.options
729 .push(
730 Pair::input(
731 name,
732 VipsValue::DoubleArray(value),
733 ),
734 );
735 }
736}
737
738impl<'a, const N: usize> Setter<'a, &'a [f64; N]> for VOption<'a> {
739 fn set(mut self, name: &str, value: &'a [f64; N]) -> VOption<'a> {
740 self.options
741 .push(
742 Pair::input(
743 name,
744 VipsValue::DoubleArray(value),
745 ),
746 );
747 self
748 }
749 fn add(&mut self, name: &str, value: &'a [f64; N]) {
750 self.options
751 .push(
752 Pair::input(
753 name,
754 VipsValue::DoubleArray(value),
755 ),
756 );
757 }
758}
759
760impl<'a> Setter<'a, &'a [crate::VipsImage]> for VOption<'a> {
762 fn set(mut self, name: &str, value: &'a [crate::VipsImage]) -> VOption<'a> {
763 self.options
764 .push(
765 Pair::input(
766 name,
767 VipsValue::ImageArray(value),
768 ),
769 );
770 self
771 }
772 fn add(&mut self, name: &str, value: &'a [crate::VipsImage]) {
773 self.options
774 .push(
775 Pair::input(
776 name,
777 VipsValue::ImageArray(value),
778 ),
779 );
780 }
781}
782
783impl<'a, const N: usize> Setter<'a, &'a [crate::VipsImage; N]> for VOption<'a> {
784 fn set(mut self, name: &str, value: &'a [crate::VipsImage; N]) -> VOption<'a> {
785 self.options
786 .push(
787 Pair::input(
788 name,
789 VipsValue::ImageArray(value),
790 ),
791 );
792 self
793 }
794 fn add(&mut self, name: &str, value: &'a [crate::VipsImage; N]) {
795 self.options
796 .push(
797 Pair::input(
798 name,
799 VipsValue::ImageArray(value),
800 ),
801 );
802 }
803}
804
805impl<'a> Setter<'a, &'a crate::region::VipsBlob> for VOption<'a> {
807 fn set(mut self, name: &str, value: &'a crate::region::VipsBlob) -> VOption<'a> {
808 self.options
809 .push(
810 Pair::input(
811 name,
812 VipsValue::Blob(value),
813 ),
814 );
815 self
816 }
817 fn add(&mut self, name: &str, value: &'a crate::region::VipsBlob) {
818 self.options
819 .push(
820 Pair::input(
821 name,
822 VipsValue::Blob(value),
823 ),
824 );
825 }
826}
827
828impl<'a> Setter<'a, &'a crate::connection::VipsTarget> for VOption<'a> {
830 fn set(mut self, name: &str, value: &'a crate::connection::VipsTarget) -> VOption<'a> {
831 self.options
832 .push(
833 Pair::input(
834 name,
835 VipsValue::Target(value),
836 ),
837 );
838 self
839 }
840 fn add(&mut self, name: &str, value: &'a crate::connection::VipsTarget) {
841 self.options
842 .push(
843 Pair::input(
844 name,
845 VipsValue::Target(value),
846 ),
847 );
848 }
849}
850
851impl<'a> Setter<'a, &'a crate::connection::VipsSource> for VOption<'a> {
853 fn set(mut self, name: &str, value: &'a crate::connection::VipsSource) -> VOption<'a> {
854 self.options
855 .push(
856 Pair::input(
857 name,
858 VipsValue::Source(value),
859 ),
860 );
861 self
862 }
863 fn add(&mut self, name: &str, value: &'a crate::connection::VipsSource) {
864 self.options
865 .push(
866 Pair::input(
867 name,
868 VipsValue::Source(value),
869 ),
870 );
871 }
872}
873
874impl<'a> Setter<'a, &'a crate::interpolate::VipsInterpolate> for VOption<'a> {
876 fn set(mut self, name: &str, value: &'a crate::interpolate::VipsInterpolate) -> VOption<'a> {
877 self.options
878 .push(
879 Pair::input(
880 name,
881 VipsValue::Interpolate(value),
882 ),
883 );
884 self
885 }
886 fn add(&mut self, name: &str, value: &'a crate::interpolate::VipsInterpolate) {
887 self.options
888 .push(
889 Pair::input(
890 name,
891 VipsValue::Interpolate(value),
892 ),
893 );
894 }
895}
896
897impl<'a> Setter<'a, &'a mut bool> for VOption<'a> {
899 fn set(mut self, name: &str, value: &'a mut bool) -> VOption<'a> {
900 self.options
901 .push(
902 Pair::output(
903 name,
904 VipsValue::MutBool(value),
905 ),
906 );
907 self
908 }
909 fn add(&mut self, name: &str, value: &'a mut bool) {
910 self.options
911 .push(
912 Pair::output(
913 name,
914 VipsValue::MutBool(value),
915 ),
916 );
917 }
918}
919
920impl<'a> Setter<'a, &'a mut i32> for VOption<'a> {
922 fn set(mut self, name: &str, value: &'a mut i32) -> VOption<'a> {
923 self.options
924 .push(
925 Pair::output(
926 name,
927 VipsValue::MutInt(value),
928 ),
929 );
930 self
931 }
932 fn add(&mut self, name: &str, value: &'a mut i32) {
933 self.options
934 .push(
935 Pair::output(
936 name,
937 VipsValue::MutInt(value),
938 ),
939 );
940 }
941}
942
943impl<'a> Setter<'a, &'a mut f64> for VOption<'a> {
945 fn set(mut self, name: &str, value: &'a mut f64) -> VOption<'a> {
946 self.options
947 .push(
948 Pair::output(
949 name,
950 VipsValue::MutDouble(value),
951 ),
952 );
953 self
954 }
955 fn add(&mut self, name: &str, value: &'a mut f64) {
956 self.options
957 .push(
958 Pair::output(
959 name,
960 VipsValue::MutDouble(value),
961 ),
962 );
963 }
964}
965
966impl<'a> Setter<'a, &'a mut crate::VipsImage> for VOption<'a> {
968 fn set(mut self, name: &str, value: &'a mut crate::VipsImage) -> VOption<'a> {
969 self.options
970 .push(
971 Pair::output(
972 name,
973 VipsValue::MutImage(value),
974 ),
975 );
976 self
977 }
978 fn add(&mut self, name: &str, value: &'a mut crate::VipsImage) {
979 self.options
980 .push(
981 Pair::output(
982 name,
983 VipsValue::MutImage(value),
984 ),
985 );
986 }
987}
988
989impl<'a> Setter<'a, &'a mut Vec<f64>> for VOption<'a> {
991 fn set(mut self, name: &str, value: &'a mut Vec<f64>) -> VOption<'a> {
992 self.options
993 .push(
994 Pair::output(
995 name,
996 VipsValue::MutDoubleArray(value),
997 ),
998 );
999 self
1000 }
1001 fn add(&mut self, name: &str, value: &'a mut Vec<f64>) {
1002 self.options
1003 .push(
1004 Pair::output(
1005 name,
1006 VipsValue::MutDoubleArray(value),
1007 ),
1008 );
1009 }
1010}
1011
1012impl<'a> Setter<'a, &'a mut crate::region::VipsBlob> for VOption<'a> {
1014 fn set(mut self, name: &str, value: &'a mut crate::region::VipsBlob) -> VOption<'a> {
1015 self.options
1016 .push(
1017 Pair::output(
1018 name,
1019 VipsValue::MutBlob(value),
1020 ),
1021 );
1022 self
1023 }
1024 fn add(&mut self, name: &str, value: &'a mut crate::region::VipsBlob) {
1025 self.options
1026 .push(
1027 Pair::output(
1028 name,
1029 VipsValue::MutBlob(value),
1030 ),
1031 );
1032 }
1033}