1 /* Define built-in VIPS types.
2  *
3  * J. Cupitt, 8/4/93.
4  *
5  * Modified:
6  * 21/5/07
7  *	- any length vector (Tom)
8  * 23/8/10
9  * 	- add IM_TYPE_RW flag for im__rw_image
10  */
11 
12 /*
13 
14     This file is part of VIPS.
15 
16     VIPS is free software; you can redistribute it and/or modify
17     it under the terms of the GNU Lesser General Public License as published by
18     the Free Software Foundation; either version 2 of the License, or
19     (at your option) any later version.
20 
21     This program is distributed in the hope that it will be useful,
22     but WITHOUT ANY WARRANTY; without even the implied warranty of
23     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24     GNU Lesser General Public License for more details.
25 
26     You should have received a copy of the GNU Lesser General Public License
27     along with this program; if not, write to the Free Software
28     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
29     02110-1301  USA
30 
31  */
32 
33 /*
34 
35     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
36 
37  */
38 
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif /*HAVE_CONFIG_H*/
42 #include <vips/intl.h>
43 
44 #include <errno.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 
49 #include <vips/vips.h>
50 #include <vips/vips7compat.h>
51 #include <vips/internal.h>
52 
53 /* String containing each of the characters which can be used within a
54  * single command line argument to separate the elements of a vector.
55  */
56 #define VEC_SEPS " "
57 
58 /* Init function for input displays. Just a stub nowadays.
59  */
60 static int
input_display_init(im_object * obj,char * str)61 input_display_init( im_object *obj, char *str )
62 {
63 	*obj = NULL;
64 
65 	return( 0 );
66 }
67 
68 /* Input display type.
69  */
70 im_type_desc im__input_display = {
71 	IM_TYPE_DISPLAY,		/* It's a display */
72 	0, 				/* No storage needed */
73 	IM_TYPE_ARG,			/* It requires a command-line arg */
74 	input_display_init,		/* Init function */
75 	NULL				/* Destroy function */
76 };
77 
78 /* Output display type.
79  */
80 im_type_desc im__output_display = {
81 	IM_TYPE_DISPLAY,		/* It's a display */
82 	sizeof( void * ),		/* Memory to allocate */
83 	IM_TYPE_OUTPUT,			/* Output object */
84 	NULL,				/* Init function */
85 	NULL				/* Destroy function */
86 };
87 
88 /* Init function for input images.
89  */
90 static int
input_image_init(im_object * obj,char * str)91 input_image_init( im_object *obj, char *str )
92 {
93 	IMAGE **im = (IMAGE **) obj;
94 
95 	return( !(*im = vips__deprecated_open_read( str, FALSE )) );
96 }
97 
98 /* Input image type.
99  */
100 im_type_desc im__input_image = {
101 	IM_TYPE_IMAGE,			/* It's an image */
102 	0, 				/* No storage needed */
103 	IM_TYPE_ARG,			/* It requires a command-line arg */
104 	(im_init_obj_fn) input_image_init,/* Init function */
105 	(im_dest_obj_fn) im_close	/* Destroy function */
106 };
107 
108 /* Init function for output images.
109  */
110 static int
output_image_init(im_object * obj,char * str)111 output_image_init( im_object *obj, char *str )
112 {
113 	IMAGE **im = (IMAGE **) obj;
114 
115 	return( !(*im = vips__deprecated_open_write( str )) );
116 }
117 
118 /* Output image type.
119  */
120 im_type_desc im__output_image = {
121 	IM_TYPE_IMAGE,			/* It's an image */
122 	0,				/* No storage to be allocated */
123 	IM_TYPE_OUTPUT | IM_TYPE_ARG,	/* Flags! */
124 	(im_init_obj_fn) output_image_init,/* Init function */
125 	(im_dest_obj_fn) im_close	/* Destroy function */
126 };
127 
128 /* Init function for RW images.
129  */
130 static int
rw_image_init(im_object * obj,char * str)131 rw_image_init( im_object *obj, char *str )
132 {
133 	IMAGE **im = (IMAGE **) obj;
134 
135 	return( !(*im = im_open( str, "rw" )) );
136 }
137 
138 /* RW image type.
139  */
140 im_type_desc im__rw_image = {
141 	IM_TYPE_IMAGE,			/* It's an image */
142 	0,				/* No storage to be allocated */
143 	IM_TYPE_ARG | IM_TYPE_RW,	/* Read-write object, needs an arg */
144 	(im_init_obj_fn) rw_image_init,	/* Init function */
145 	(im_dest_obj_fn) im_close	/* Destroy function */
146 };
147 
148 /* im_imagevec_object destroy function.
149  */
150 static int
imagevec_dest(im_object obj)151 imagevec_dest( im_object obj )
152 {
153 	im_imagevec_object *iv = obj;
154 
155 	if( iv->vec ) {
156 		int i;
157 
158 		for( i = 0; i < iv->n; i++ )
159 			if( iv->vec[i] ) {
160 				im_close( iv->vec[i] );
161 				iv->vec[i] = NULL;
162 			}
163 
164 		g_free( iv->vec );
165 		iv->vec = NULL;
166 		iv->n = 0;
167 	}
168 
169 	return( 0 );
170 }
171 
172 /* Init function for imagevec input.
173  */
174 static int
input_imagevec_init(im_object * obj,char * str)175 input_imagevec_init( im_object *obj, char *str )
176 {
177 	im_imagevec_object *iv = *obj;
178 	char **strv;
179 	int nargs;
180 	int i;
181 
182 	strv = g_strsplit( str, VEC_SEPS, -1 );
183 	nargs = g_strv_length( strv );
184 
185 	if( !(iv->vec = VIPS_ARRAY( NULL, nargs, IMAGE * )) ) {
186 		g_strfreev( strv );
187 		return( -1 );
188 	}
189 	iv->n = nargs;
190 
191 	/* Must NULL them out in case we fail halfway though opening them all.
192 	 */
193 	for( i = 0; i < nargs; i++ )
194 		iv->vec[i] = NULL;
195 
196 	for( i = 0; i < nargs; i++ )
197 		if( !(iv->vec[i] = im_open( strv[i], "rd" )) ) {
198 			g_strfreev( strv );
199 			return( -1 );
200 		}
201 
202 	g_strfreev( strv );
203 
204 	return( 0 );
205 }
206 
207 /* Input image vector type.
208  */
209 im_type_desc im__input_imagevec = {
210 	IM_TYPE_IMAGEVEC,		/* It's an array of IMAGE */
211 	sizeof( im_imagevec_object ), 	/* Memory to allocate in vec build */
212 	IM_TYPE_ARG,			/* It requires a command-line arg */
213 	input_imagevec_init,		/* Init function */
214 	imagevec_dest			/* Destroy function */
215 };
216 
217 /* Init function for masks. "str" can be NULL for output masks.
218  */
219 static int
mask_init(im_object * obj,char * str)220 mask_init( im_object *obj, char *str )
221 {
222 	im_mask_object *mo = *obj;
223 
224 	/* Install string, clear mask.
225 	 */
226 	if( str && !(mo->name = im_strdup( NULL, str )) )
227 		return( -1 );
228 	mo->mask = NULL;
229 
230 	return( 0 );
231 }
232 
233 /* Init function for input dmasks. As above, but read in the mask.
234  */
235 static int
dmask_init(im_object * obj,char * str)236 dmask_init( im_object *obj, char *str )
237 {
238 	im_mask_object *mo = *obj;
239 
240 	if( mask_init( obj, str ) )
241 		return( -1 );
242 	if( !(mo->mask = im_read_dmask( str )) )
243 		return( -1 );
244 
245 	return( 0 );
246 }
247 
248 /* Init function for input imasks.
249  */
250 static int
imask_init(im_object * obj,char * str)251 imask_init( im_object *obj, char *str )
252 {
253 	im_mask_object *mo = *obj;
254 
255 	if( mask_init( obj, str ) )
256 		return( -1 );
257 	if( !(mo->mask = im_read_imask( str )) )
258 		return( -1 );
259 
260 	return( 0 );
261 }
262 
263 /* DOUBLEMASK destroy function.
264  */
265 static int
dmask_dest(im_object obj)266 dmask_dest( im_object obj )
267 {
268 	im_mask_object *mo = obj;
269 
270 	VIPS_FREE( mo->name );
271 	VIPS_FREEF( im_free_dmask, mo->mask );
272 
273 	return( 0 );
274 }
275 
276 /* INTMASK destroy function.
277  */
278 static int
imask_dest(im_object obj)279 imask_dest( im_object obj )
280 {
281 	im_mask_object *mo = obj;
282 
283 	VIPS_FREE( mo->name );
284 	VIPS_FREEF( im_free_imask, mo->mask );
285 
286 	return( 0 );
287 }
288 
289 /* As above, but save the mask first.
290  */
291 static int
save_dmask_dest(im_object obj)292 save_dmask_dest( im_object obj )
293 {
294 	im_mask_object *mo = obj;
295 
296 	if( mo->mask && im_write_dmask( mo->mask ) )
297 		return( -1 );
298 	return( dmask_dest( obj ) );
299 }
300 
301 /* As above, but save the mask first.
302  */
303 static int
save_imask_dest(im_object obj)304 save_imask_dest( im_object obj )
305 {
306 	im_mask_object *mo = obj;
307 
308 	if( mo->mask && im_write_imask( mo->mask ) )
309 		return( -1 );
310 	return( imask_dest( obj ) );
311 }
312 
313 /* Output dmask type.
314  */
315 im_type_desc im__output_dmask = {
316 	IM_TYPE_DMASK,			/* It's a mask */
317 	sizeof( im_mask_object ),	/* Storage for mask object */
318 	IM_TYPE_OUTPUT | IM_TYPE_ARG,	/* Flags */
319 	mask_init,			/* Init function */
320 	save_dmask_dest			/* Save and destroy function */
321 };
322 
323 /* Input dmask type.
324  */
325 im_type_desc im__input_dmask = {
326 	IM_TYPE_DMASK,			/* It's a mask */
327 	sizeof( im_mask_object ),	/* Storage for mask object */
328 	IM_TYPE_ARG,			/* It requires a command-line arg */
329 	dmask_init,			/* Init function */
330 	dmask_dest			/* Destroy function */
331 };
332 
333 /* Output imask type.
334  */
335 im_type_desc im__output_imask = {
336 	IM_TYPE_IMASK,			/* It's a mask */
337 	sizeof( im_mask_object ),	/* Storage for mask object */
338 	IM_TYPE_OUTPUT | IM_TYPE_ARG,	/* Flags */
339 	mask_init,			/* Init function */
340 	save_imask_dest			/* Save and destroy function */
341 };
342 
343 /* Input imask type.
344  */
345 im_type_desc im__input_imask = {
346 	IM_TYPE_IMASK,			/* It's a mask */
347 	sizeof( im_mask_object ),	/* Storage for mask object */
348 	IM_TYPE_ARG,			/* It requires a command-line arg */
349 	imask_init,			/* Init function */
350 	imask_dest			/* Destroy function */
351 };
352 
353 /* Output dmask to screen type. Set a `print' function to get actual output.
354  * Used for things like "stats".
355  */
356 im_type_desc im__output_dmask_screen = {
357 	IM_TYPE_DMASK,			/* It's a mask */
358 	sizeof( im_mask_object ),	/* Storage for mask object */
359 	IM_TYPE_OUTPUT,			/* It's an output argument */
360 	mask_init,			/* Init function */
361 	dmask_dest			/* Destroy function */
362 };
363 
364 /* Init function for double input.
365  */
366 static int
input_double_init(im_object * obj,char * str)367 input_double_init( im_object *obj, char *str )
368 {
369 	double *d = (double *) *obj;
370 
371 	*d = g_ascii_strtod( str, NULL );
372 
373 	return( 0 );
374 }
375 
376 /* Input double type.
377  */
378 im_type_desc im__input_double = {
379 	IM_TYPE_DOUBLE,			/* It's a double */
380 	sizeof( double ),		/* Memory to allocate */
381 	IM_TYPE_ARG,			/* It requires a command-line arg */
382 	input_double_init,		/* Init function */
383 	NULL				/* Destroy function */
384 };
385 
386 /* im_doublevec_object destroy function.
387  */
388 static int
doublevec_dest(im_object obj)389 doublevec_dest( im_object obj )
390 {
391 	im_doublevec_object *dv = obj;
392 
393 	if( dv->vec ) {
394 		g_free( dv->vec );
395 		dv->vec = NULL;
396 		dv->n = 0;
397 	}
398 
399 	return( 0 );
400 }
401 
402 /* Init function for doublevec input.
403  */
404 static int
input_doublevec_init(im_object * obj,char * str)405 input_doublevec_init( im_object *obj, char *str )
406 {
407 	im_doublevec_object *dv = *obj;
408 	char **strv;
409 	int nargs;
410 	int i;
411 
412 	strv = g_strsplit( str, VEC_SEPS, -1 );
413 	nargs = g_strv_length( strv );
414 
415 	if( !(dv->vec = VIPS_ARRAY( NULL, nargs, double )) ) {
416 		g_strfreev( strv );
417 		return( -1 );
418 	}
419 	dv->n = nargs;
420 
421 	for( i = 0; i < nargs; i++ ) {
422 		dv->vec[i] = g_ascii_strtod( strv[i], NULL );
423 		if( errno ) {
424 			vips_error_system( errno, "input_doublevec_init",
425 				_( "bad double \"%s\"" ), strv[i] );
426 			g_strfreev( strv );
427 			return( -1 );
428 		}
429 	}
430 
431 	g_strfreev( strv );
432 
433 	return( 0 );
434 }
435 
436 /* Input double vector type.
437  */
438 im_type_desc im__input_doublevec = {
439 	IM_TYPE_DOUBLEVEC,		/* It's an array of double */
440 	sizeof( im_doublevec_object ), 	/* Memory to allocate in vec build */
441 	IM_TYPE_ARG,			/* It requires a command-line arg */
442 	input_doublevec_init,		/* Init function */
443 	doublevec_dest			/* Destroy function */
444 };
445 
446 /* Print function for doublevec output.
447  */
448 int
im__dvprint(im_object obj)449 im__dvprint( im_object obj )
450 {
451 	im_doublevec_object *dv = obj;
452 	int i;
453 
454 	for( i = 0; i < dv->n; i++ )
455 		printf( "%G ", dv->vec[i] );
456 	printf( "\n" );
457 
458 	return( 0 );
459 }
460 
461 /* Output double vector type.
462  */
463 im_type_desc im__output_doublevec = {
464 	IM_TYPE_DOUBLEVEC,		/* It's an array of double */
465 	sizeof( im_doublevec_object ), 	/* Memory to allocate in vec build */
466 	IM_TYPE_OUTPUT,			/* Output type */
467 	NULL,				/* Init function */
468 	doublevec_dest			/* Destroy function */
469 };
470 
471 /* im_intvec_object destroy function.
472  */
473 static int
intvec_dest(im_object obj)474 intvec_dest( im_object obj )
475 {
476 	im_intvec_object *iv = obj;
477 
478 	if( iv->vec ) {
479 		g_free( iv->vec );
480 		iv->vec = NULL;
481 		iv->n = 0;
482 	}
483 
484 	return( 0 );
485 }
486 
487 /* Init function for intvec input.
488  */
489 static int
input_intvec_init(im_object * obj,char * str)490 input_intvec_init( im_object *obj, char *str )
491 {
492 	im_intvec_object *iv = *obj;
493 	char **strv;
494 	int nargs;
495 	int i;
496 
497 	strv = g_strsplit( str, VEC_SEPS, -1 );
498 	nargs = g_strv_length( strv );
499 
500 	if( !(iv->vec = VIPS_ARRAY( NULL, nargs, int )) ) {
501 		g_strfreev( strv );
502 		return( -1 );
503 	}
504 	iv->n = nargs;
505 
506 	for( i = 0; i < nargs; i++ ) {
507                 long int val= strtol( strv[i], NULL, 10 );
508 
509 		if( errno ) {
510 			vips_error_system( errno, "input_intvec_init",
511 				_( "bad integer \"%s\"" ), strv[i] );
512 			g_strfreev( strv );
513 			return( -1 );
514 		}
515                 if( INT_MAX < val || INT_MIN > val ) {
516                         vips_error( "input_intvec_init",
517                                 "%ld overflows integer type", val );
518                 }
519 		iv->vec[i] = (int) val;
520 	}
521 
522 	g_strfreev( strv );
523 
524 	return( 0 );
525 }
526 
527 /* Input int vector type.
528  */
529 im_type_desc im__input_intvec = {
530 	IM_TYPE_INTVEC,			/* It's an array of int */
531 	sizeof( im_intvec_object ), 	/* Memory to allocate in vec build */
532 	IM_TYPE_ARG,			/* It requires a command-line arg */
533 	input_intvec_init,		/* Init function */
534 	intvec_dest			/* Destroy function */
535 };
536 
537 /* Print function for intvec output.
538  */
539 int
im__ivprint(im_object obj)540 im__ivprint( im_object obj )
541 {
542 	im_intvec_object *iv = obj;
543 	int i;
544 
545 	for( i = 0; i < iv->n; i++ )
546 		printf( "%d ", iv->vec[i] );
547 	printf( "\n" );
548 
549 	return( 0 );
550 }
551 
552 /* Output int vector type.
553  */
554 im_type_desc im__output_intvec = {
555 	IM_TYPE_INTVEC,			/* It's an array of int */
556 	sizeof( im_intvec_object ), 	/* Memory to allocate in vec build */
557 	IM_TYPE_OUTPUT,			/* Output arg */
558 	(im_init_obj_fn)NULL,		/* Init function */
559 	(im_dest_obj_fn)intvec_dest	/* Destroy function */
560 };
561 
562 /* Init function for int input.
563  */
564 static int
input_int_init(im_object * obj,char * str)565 input_int_init( im_object *obj, char *str )
566 {
567 	int *i = (int *) *obj;
568 
569 	if( sscanf( str, "%d", i ) != 1 ) {
570 		vips_error( "input_int", "%s", _( "bad format" ) );
571 		return( -1 );
572 	}
573 
574 	return( 0 );
575 }
576 
577 /* Input int type.
578  */
579 im_type_desc im__input_int = {
580 	IM_TYPE_INT,			/* It's an int */
581 	sizeof( int ),			/* Memory to allocate */
582 	IM_TYPE_ARG,			/* It requires a command-line arg */
583 	input_int_init,			/* Init function */
584 	NULL				/* Destroy function */
585 };
586 
587 /* Init function for string input.
588  */
589 static int
input_string_init(im_object * obj,char * str)590 input_string_init( im_object *obj, char *str )
591 {
592 	if( !(*obj = (im_object) im_strdup( NULL, str )) )
593 		return( -1 );
594 
595 	return( 0 );
596 }
597 
598 /* Input string type.
599  */
600 im_type_desc im__input_string = {
601 	IM_TYPE_STRING,			/* It's a string */
602 	0, 				/* Memory to allocate */
603 	IM_TYPE_ARG,			/* It requires a command-line arg */
604 	input_string_init,		/* Init function */
605 	vips_free				/* Destroy function */
606 };
607 
608 /* Output string type.
609  */
610 im_type_desc im__output_string = {
611 	IM_TYPE_STRING,			/* It's a string */
612 	0,				/* Memory to allocate */
613 	IM_TYPE_OUTPUT,			/* It's an output argument */
614 	NULL,				/* Init function */
615 	vips_free				/* Destroy function */
616 };
617 
618 /* Output double type.
619  */
620 im_type_desc im__output_double = {
621 	IM_TYPE_DOUBLE,			/* It's a double */
622 	sizeof( double ),		/* Memory to allocate */
623 	IM_TYPE_OUTPUT,			/* It's an output argument */
624 	NULL,				/* Init function */
625 	NULL				/* Destroy function */
626 };
627 
628 /* Output complex type.
629  */
630 im_type_desc im__output_complex = {
631 	IM_TYPE_COMPLEX,		/* It's a complex */
632 	2 * sizeof( double ),		/* Memory to allocate */
633 	IM_TYPE_OUTPUT,			/* It's an output argument */
634 	NULL,				/* Init function */
635 	NULL				/* Destroy function */
636 };
637 
638 /* Output int type.
639  */
640 im_type_desc im__output_int = {
641 	IM_TYPE_INT,			/* It's an int */
642 	sizeof( int ),			/* Memory to allocate */
643 	IM_TYPE_OUTPUT,			/* It's an output argument */
644 	NULL,				/* Init function */
645 	NULL				/* Destroy function */
646 };
647 
648 /* Print function for int output.
649  */
650 int
im__iprint(im_object obj)651 im__iprint( im_object obj )
652 {
653 	int *i = (int *) obj;
654 
655 	printf( "%d\n", *i );
656 
657 	return( 0 );
658 }
659 
660 /* Print function for string output.
661  */
662 int
im__sprint(im_object obj)663 im__sprint( im_object obj )
664 {
665 	char *s = (char *) obj;
666 
667 	printf( "%s\n", s );
668 
669 	return( 0 );
670 }
671 
672 /* Print function for double output.
673  */
674 int
im__dprint(im_object obj)675 im__dprint( im_object obj )
676 {
677 	double *d = (double *) obj;
678 
679 	printf( "%G\n", *d );
680 
681 	return( 0 );
682 }
683 
684 /* Print function for complex output.
685  */
686 int
im__cprint(im_object obj)687 im__cprint( im_object obj )
688 {
689 	double *d = (double *) obj;
690 
691 	printf( "%G %G\n", d[0], d[1] );
692 
693 	return( 0 );
694 }
695 
696 /* Statistics to stdout.
697  */
698 int
im__dmsprint(im_object obj)699 im__dmsprint( im_object obj )
700 {
701 	DOUBLEMASK *mask = ((im_mask_object *) obj)->mask;
702 	double *row;
703 	int i, j;
704 
705 	/* Print statistics band stats eg: 2 bands:b 0,1
706 	 */
707 	printf( "band    minimum     maximum         sum       "
708 		"sum^2        mean   deviation\n" );
709 	for( j = 0; j < mask->ysize; j++ ) {
710 		row = mask->coeff + j * mask->xsize;
711 		if( j == 0 )
712 			printf( "all" );
713 		else
714 			printf( "%2d ", j );
715 
716 		for( i = 0; i < 6; i++ )
717 			printf( "%12g", row[i] );
718 		printf( "\n" );
719 	}
720 
721 	return( 0 );
722 }
723 
724 /* GValue
725  */
726 
727 /* Init function for input gvalue. Just make a string ... will get cast to
728  * whatever later.
729  */
730 static int
input_gvalue_init(im_object * obj,char * str)731 input_gvalue_init( im_object *obj, char *str )
732 {
733 	GValue *value = *obj;
734 
735 	g_value_init( value, G_TYPE_STRING );
736 	g_value_set_string( value, str );
737 
738 	return( 0 );
739 }
740 
741 static int
gvalue_free(im_object obj)742 gvalue_free( im_object obj )
743 {
744 	GValue *value = obj;
745 
746 	/* If it's just zeros (built but not used) we'll get an error if we
747 	 * unset().
748 	 */
749 	if( G_IS_VALUE( value ) )
750 		g_value_unset( value );
751 
752 	return( 0 );
753 }
754 
755 /* Input GValue type.
756  */
757 im_type_desc im__input_gvalue = {
758 	IM_TYPE_GVALUE,
759 	sizeof( GValue ),		/* Need some storage */
760 	IM_TYPE_ARG,			/* It requires a command-line arg */
761 	(im_init_obj_fn) input_gvalue_init,	/* Init function */
762 	(im_dest_obj_fn) gvalue_free 	/* Destroy function */
763 };
764 
765 int
im__gprint(im_object obj)766 im__gprint( im_object obj )
767 {
768 	GValue *value = obj;
769 	char *str_value;
770 
771 	str_value = g_strdup_value_contents( value );
772 	printf( "%s\n", str_value );
773 	g_free( str_value );
774 
775 	return( 0 );
776 }
777 
778 /* Init function for output gvalue. Just init to zero.
779  */
780 static int
output_gvalue_init(im_object * obj)781 output_gvalue_init( im_object *obj )
782 {
783 	GValue *value = *obj;
784 
785 	memset( value, 0, sizeof( GValue ) );
786 
787 	return( 0 );
788 }
789 
790 im_type_desc im__output_gvalue = {
791 	IM_TYPE_GVALUE,
792 	sizeof( GValue ),       	/* Need some storage */
793 	IM_TYPE_OUTPUT,			/* No arg needed (just print) */
794 	(im_init_obj_fn) output_gvalue_init,	/* Init function */
795 	(im_dest_obj_fn) gvalue_free 	/* Destroy function */
796 };
797 
798 /* Init function for input interpolate.
799  *
800  * This is used as a helper function by the C++ interface, so amke it public.
801  */
802 int
vips__input_interpolate_init(im_object * obj,char * str)803 vips__input_interpolate_init( im_object *obj, char *str )
804 {
805 	GType type = g_type_from_name( "VipsInterpolate" );
806 	VipsObjectClass *class = VIPS_OBJECT_CLASS( g_type_class_ref( type ) );
807 	VipsObject *object;
808 
809 	g_assert( class );
810 
811 	if( !(object = vips_object_new_from_string( class, str )) )
812 		return( -1 );
813 	if( vips_object_build( object ) ) {
814 		g_object_unref( object );
815 		return( -1 );
816 	}
817 	*obj = object;
818 
819 	return( 0 );
820 }
821 
822 static int
input_interpolate_dest(im_object obj)823 input_interpolate_dest( im_object obj )
824 {
825 	g_object_unref( (GObject *) obj );
826 
827 	return( 0 );
828 }
829 
830 im_type_desc im__input_interpolate = {
831 	IM_TYPE_INTERPOLATE,
832 	0,      			/* No storage required */
833 	IM_TYPE_ARG,			/* It requires a command-line arg */
834 	vips__input_interpolate_init,	/* Init function */
835 	input_interpolate_dest		/* Destroy function */
836 };
837 
838