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