1 /* compat stuff for vips7
2  *
3  * 4/3/11
4  * 	- hacked up
5  */
6 
7 /*
8 
9     This file is part of VIPS.
10 
11     VIPS is free software; you can redistribute it and/or modify
12     it under the terms of the GNU Lesser General Public License as published by
13     the Free Software Foundation; either version 2 of the License, or
14     (at your option) any later version.
15 
16     This program is distributed in the hope that it will be useful,
17     but WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     GNU Lesser General Public License for more details.
20 
21     You should have received a copy of the GNU Lesser General Public License
22     along with this program; if not, write to the Free Software
23     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24     02110-1301  USA
25 
26  */
27 
28 /*
29 
30     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
31 
32  */
33 
34 /*
35 #define VIPS_DEBUG
36  */
37 
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif /*HAVE_CONFIG_H*/
41 #include <vips/intl.h>
42 
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <ctype.h>
47 
48 #include <vips/vips.h>
49 #include <vips/vips7compat.h>
50 #include <vips/internal.h>
51 #include <vips/debug.h>
52 #include <vips/vector.h>
53 #include <vips/transform.h>
54 
55 /* Split filename into name / mode components. name and mode should both be
56  * FILENAME_MAX chars.
57  *
58  * We look for the ':' splitting the name and mode by searching for the
59  * rightmost occurrence of the regexp "\.[A-Za-z0-9]+:". The initial dot can
60  * be missing if there's a dirsep or start of string, meaning this is a
61  * filename without an extension.
62  *
63  * Examples:
64  *
65  * 	c:\silly:dir:name\fr:ed.tif:jpeg:95,,,,c:\icc\srgb.icc
66  * 	  -> c:\silly:dir:name\fr:ed.tif  jpeg:95,,,,c:\icc\srgb.icc
67  * 	I180:
68  * 	  -> I180 ""
69  * 	c:\silly:
70  * 	  -> c:\silly ""
71  * 	c:\silly
72  * 	  -> c:\silly ""
73  * 	C:\fixtures\2569067123_aca715a2ee_o.jpg
74  * 	  -> C:\fixtures\2569067123_aca715a2ee_o.jpg ""
75  *
76  * vips8 handles this in a much better way :(
77  */
78 void
im_filename_split(const char * path,char * name,char * mode)79 im_filename_split( const char *path, char *name, char *mode )
80 {
81         char *p;
82 	size_t len;
83 
84         vips_strncpy( name, path, FILENAME_MAX );
85 	strcpy( mode, "" );
86 
87 	if( (len = strlen( name )) == 0 )
88 	       return;
89 
90 	/* Search backwards towards start, stopping at each ':' char.
91 	 */
92 	for( p = name + len - 1; p > name; p -= 1 )
93 		if( *p == ':' ) {
94 			char *q;
95 
96 			/* We are skipping back over the file extension,
97 			 * isalnum() is probably sufficient.
98 			 */
99 			for( q = p - 1; isalnum( *q ) && q > name; q -= 1 )
100 				;
101 
102 			if( *q == '.' ) {
103 				break;
104 			}
105 
106 			/* All the way back to the start? We probably have a
107 			 * filename with no extension, eg. "I180:"
108 			 */
109 			if( q == name )
110 				break;
111 
112 			/* .. or we could hit a dirsep. Allow win or nix
113 			 * separators.
114 			 */
115 			if( *q == '/' ||
116 				*q == '\\' )
117 				break;
118 		}
119 
120 	/* Ignore a ':' in column 1, it's probably a drive letter on a
121 	 * Windows path.
122 	 */
123 	if( *p == ':' &&
124 		p - name != 1 ) {
125                 vips_strncpy( mode, p + 1, FILENAME_MAX );
126                 *p = '\0';
127         }
128 }
129 
130 /**
131  * vips_path_filename7:
132  * @path: path to split
133  *
134  * Return the filename part of a vips7 path. For testing only.
135  */
136 char *
vips_path_filename7(const char * path)137 vips_path_filename7( const char *path )
138 {
139 	char name[FILENAME_MAX];
140 	char mode[FILENAME_MAX];
141 
142 	im_filename_split( path, name, mode );
143 
144 	return( g_strdup( name ) );
145 }
146 
147 /**
148  * vips_path_mode7:
149  * @path: path to split
150  *
151  * Return the mode part of a vips7 path. For testing only.
152  */
153 char *
vips_path_mode7(const char * path)154 vips_path_mode7( const char *path )
155 {
156 	char name[FILENAME_MAX];
157 	char mode[FILENAME_MAX];
158 
159 	im_filename_split( path, name, mode );
160 
161 	return( g_strdup( mode ) );
162 }
163 
164 /* Skip any leading path stuff. Horrible: if this is a filename which came
165  * from win32 and we're a *nix machine, it'll have '\\' not '/' as the
166  * separator :-(
167  *
168  * Try to fudge this ... if the file doesn't contain any of our native
169  * separators, look for the opposite one as well. If there are none of those
170  * either, just return the filename.
171  */
172 const char *
im_skip_dir(const char * path)173 im_skip_dir( const char *path )
174 {
175 	char name[FILENAME_MAX];
176 	char mode[FILENAME_MAX];
177         const char *p;
178         const char *q;
179 
180 	const char native_dir_sep = G_DIR_SEPARATOR;
181 	const char non_native_dir_sep = native_dir_sep == '/' ? '\\' : '/';
182 
183 	/* Remove any trailing save modifiers: we don't want '/' or '\' in the
184 	 * modifier confusing us.
185 	 */
186 	im_filename_split( path, name, mode );
187 
188 	/* The '\0' char at the end of the string.
189 	 */
190 	p = name + strlen( name );
191 
192 	/* Search back for the first native dir sep, or failing that, the first
193 	 * non-native dir sep.
194 	 */
195 	for( q = p; q > name && q[-1] != native_dir_sep; q-- )
196 		;
197 	if( q == name )
198 		for( q = p; q > name && q[-1] != non_native_dir_sep; q-- )
199 			;
200 
201         return( path + (q - name) );
202 }
203 
204 /* Extract suffix from filename, ignoring any mode string. Suffix should be
205  * FILENAME_MAX chars. Include the "." character, if any.
206  */
207 void
im_filename_suffix(const char * path,char * suffix)208 im_filename_suffix( const char *path, char *suffix )
209 {
210 	char name[FILENAME_MAX];
211 	char mode[FILENAME_MAX];
212         char *p;
213 
214 	im_filename_split( path, name, mode );
215         if( (p = strrchr( name, '.' )) )
216                 strcpy( suffix, p );
217         else
218                 strcpy( suffix, "" );
219 }
220 
221 /* Does a filename have one of a set of suffixes. Ignore case.
222  */
223 int
im_filename_suffix_match(const char * path,const char * suffixes[])224 im_filename_suffix_match( const char *path, const char *suffixes[] )
225 {
226 	char suffix[FILENAME_MAX];
227 	const char **p;
228 
229 	im_filename_suffix( path, suffix );
230 	for( p = suffixes; *p; p++ )
231 		if( g_ascii_strcasecmp( suffix, *p ) == 0 )
232 			return( 1 );
233 
234 	return( 0 );
235 }
236 
237 /* p points to the start of a buffer ... move it on through the buffer (ready
238  * for the next call), and return the current option (or NULL for option
239  * missing). ',' characters inside options can be escaped with a '\'.
240  */
241 char *
im_getnextoption(char ** in)242 im_getnextoption( char **in )
243 {
244         char *p;
245         char *q;
246 
247         p = *in;
248         q = p;
249 
250         if( !p || !*p )
251                 return( NULL );
252 
253 	/* Find the next ',' not prefixed with a '\'. If the first character
254 	 * of p is ',', there can't be a previous escape character.
255 	 */
256 	for(;;) {
257 		if( !(p = strchr( p, ',' )) )
258 			break;
259 		if( p == q )
260 			break;
261 		if( p[-1] != '\\' )
262 			break;
263 
264 		p += 1;
265 	}
266 
267         if( p ) {
268                 /* Another option follows this one .. set up to pick that out
269                  * next time.
270                  */
271                 *p = '\0';
272                 *in = p + 1;
273         }
274         else {
275                 /* This is the last one.
276                  */
277                 *in = NULL;
278         }
279 
280         if( strlen( q ) > 0 )
281                 return( q );
282         else
283                 return( NULL );
284 }
285 
286 /* Get a suboption string, or NULL.
287  */
288 char *
im_getsuboption(const char * buf)289 im_getsuboption( const char *buf )
290 {
291         char *p, *q, *r;
292 
293         if( !(p = strchr( buf, ':' )) )
294 		/* No suboption.
295 		 */
296 		return( NULL );
297 
298 	/* Step over the ':'.
299 	 */
300 	p += 1;
301 
302 	/* Need to unescape any \, pairs. Shift stuff down one if we find one.
303 	 */
304 	for( q = p; *q; q++ )
305 		if( q[0] == '\\' && q[1] == ',' )
306 			for( r = q; *r; r++ )
307 				r[0] = r[1];
308 
309         return( p );
310 }
311 
312 VipsImage *
im_open(const char * filename,const char * mode)313 im_open( const char *filename, const char *mode )
314 {
315 	VipsImage *image;
316 
317 	vips_check_init();
318 
319 	/* We have to go via the old VipsFormat system so we can support the
320 	 * "filename:option" syntax.
321 	 *
322 	 * Use "rs" to turn on seq mode.
323 	 */
324 	if( strcmp( mode, "r" ) == 0 ||
325 		strcmp( mode, "rd" ) == 0 ) {
326 		if( !(image = vips__deprecated_open_read( filename, FALSE )) )
327 			return( NULL );
328 	}
329 	else if( strcmp( mode, "rs" ) == 0 ) {
330 		if( !(image = vips__deprecated_open_read( filename, TRUE )) )
331 			return( NULL );
332 	}
333 	else if( strcmp( mode, "w" ) == 0 ) {
334 		if( !(image = vips__deprecated_open_write( filename )) )
335 			return( NULL );
336 	}
337 	else {
338 		if( !(image = vips_image_new_mode( filename, mode )) )
339 			return( NULL );
340 	}
341 
342 	return( image );
343 }
344 
345 /* Just for compatibility. New code should use vips_object_local() directly.
346  */
347 VipsImage *
im_open_local(VipsImage * parent,const char * filename,const char * mode)348 im_open_local( VipsImage *parent,
349 	const char *filename, const char *mode )
350 {
351 	VipsImage *image;
352 
353 	if( !(image = im_open( filename, mode )) )
354 		return( NULL );
355 	vips_object_local( parent, image );
356 
357 	return( image );
358 }
359 
360 /* Just for compatibility. New code should use vips_object_local_array().
361  */
362 int
im_open_local_array(VipsImage * parent,VipsImage ** images,int n,const char * filename,const char * mode)363 im_open_local_array( VipsImage *parent,
364 	VipsImage **images, int n,
365 	const char *filename, const char *mode )
366 {
367 	int i;
368 
369 	for( i = 0; i < n; i++ )
370 		if( !(images[i] = im_open_local( parent, filename, mode )) )
371 			return( -1 );
372 
373 	return( 0 );
374 }
375 
376 typedef struct {
377 	im_callback_fn fn;
378 	void *a;
379 	void *b;
380 } Callback;
381 
382 static void
im_add_callback_cb(VipsImage * im,Callback * callback)383 im_add_callback_cb( VipsImage *im, Callback *callback )
384 {
385 	if( callback->fn( callback->a, callback->b ) )
386 		vips_image_set_kill( im, TRUE );
387 }
388 
389 int
im_add_callback(VipsImage * im,const char * name,im_callback_fn fn,void * a,void * b)390 im_add_callback( VipsImage *im,
391 	const char *name, im_callback_fn fn, void *a, void *b )
392 {
393 	Callback *callback;
394 
395 	callback = VIPS_NEW( VIPS_OBJECT( im ), Callback );
396 	callback->fn = fn;
397 	callback->a = a;
398 	callback->b = b;
399 	g_signal_connect( im, name,
400 		G_CALLBACK( im_add_callback_cb ), callback );
401 
402 	return( 0 );
403 }
404 
405 static void
im_add_callback_cb1(VipsImage * im,void * x,Callback * callback)406 im_add_callback_cb1( VipsImage *im, void *x, Callback *callback )
407 {
408 	if( callback->fn( callback->a, callback->b ) )
409 		vips_image_set_kill( im, TRUE );
410 }
411 
412 int
im_add_callback1(VipsImage * im,const char * name,im_callback_fn fn,void * a,void * b)413 im_add_callback1( VipsImage *im,
414 	const char *name, im_callback_fn fn, void *a, void *b )
415 {
416 	Callback *callback;
417 
418 	callback = VIPS_NEW( VIPS_OBJECT( im ), Callback );
419 	callback->fn = fn;
420 	callback->a = a;
421 	callback->b = b;
422 	g_signal_connect( im, name,
423 		G_CALLBACK( im_add_callback_cb1 ), callback );
424 
425 	return( 0 );
426 }
427 
428 /* Make something local to an image descriptor ... pass in a constructor
429  * and a destructor, plus three args.
430  */
431 void *
im_local(IMAGE * im,im_construct_fn cons,im_callback_fn dest,void * a,void * b,void * c)432 im_local( IMAGE *im,
433 	im_construct_fn cons, im_callback_fn dest, void *a, void *b, void *c )
434 {
435 	void *obj;
436 
437 	if( !im ) {
438 		im_error( "im_local", "%s", _( "NULL image descriptor" ) );
439 		return( NULL );
440 	}
441 
442         if( !(obj = cons( a, b, c )) )
443                 return( NULL );
444         if( im_add_close_callback( im, (im_callback_fn) dest, obj, a ) ) {
445                 dest( obj, a );
446                 return( NULL );
447         }
448 
449         return( obj );
450 }
451 
452 /* Make an array of things local to a descriptor ... eg. make 6 local temp
453  * images.
454  */
455 int
im_local_array(IMAGE * im,void ** out,int n,im_construct_fn cons,im_callback_fn dest,void * a,void * b,void * c)456 im_local_array( IMAGE *im, void **out, int n,
457 	im_construct_fn cons, im_callback_fn dest, void *a, void *b, void *c )
458 {
459 	int i;
460 
461 	for( i = 0; i < n; i++ )
462 		if( !(out[i] = im_local( im, cons, dest, a, b, c )) )
463 			return( -1 );
464 
465 	return( 0 );
466 }
467 
468 int
im_close(VipsImage * im)469 im_close( VipsImage *im )
470 {
471 	g_object_unref( im );
472 
473 	return( 0 );
474 }
475 
476 /* edvips.c needs this
477  */
478 VipsImage *
im_init(const char * filename)479 im_init( const char *filename )
480 {
481 	VipsImage *image;
482 
483 	image = vips_image_new();
484 	IM_SETSTR( image->filename, filename );
485 
486 	return( image );
487 }
488 
489 /* We can't do this with a rename macro since the C++ interface needs
490  * this entrypoint, see VImage.h.
491  *
492  * As a result our fancy ABI check will not work with the vips7 interface.
493  */
494 int
im_init_world(const char * argv0)495 im_init_world( const char *argv0 )
496 {
497 	return( vips_init( argv0 ) );
498 }
499 
500 /* Prettyprint various header fields. Just for vips7 compat, use
501  * vips_enum_value() instead.
502  */
im_Type2char(VipsInterpretation type)503 const char *im_Type2char( VipsInterpretation type )
504 	{ return( vips_enum_string( VIPS_TYPE_INTERPRETATION, type ) ); }
im_BandFmt2char(VipsBandFormat format)505 const char *im_BandFmt2char( VipsBandFormat format )
506 	{ return( vips_enum_string( VIPS_TYPE_BAND_FORMAT, format ) ); }
im_Coding2char(VipsCoding coding)507 const char *im_Coding2char( VipsCoding coding )
508 	{ return( vips_enum_string( VIPS_TYPE_CODING, coding ) ); }
im_dtype2char(VipsImageType n)509 const char *im_dtype2char( VipsImageType n )
510 	{ return( vips_enum_string( VIPS_TYPE_IMAGE_TYPE, n ) ); }
im_dhint2char(VipsDemandStyle style)511 const char *im_dhint2char( VipsDemandStyle style )
512 	{ return( vips_enum_string( VIPS_TYPE_DEMAND_STYLE, style ) ); }
513 
514 /* Old names for enums, for compat.
515  */
516 static const char *im_Type[] = {
517 	"IM_TYPE_MULTIBAND", 		/* 0 */
518 	"IM_TYPE_B_W", 			/* 1 */
519 	"LUMINACE", 			/* 2 */
520 	"XRAY", 			/* 3 */
521 	"IR", 				/* 4 */
522 	"YUV", 				/* 5 */
523 	"RED_ONLY", 			/* 6 */
524 	"GREEN_ONLY", 			/* 7 */
525 	"BLUE_ONLY", 			/* 8 */
526 	"POWER_SPECTRUM", 		/* 9 */
527 	"IM_TYPE_HISTOGRAM", 		/* 10 */
528 	"LUT", 				/* 11 */
529 	"IM_TYPE_XYZ",			/* 12 */
530 	"IM_TYPE_LAB", 			/* 13 */
531 	"CMC", 				/* 14 */
532 	"IM_TYPE_CMYK", 		/* 15 */
533 	"IM_TYPE_LABQ", 		/* 15 */
534 	"IM_TYPE_RGB", 			/* 17 */
535 	"IM_TYPE_UCS", 			/* 18 */
536 	"IM_TYPE_LCH", 			/* 19 */
537 	"IM_TYPE_LABS",			/* 20 */
538 	"<unknown>", 			/* 21 */
539 	"IM_TYPE_sRGB", 		/* 22 */
540 	"IM_TYPE_YXY", 			/* 23 */
541 	"IM_TYPE_FOURIER",		/* 24 */
542 	"IM_TYPE_RGB16",		/* 25 */
543 	"IM_TYPE_GREY16",		/* 26 */
544 	NULL
545 };
546 
547 static const char *im_BandFmt[] = {
548 	"IM_BANDFMT_UCHAR",
549 	"IM_BANDFMT_CHAR",
550 	"IM_BANDFMT_USHORT",
551 	"IM_BANDFMT_SHORT",
552 	"IM_BANDFMT_UINT",
553 	"IM_BANDFMT_INT",
554 	"IM_BANDFMT_FLOAT",
555 	"IM_BANDFMT_COMPLEX",
556 	"IM_BANDFMT_DOUBLE",
557 	"IM_BANDFMT_DPCOMPLEX",
558 	NULL
559 };
560 
561 static const char *im_Coding[] = {
562 	"IM_CODING_NONE",
563 	"COLQUANT8",
564 	"IM_CODING_LABQ",
565 	"IM_CODING_LABQ_COMPRESSED",
566 	"RGB_COMPRESSED",
567 	"LUM_COMPRESSED",
568 	"IM_CODING_RAD",
569 	NULL
570 };
571 
572 static const char *im_dtype[] = {
573 	"IM_NONE",
574 	"IM_SETBUF",
575 	"IM_SETBUF_FOREIGN",
576 	"IM_OPENIN",
577 	"IM_MMAPIN",
578 	"IM_MMAPINRW",
579 	"IM_OPENOUT",
580 	"IM_PARTIAL",
581 	NULL
582 };
583 
584 static const char *im_dhint[] = {
585 	"IM_SMALLTILE",
586 	"IM_FATSTRIP",
587 	"IM_THINSTRIP",
588 	"IM_ANY",
589 	NULL
590 };
591 
592 /* enum string to int, try the GEnum first, then use a compat *char[] for old
593  * names.
594  */
595 static int
lookup_enum(GType type,const char * names[],const char * name)596 lookup_enum( GType type, const char *names[], const char *name )
597 {
598 	GEnumClass *class;
599 	GEnumValue *value;
600 	int i;
601 
602 	class = g_type_class_ref( type );
603 	if( (value = g_enum_get_value_by_nick( class, name )) )
604 		return( value->value );
605 	if( (value = g_enum_get_value_by_name( class, name )) )
606 		return( value->value );
607 
608 	for( i = 0; names[i]; i++ )
609 		if( g_ascii_strcasecmp( names[i], name ) == 0 )
610 			return( i );
611 
612 	return( -1 );
613 }
614 
im_char2Type(const char * str)615 VipsInterpretation im_char2Type( const char *str )
616 	{ return( lookup_enum( VIPS_TYPE_INTERPRETATION, im_Type, str ) ); }
im_char2BandFmt(const char * str)617 VipsBandFormat im_char2BandFmt( const char *str )
618 	{ return( lookup_enum( VIPS_TYPE_BAND_FORMAT, im_BandFmt, str ) ); }
im_char2Coding(const char * str)619 VipsCoding im_char2Coding( const char *str )
620 	{ return( lookup_enum( VIPS_TYPE_CODING, im_Coding, str ) ); }
im_char2dtype(const char * str)621 VipsImageType im_char2dtype( const char *str )
622 	{ return( lookup_enum( VIPS_TYPE_IMAGE_TYPE, im_dtype, str ) ); }
im_char2dhint(const char * str)623 VipsDemandStyle im_char2dhint( const char *str )
624 	{ return( lookup_enum( VIPS_TYPE_DEMAND_STYLE, im_dhint, str ) ); }
625 
626 /* Totally useless now.
627  */
im_Compression2char(int n)628 const char *im_Compression2char( int n ) { return( "NONE" ); }
im_char2Compression(const char * str)629 int im_char2Compression( const char *str ) { return( -1 ); }
630 
631 /* Wrap one / many is being replaced by a class thing.
632  */
633 
634 typedef struct {
635 	im_wrapmany_fn fn;	/* Function we call */
636 	void *a, *b;		/* User values for function */
637 } Bundle;
638 
639 /* Maximum number of input images -- why not?
640  */
641 #define MAX_INPUT_IMAGES (64)
642 
643 /* Convert a VipsRegion.
644  */
645 static int
process_region(VipsRegion * or,void * seq,void * a,void * b)646 process_region( VipsRegion *or, void *seq, void *a, void *b )
647 {
648 	VipsRegion **ir = (VipsRegion **) seq;
649 	Bundle *bun = (Bundle *) b;
650 
651 	PEL *p[MAX_INPUT_IMAGES], *q;
652 	int i, y;
653 
654 	/* Prepare all input regions and make buffer pointers.
655 	 */
656 	if( vips_reorder_prepare_many( or->im, ir, &or->valid ) )
657 		return( -1 );
658 	for( i = 0; ir[i]; i++ )
659 		p[i] = (PEL *) VIPS_REGION_ADDR( ir[i],
660 			or->valid.left, or->valid.top );
661 	p[i] = NULL;
662 	q = (PEL *) VIPS_REGION_ADDR( or, or->valid.left, or->valid.top );
663 
664 	/* Convert linewise.
665 	 */
666 	for( y = 0; y < or->valid.height; y++ ) {
667 		PEL *p1[MAX_INPUT_IMAGES];
668 
669 		/* Make a copy of p[] which the buffer function can mess up if
670 		 * it wants.
671 		 */
672 		for( i = 0; ir[i]; i++ )
673 			p1[i] = p[i];
674 
675 		/* Bizarre double-cast stops a bogus gcc 4.1 compiler warning.
676 		 */
677 		bun->fn( (void **) ((void *)p1), q,
678 			or->valid.width, bun->a, bun->b );
679 
680 		/* Move pointers on.
681 		 */
682 		for( i = 0; ir[i]; i++ )
683 			p[i] += VIPS_REGION_LSKIP( ir[i] );
684 		q += VIPS_REGION_LSKIP( or );
685 	}
686 
687 	return( 0 );
688 }
689 
690 /* Make a copy of an array of input images.
691  */
692 static IMAGE **
dupims(IMAGE * out,IMAGE ** in)693 dupims( IMAGE *out, IMAGE **in )
694 {
695 	IMAGE **new;
696 	int i, n;
697 
698 	for( n = 0; in[n]; n++ )
699 		;
700 	new = VIPS_ARRAY( VIPS_OBJECT( out ), n + 1, IMAGE * );
701 	for( i = 0; i < n; i++ )
702 		new[i] = in[i];
703 	new[n] = NULL;
704 
705 	return( new );
706 }
707 
708 int
im_wrapmany(IMAGE ** in,IMAGE * out,im_wrapmany_fn fn,void * a,void * b)709 im_wrapmany( IMAGE **in, IMAGE *out, im_wrapmany_fn fn, void *a, void *b )
710 {
711 	Bundle *bun;
712 	int i, n;
713 
714 	/* Count input images.
715 	 */
716 	for( n = 0; in[n]; n++ )
717 		;
718 	if( n >= MAX_INPUT_IMAGES - 1 ) {
719 		vips_error( "im_wrapmany", "%s", _( "too many input images" ) );
720 		return( -1 );
721 	}
722 
723 	/* Save args.
724 	 */
725 	bun = VIPS_NEW( VIPS_OBJECT( out ), Bundle );
726 	if( !(in = dupims( out, in )) )
727 		return( -1 );
728 	bun->fn = fn;
729 	bun->a = a;
730 	bun->b = b;
731 
732 	/* Check descriptors --- make sure that our caller has done this
733 	 * correctly.
734 	 */
735 	for( i = 0; i < n; i++ ) {
736 		if( in[i]->Xsize != out->Xsize || in[i]->Ysize != out->Ysize ) {
737 			vips_error( "im_wrapmany",
738 				"%s", _( "descriptors differ in size" ) );
739 			return( -1 );
740 		}
741 
742 		/* Check io style.
743 		 */
744 		if( vips_image_pio_input( in[i] ) )
745 			return( -1 );
746 	}
747 
748 	/* Don't call vips_image_pipeline_array(), we don't want to copy
749 	 * fields.
750 	 */
751 	vips__demand_hint_array( out, VIPS_DEMAND_STYLE_THINSTRIP, in );
752 	if( vips__reorder_set_input( out, in ) )
753 		return( -1 );
754 
755 	/* Generate!
756 	 */
757 	if( vips_image_generate( out,
758 		vips_start_many, (VipsGenerateFn) process_region,
759 		vips_stop_many, in, bun ) )
760 		return( -1 );
761 
762 	return( 0 );
763 }
764 
765 static void
wrapone_gen(void ** ins,void * out,int width,Bundle * bun,void * dummy)766 wrapone_gen( void **ins, void *out, int width, Bundle *bun, void *dummy )
767 {
768 	((im_wrapone_fn) (bun->fn)) (ins[0], out, width, bun->a, bun->b );
769 }
770 
771 int
im_wrapone(IMAGE * in,IMAGE * out,im_wrapone_fn fn,void * a,void * b)772 im_wrapone( IMAGE *in, IMAGE *out, im_wrapone_fn fn, void *a, void *b )
773 {
774 	Bundle *bun;
775 	IMAGE *invec[2];
776 
777 	/* Heh, yuk. We cast back above.
778 	 */
779 	bun = VIPS_NEW( VIPS_OBJECT( out ), Bundle );
780 	bun->fn = (im_wrapmany_fn) fn;
781 	bun->a = a;
782 	bun->b = b;
783 	invec[0] = in; invec[1] = NULL;
784 
785 	return( im_wrapmany( invec, out,
786 		(im_wrapmany_fn) wrapone_gen, bun, NULL ) );
787 }
788 
789 static void
wraptwo_gen(void ** ins,void * out,int width,Bundle * bun,void * dummy)790 wraptwo_gen( void **ins, void *out, int width, Bundle *bun, void *dummy )
791 {
792 	((im_wraptwo_fn) (bun->fn)) (ins[0], ins[1], out,
793 		width, bun->a, bun->b );
794 }
795 
796 int
im_wraptwo(IMAGE * in1,IMAGE * in2,IMAGE * out,im_wraptwo_fn fn,void * a,void * b)797 im_wraptwo( IMAGE *in1, IMAGE *in2, IMAGE *out,
798 	im_wraptwo_fn fn, void *a, void *b )
799 {
800 	Bundle *bun;
801 	IMAGE *invec[3];
802 
803 	bun = VIPS_NEW( VIPS_OBJECT( out ), Bundle );
804 	bun->fn = (im_wrapmany_fn) fn;
805 	bun->a = a;
806 	bun->b = b;
807 	invec[0] = in1; invec[1] = in2; invec[2] = NULL;
808 
809 	return( im_wrapmany( invec, out,
810 		(im_wrapmany_fn) wraptwo_gen, bun, NULL ) );
811 }
812 
813 /* Save a bit of typing.
814  */
815 #define UC IM_BANDFMT_UCHAR
816 #define C IM_BANDFMT_CHAR
817 #define US IM_BANDFMT_USHORT
818 #define S IM_BANDFMT_SHORT
819 #define UI IM_BANDFMT_UINT
820 #define I IM_BANDFMT_INT
821 #define F IM_BANDFMT_FLOAT
822 #define X IM_BANDFMT_COMPLEX
823 #define D IM_BANDFMT_DOUBLE
824 #define DX IM_BANDFMT_DPCOMPLEX
825 
826 /* For two integer types, the "largest", ie. one which can represent the
827  * full range of both.
828  */
829 static int bandfmt_largest[6][6] = {
830         /* UC  C   US  S   UI  I */
831 /* UC */ { UC, S,  US, S,  UI, I },
832 /* C */  { S,  C,  I,  S,  I,  I },
833 /* US */ { US, I,  US, I,  UI, I },
834 /* S */  { S,  S,  I,  S,  I,  I },
835 /* UI */ { UI, I,  UI, I,  UI, I },
836 /* I */  { I,  I,  I,  I,  I,  I }
837 };
838 
839 /* For two formats, find one which can represent the full range of both.
840  */
841 static VipsBandFmt
im__format_common(VipsBandFmt in1,VipsBandFmt in2)842 im__format_common( VipsBandFmt in1, VipsBandFmt in2 )
843 {
844 	if( vips_band_format_iscomplex( in1 ) ||
845 		vips_band_format_iscomplex( in2 ) ) {
846 		/* What kind of complex?
847 		 */
848 		if( in1 == IM_BANDFMT_DPCOMPLEX || in2 == IM_BANDFMT_DPCOMPLEX )
849 			/* Output will be DPCOMPLEX.
850 			 */
851 			return( IM_BANDFMT_DPCOMPLEX );
852 		else
853 			return( IM_BANDFMT_COMPLEX );
854 
855 	}
856 	else if( vips_bandfmt_isfloat( in1 ) ||
857 		vips_bandfmt_isfloat( in2 ) ) {
858 		/* What kind of float?
859 		 */
860 		if( in1 == IM_BANDFMT_DOUBLE || in2 == IM_BANDFMT_DOUBLE )
861 			return( IM_BANDFMT_DOUBLE );
862 		else
863 			return( IM_BANDFMT_FLOAT );
864 	}
865 	else
866 		/* Must be int+int -> int.
867 		 */
868 		return( bandfmt_largest[in1][in2] );
869 }
870 
871 int
im__formatalike_vec(IMAGE ** in,IMAGE ** out,int n)872 im__formatalike_vec( IMAGE **in, IMAGE **out, int n )
873 {
874 	int i;
875 	VipsBandFmt fmt;
876 
877 	g_assert( n >= 1 );
878 
879 	fmt = in[0]->BandFmt;
880 	for( i = 1; i < n; i++ )
881 		fmt = im__format_common( fmt, in[i]->BandFmt );
882 
883 	for( i = 0; i < n; i++ )
884 		if( im_clip2fmt( in[i], out[i], fmt ) )
885 			return( -1 );
886 
887 	return( 0 );
888 }
889 
890 int
im__formatalike(IMAGE * in1,IMAGE * in2,IMAGE * out1,IMAGE * out2)891 im__formatalike( IMAGE *in1, IMAGE *in2, IMAGE *out1, IMAGE *out2 )
892 {
893 	IMAGE *in[2];
894 	IMAGE *out[2];
895 
896 	in[0] = in1;
897 	in[1] = in2;
898 	out[0] = out1;
899 	out[1] = out2;
900 
901 	return( im__formatalike_vec( in, out, 2 ) );
902 }
903 
904 /* Make an n-band image. Input 1 or n bands.
905  */
906 int
im__bandup(const char * domain,IMAGE * in,IMAGE * out,int n)907 im__bandup( const char *domain, IMAGE *in, IMAGE *out, int n )
908 {
909 	IMAGE *bands[256];
910 	int i;
911 
912 	if( in->Bands == n )
913 		return( vips_image_write( in, out ) );
914 	if( in->Bands != 1 ) {
915 		im_error( domain, _( "not one band or %d bands" ), n );
916 		return( -1 );
917 	}
918 	if( n > 256 || n < 1 ) {
919 		im_error( domain, "%s", _( "bad bands" ) );
920 		return( -1 );
921 	}
922 
923 	for( i = 0; i < n; i++ )
924 		bands[i] = in;
925 
926 	return( im_gbandjoin( bands, out, n ) );
927 }
928 
929 int
im__bandalike_vec(const char * domain,IMAGE ** in,IMAGE ** out,int n)930 im__bandalike_vec( const char *domain, IMAGE **in, IMAGE **out, int n )
931 {
932 	int i;
933 	int max_bands;
934 
935 	g_assert( n >= 1 );
936 
937 	max_bands = in[0]->Bands;
938 	for( i = 1; i < n; i++ )
939 		max_bands = IM_MAX( max_bands, in[i]->Bands );
940 	for( i = 0; i < n; i++ )
941 		if( im__bandup( domain, in[i], out[i], max_bands ) )
942 			return( -1 );
943 
944 	return( 0 );
945 }
946 
947 int
im__bandalike(const char * domain,IMAGE * in1,IMAGE * in2,IMAGE * out1,IMAGE * out2)948 im__bandalike( const char *domain,
949 	IMAGE *in1, IMAGE *in2, IMAGE *out1, IMAGE *out2 )
950 {
951 	IMAGE *in[2];
952 	IMAGE *out[2];
953 
954 	in[0] = in1;
955 	in[1] = in2;
956 	out[0] = out1;
957 	out[1] = out2;
958 	if( im__bandalike_vec( domain, in, out, 2 ) )
959 		return( -1 );
960 
961 	return( 0 );
962 }
963 
964 VipsVector *
im__init_program(VipsVector * vectors[IM_BANDFMT_LAST],VipsBandFmt format_table[IM_BANDFMT_LAST],VipsBandFmt fmt)965 im__init_program( VipsVector *vectors[IM_BANDFMT_LAST],
966 	VipsBandFmt format_table[IM_BANDFMT_LAST], VipsBandFmt fmt )
967 {
968 	int isize = im__sizeof_bandfmt[fmt];
969 	int osize = im__sizeof_bandfmt[format_table[fmt]];
970 
971 	VipsVector *v;
972 
973 	v = vips_vector_new( "binary arith", osize );
974 
975 	vips_vector_source_name( v, "s1", isize );
976 	vips_vector_source_name( v, "s2", isize );
977 	vips_vector_temporary( v, "t1", osize );
978 	vips_vector_temporary( v, "t2", osize );
979 
980 	vectors[fmt] = v;
981 
982 	return( v );
983 }
984 
985 void
im__compile_programs(VipsVector * vectors[IM_BANDFMT_LAST])986 im__compile_programs( VipsVector *vectors[IM_BANDFMT_LAST] )
987 {
988 	int fmt;
989 
990 	for( fmt = 0; fmt < IM_BANDFMT_LAST; fmt++ ) {
991 		if( vectors[fmt] &&
992 			!vips_vector_compile( vectors[fmt] ) )
993 			IM_FREEF( vips_vector_free, vectors[fmt] );
994 	}
995 
996 #ifdef DEBUG
997 	printf( "im__compile_programs: " );
998 	for( fmt = 0; fmt < IM_BANDFMT_LAST; fmt++ )
999 		if( vectors[fmt] )
1000 			printf( "%s ", im_BandFmt2char( fmt ) );
1001 	printf( "\n" );
1002 #endif /*DEBUG*/
1003 }
1004 
1005 int
im_add(IMAGE * in1,IMAGE * in2,IMAGE * out)1006 im_add( IMAGE *in1, IMAGE *in2, IMAGE *out )
1007 {
1008 	VipsImage *x;
1009 
1010 	if( vips_call( "add", in1, in2, &x, NULL ) )
1011 		return( -1 );
1012 	if( vips_image_write( x, out ) ) {
1013 		g_object_unref( x );
1014 		return( -1 );
1015 	}
1016 	g_object_unref( x );
1017 
1018 	return( 0 );
1019 }
1020 
1021 int
im_subtract(IMAGE * in1,IMAGE * in2,IMAGE * out)1022 im_subtract( IMAGE *in1, IMAGE *in2, IMAGE *out )
1023 {
1024 	VipsImage *x;
1025 
1026 	if( vips_call( "subtract", in1, in2, &x, NULL ) )
1027 		return( -1 );
1028 	if( vips_image_write( x, out ) ) {
1029 		g_object_unref( x );
1030 		return( -1 );
1031 	}
1032 	g_object_unref( x );
1033 
1034 	return( 0 );
1035 }
1036 
1037 int
im_multiply(IMAGE * in1,IMAGE * in2,IMAGE * out)1038 im_multiply( IMAGE *in1, IMAGE *in2, IMAGE *out )
1039 {
1040 	VipsImage *x;
1041 
1042 	if( vips_call( "multiply", in1, in2, &x, NULL ) )
1043 		return( -1 );
1044 	if( vips_image_write( x, out ) ) {
1045 		g_object_unref( x );
1046 		return( -1 );
1047 	}
1048 	g_object_unref( x );
1049 
1050 	return( 0 );
1051 }
1052 
1053 int
im_divide(IMAGE * in1,IMAGE * in2,IMAGE * out)1054 im_divide( IMAGE *in1, IMAGE *in2, IMAGE *out )
1055 {
1056 	VipsImage *x;
1057 
1058 	if( vips_call( "divide", in1, in2, &x, NULL ) )
1059 		return( -1 );
1060 	if( vips_image_write( x, out ) ) {
1061 		g_object_unref( x );
1062 		return( -1 );
1063 	}
1064 	g_object_unref( x );
1065 
1066 	return( 0 );
1067 }
1068 
1069 int
im_avg(IMAGE * in,double * out)1070 im_avg( IMAGE *in, double *out )
1071 {
1072 	return( vips_avg( in, out, NULL ) );
1073 }
1074 
1075 int
im_deviate(IMAGE * in,double * out)1076 im_deviate( IMAGE *in, double *out )
1077 {
1078 	return( vips_deviate( in, out, NULL ) );
1079 }
1080 
im_generate(VipsImage * im,im_start_fn start,im_generate_fn generate,im_stop_fn stop,void * a,void * b)1081 int im_generate( VipsImage *im,
1082 	im_start_fn start, im_generate_fn generate, im_stop_fn stop,
1083 	void *a, void *b )
1084 {
1085 	return( vips_image_generate( im,
1086 		start, (VipsGenerateFn) generate, stop, a, b ) );
1087 }
1088 
1089 int
im_minpos(IMAGE * in,int * xpos,int * ypos,double * out)1090 im_minpos( IMAGE *in, int *xpos, int *ypos, double *out )
1091 {
1092 	return( vips_min( in, out, "x", xpos, "y", ypos, NULL ) );
1093 }
1094 
1095 int
im_min(IMAGE * in,double * out)1096 im_min( IMAGE *in, double *out )
1097 {
1098 	return( im_minpos( in, NULL, NULL, out ) );
1099 }
1100 
1101 int
im_maxpos(IMAGE * in,int * xpos,int * ypos,double * out)1102 im_maxpos( IMAGE *in, int *xpos, int *ypos, double *out )
1103 {
1104 	return( vips_max( in, out, "x", xpos, "y", ypos, NULL ) );
1105 }
1106 
1107 int
im_max(IMAGE * in,double * out)1108 im_max( IMAGE *in, double *out )
1109 {
1110 	return( im_maxpos( in, NULL, NULL, out ) );
1111 }
1112 
1113 #define MAX_IMAGES 100
1114 int
im_demand_hint(IMAGE * im,VipsDemandStyle hint,...)1115 im_demand_hint (IMAGE * im, VipsDemandStyle hint, ...)
1116 {
1117   va_list ap;
1118   int i;
1119   IMAGE *ar[MAX_IMAGES];
1120 
1121   va_start (ap, hint);
1122   for (i = 0; i < MAX_IMAGES && (ar[i] = va_arg (ap, IMAGE *)); i++)
1123     ;
1124   va_end (ap);
1125   if (i == MAX_IMAGES)
1126     {
1127       im_error ("im_demand_hint", "%s", _("too many images"));
1128       return (-1);
1129     }
1130 
1131   vips__demand_hint_array (im, hint, ar);
1132 
1133   return (0);
1134 }
1135 
1136 int
im_cp_descv(IMAGE * im,...)1137 im_cp_descv (IMAGE * im, ...)
1138 {
1139   va_list ap;
1140   int i;
1141   IMAGE *ar[MAX_IMAGES];
1142 
1143   va_start (ap, im);
1144   for (i = 0; i < MAX_IMAGES && (ar[i] = va_arg (ap, IMAGE *)); i++)
1145     ;
1146   va_end (ap);
1147   if (i == MAX_IMAGES)
1148     {
1149       im_error ("im_cp_descv", "%s", _("too many images"));
1150       return (-1);
1151     }
1152 
1153   return (vips__image_copy_fields_array (im, ar));
1154 }
1155 
1156 int
im_cp_desc(IMAGE * out,IMAGE * in)1157 im_cp_desc(IMAGE *out, IMAGE *in )
1158 {
1159 	return( im_cp_descv( out, in, NULL));
1160 }
1161 
1162 int
im_copy_set(IMAGE * in,IMAGE * out,VipsType type,float xres,float yres,int xoffset,int yoffset)1163 im_copy_set( IMAGE *in, IMAGE *out,
1164 	VipsType type, float xres, float yres, int xoffset, int yoffset )
1165 {
1166 	VipsImage *x;
1167 
1168 	if( vips_copy( in, &x,
1169 		"interpretation", type,
1170 		"xres", xres,
1171 		"yres", yres,
1172 		"xoffset", xoffset,
1173 		"yoffset", yoffset,
1174 		NULL ) )
1175 		return( -1 );
1176 	if( vips_image_write( x, out ) ) {
1177 		g_object_unref( x );
1178 		return( -1 );
1179 	}
1180 	g_object_unref( x );
1181 
1182 	return( 0 );
1183 }
1184 
1185 int
im_copy_morph(IMAGE * in,IMAGE * out,int bands,VipsBandFmt bandfmt,VipsCoding coding)1186 im_copy_morph( IMAGE *in, IMAGE *out,
1187 	int bands, VipsBandFmt bandfmt, VipsCoding coding )
1188 {
1189 	VipsImage *x;
1190 
1191 	if( vips_copy( in, &x,
1192 		"bands", bands,
1193 		"format", bandfmt,
1194 		"coding", coding,
1195 		NULL ) )
1196 		return( -1 );
1197 	if( vips_image_write( x, out ) ) {
1198 		g_object_unref( x );
1199 		return( -1 );
1200 	}
1201 	g_object_unref( x );
1202 
1203 	return( 0 );
1204 }
1205 
1206 int
im_copy(IMAGE * in,IMAGE * out)1207 im_copy( IMAGE *in, IMAGE *out )
1208 {
1209 	return( vips_image_write( in, out ) );
1210 }
1211 
1212 int
im_copy_swap(IMAGE * in,IMAGE * out)1213 im_copy_swap( IMAGE *in, IMAGE *out )
1214 {
1215 	VipsImage *x;
1216 
1217 	if( vips_byteswap( in, &x, NULL ) )
1218 		return( -1 );
1219 	if( vips_image_write( x, out ) ) {
1220 		g_object_unref( x );
1221 		return( -1 );
1222 	}
1223 	g_object_unref( x );
1224 
1225 	return( 0 );
1226 }
1227 
1228 int
im_copy_set_meta(IMAGE * in,IMAGE * out,const char * field,GValue * value)1229 im_copy_set_meta( IMAGE *in, IMAGE *out, const char *field, GValue *value )
1230 {
1231 	if( vips_image_write( in, out ) )
1232 		return( -1 );
1233 	(void) im_meta_set( out, field, value );
1234 
1235 	return( 0 );
1236 }
1237 
1238 int
im_copy_native(IMAGE * in,IMAGE * out,gboolean is_msb_first)1239 im_copy_native( IMAGE *in, IMAGE *out, gboolean is_msb_first )
1240 {
1241 	if( is_msb_first != im_amiMSBfirst() )
1242 		return( im_copy_swap( in, out ) );
1243 	else
1244 		return( vips_image_write( in, out ) );
1245 }
1246 
1247 int
im_embed(IMAGE * in,IMAGE * out,int type,int x,int y,int width,int height)1248 im_embed( IMAGE *in, IMAGE *out, int type, int x, int y, int width, int height )
1249 {
1250 	VipsImage *t;
1251 
1252 	if( vips_embed( in, &t, x, y, width, height,
1253 		"extend", type,
1254 		NULL ) )
1255 		return( -1 );
1256 	if( vips_image_write( t, out ) ) {
1257 		g_object_unref( t );
1258 		return( -1 );
1259 	}
1260 	g_object_unref( t );
1261 
1262 	return( 0 );
1263 }
1264 
1265 int
im_fliphor(IMAGE * in,IMAGE * out)1266 im_fliphor( IMAGE *in, IMAGE *out )
1267 {
1268 	VipsImage *t;
1269 
1270 	if( vips_flip( in, &t, VIPS_DIRECTION_HORIZONTAL, NULL ) )
1271 		return( -1 );
1272 	if( vips_image_write( t, out ) ) {
1273 		g_object_unref( t );
1274 		return( -1 );
1275 	}
1276 	g_object_unref( t );
1277 
1278 	return( 0 );
1279 }
1280 
1281 int
im_rot90(IMAGE * in,IMAGE * out)1282 im_rot90( IMAGE *in, IMAGE *out )
1283 {
1284 	VipsImage *t;
1285 
1286 	if( vips_rot( in, &t, VIPS_ANGLE_D90, NULL ) )
1287 		return( -1 );
1288 	if( vips_image_write( t, out ) ) {
1289 		g_object_unref( t );
1290 		return( -1 );
1291 	}
1292 	g_object_unref( t );
1293 
1294 	return( 0 );
1295 }
1296 
1297 int
im_rot180(IMAGE * in,IMAGE * out)1298 im_rot180( IMAGE *in, IMAGE *out )
1299 {
1300 	VipsImage *t;
1301 
1302 	if( vips_rot( in, &t, VIPS_ANGLE_D180, NULL ) )
1303 		return( -1 );
1304 	if( vips_image_write( t, out ) ) {
1305 		g_object_unref( t );
1306 		return( -1 );
1307 	}
1308 	g_object_unref( t );
1309 
1310 	return( 0 );
1311 }
1312 
1313 int
im_rot270(IMAGE * in,IMAGE * out)1314 im_rot270( IMAGE *in, IMAGE *out )
1315 {
1316 	VipsImage *t;
1317 
1318 	if( vips_rot( in, &t, VIPS_ANGLE_D270, NULL ) )
1319 		return( -1 );
1320 	if( vips_image_write( t, out ) ) {
1321 		g_object_unref( t );
1322 		return( -1 );
1323 	}
1324 	g_object_unref( t );
1325 
1326 	return( 0 );
1327 }
1328 
1329 int
im_flipver(IMAGE * in,IMAGE * out)1330 im_flipver( IMAGE *in, IMAGE *out )
1331 {
1332 	VipsImage *t;
1333 
1334 	if( vips_flip( in, &t, VIPS_DIRECTION_VERTICAL, NULL ) )
1335 		return( -1 );
1336 	if( vips_image_write( t, out ) ) {
1337 		g_object_unref( t );
1338 		return( -1 );
1339 	}
1340 	g_object_unref( t );
1341 
1342 	return( 0 );
1343 }
1344 
1345 int
im_insert(IMAGE * main,IMAGE * sub,IMAGE * out,int x,int y)1346 im_insert( IMAGE *main, IMAGE *sub, IMAGE *out, int x, int y )
1347 {
1348 	VipsImage *t;
1349 
1350 	if( vips_insert( main, sub, &t, x, y,
1351 		"expand", TRUE,
1352 		NULL ) )
1353 		return( -1 );
1354 	if( vips_image_write( t, out ) ) {
1355 		g_object_unref( t );
1356 		return( -1 );
1357 	}
1358 	g_object_unref( t );
1359 
1360 	return( 0 );
1361 }
1362 
1363 int
im_insert_noexpand(IMAGE * main,IMAGE * sub,IMAGE * out,int x,int y)1364 im_insert_noexpand( IMAGE *main, IMAGE *sub, IMAGE *out, int x, int y )
1365 {
1366 	VipsImage *t;
1367 
1368 	if( vips_insert( main, sub, &t, x, y, NULL ) )
1369 		return( -1 );
1370 	if( vips_image_write( t, out ) ) {
1371 		g_object_unref( t );
1372 		return( -1 );
1373 	}
1374 	g_object_unref( t );
1375 
1376 	return( 0 );
1377 }
1378 
1379 int
im_lrjoin(IMAGE * left,IMAGE * right,IMAGE * out)1380 im_lrjoin( IMAGE *left, IMAGE *right, IMAGE *out )
1381 {
1382 	VipsImage *t;
1383 
1384 	if( vips_join( left, right, &t, VIPS_DIRECTION_HORIZONTAL,
1385 		NULL ) )
1386 		return( -1 );
1387 	if( vips_image_write( t, out ) ) {
1388 		g_object_unref( t );
1389 		return( -1 );
1390 	}
1391 	g_object_unref( t );
1392 
1393 	return( 0 );
1394 }
1395 
1396 int
im_tbjoin(IMAGE * left,IMAGE * right,IMAGE * out)1397 im_tbjoin( IMAGE *left, IMAGE *right, IMAGE *out )
1398 {
1399 	VipsImage *t;
1400 
1401 	if( vips_join( left, right, &t, VIPS_DIRECTION_VERTICAL,
1402 		NULL ) )
1403 		return( -1 );
1404 	if( vips_image_write( t, out ) ) {
1405 		g_object_unref( t );
1406 		return( -1 );
1407 	}
1408 	g_object_unref( t );
1409 
1410 	return( 0 );
1411 }
1412 
1413 int
im_extract_area(IMAGE * in,IMAGE * out,int left,int top,int width,int height)1414 im_extract_area( IMAGE *in, IMAGE *out,
1415 	int left, int top, int width, int height )
1416 {
1417 	VipsImage *t;
1418 
1419 	if( vips_extract_area( in, &t, left, top, width, height,
1420 		NULL ) )
1421 		return( -1 );
1422 	if( vips_image_write( t, out ) ) {
1423 		g_object_unref( t );
1424 		return( -1 );
1425 	}
1426 	g_object_unref( t );
1427 
1428 	return( 0 );
1429 }
1430 
1431 int
im_extract_bands(IMAGE * in,IMAGE * out,int band,int nbands)1432 im_extract_bands( IMAGE *in, IMAGE *out, int band, int nbands )
1433 {
1434 	VipsImage *t;
1435 
1436 	if( vips_extract_band( in, &t, band,
1437 		"n", nbands,
1438 		NULL ) )
1439 		return( -1 );
1440 	if( vips_image_write( t, out ) ) {
1441 		g_object_unref( t );
1442 		return( -1 );
1443 	}
1444 	g_object_unref( t );
1445 
1446 	return( 0 );
1447 }
1448 
1449 int
im_extract_band(IMAGE * in,IMAGE * out,int band)1450 im_extract_band( IMAGE *in, IMAGE *out, int band )
1451 {
1452 	return( im_extract_bands( in, out, band, 1 ) );
1453 }
1454 
1455 int
im_extract_areabands(IMAGE * in,IMAGE * out,int left,int top,int width,int height,int band,int nbands)1456 im_extract_areabands( IMAGE *in, IMAGE *out,
1457 	int left, int top, int width, int height, int band, int nbands )
1458 {
1459 	VipsImage *t1, *t2;
1460 
1461 	if( vips_extract_area( in, &t1, left, top, width, height,
1462 		NULL ) )
1463 		return( -1 );
1464 
1465 	if( vips_extract_band( t1, &t2, band,
1466 		"n", nbands,
1467 		NULL ) ) {
1468 		g_object_unref( t1 );
1469 		return( -1 );
1470 	}
1471 	g_object_unref( t1 );
1472 
1473 	if( vips_image_write( t2, out ) ) {
1474 		g_object_unref( t2 );
1475 		return( -1 );
1476 	}
1477 	g_object_unref( t2 );
1478 
1479 	return( 0 );
1480 }
1481 
1482 int
im_replicate(IMAGE * in,IMAGE * out,int across,int down)1483 im_replicate( IMAGE *in, IMAGE *out, int across, int down )
1484 {
1485 	VipsImage *t;
1486 
1487 	if( vips_replicate( in, &t, across, down,
1488 		NULL ) )
1489 		return( -1 );
1490 	if( vips_image_write( t, out ) ) {
1491 		g_object_unref( t );
1492 		return( -1 );
1493 	}
1494 	g_object_unref( t );
1495 
1496 	return( 0 );
1497 }
1498 
1499 int
im_clip2fmt(IMAGE * in,IMAGE * out,VipsBandFmt fmt)1500 im_clip2fmt( IMAGE *in, IMAGE *out, VipsBandFmt fmt )
1501 {
1502 	VipsImage *t;
1503 
1504 	if( vips_cast( in, &t, fmt,
1505 		NULL ) )
1506 		return( -1 );
1507 	if( vips_image_write( t, out ) ) {
1508 		g_object_unref( t );
1509 		return( -1 );
1510 	}
1511 	g_object_unref( t );
1512 
1513 	return( 0 );
1514 }
1515 
1516 size_t
im_ref_string_get_length(const GValue * value)1517 im_ref_string_get_length( const GValue *value )
1518 {
1519 	size_t length;
1520 
1521 	(void) vips_value_get_ref_string( value, &length );
1522 
1523 	return( length );
1524 }
1525 
1526 int
im_bandjoin(VipsImage * in1,VipsImage * in2,VipsImage * out)1527 im_bandjoin( VipsImage *in1, VipsImage *in2, VipsImage *out )
1528 {
1529 	VipsImage *t;
1530 
1531 	if( vips_bandjoin2( in1, in2, &t,
1532 		NULL ) )
1533 		return( -1 );
1534 	if( vips_image_write( t, out ) ) {
1535 		g_object_unref( t );
1536 		return( -1 );
1537 	}
1538 	g_object_unref( t );
1539 
1540 	return( 0 );
1541 }
1542 
1543 int
im_gbandjoin(VipsImage ** in,VipsImage * out,int n)1544 im_gbandjoin( VipsImage **in, VipsImage *out, int n )
1545 {
1546 	VipsImage *t;
1547 
1548 	if( vips_bandjoin( in, &t, n,
1549 		NULL ) )
1550 		return( -1 );
1551 	if( vips_image_write( t, out ) ) {
1552 		g_object_unref( t );
1553 		return( -1 );
1554 	}
1555 	g_object_unref( t );
1556 
1557 	return( 0 );
1558 }
1559 
1560 int
im_rank_image(VipsImage ** in,VipsImage * out,int n,int index)1561 im_rank_image( VipsImage **in, VipsImage *out, int n, int index )
1562 {
1563 	VipsImage *t;
1564 
1565 	if( vips_bandrank( in, &t, n,
1566 		"index", index,
1567 		NULL ) )
1568 		return( -1 );
1569 	if( vips_image_write( t, out ) ) {
1570 		g_object_unref( t );
1571 		return( -1 );
1572 	}
1573 	g_object_unref( t );
1574 
1575 	return( 0 );
1576 }
1577 
1578 int
im_maxvalue(IMAGE ** in,IMAGE * out,int n)1579 im_maxvalue( IMAGE **in, IMAGE *out, int n )
1580 {
1581 	return( im_rank_image( in, out, n, n - 1 ) );
1582 }
1583 
1584 int
im_invert(IMAGE * in,IMAGE * out)1585 im_invert( IMAGE *in, IMAGE *out )
1586 {
1587 	VipsImage *t;
1588 
1589 	if( vips_invert( in, &t,
1590 		NULL ) )
1591 		return( -1 );
1592 	if( vips_image_write( t, out ) ) {
1593 		g_object_unref( t );
1594 		return( -1 );
1595 	}
1596 	g_object_unref( t );
1597 
1598 	return( 0 );
1599 }
1600 
1601 int
im_sign(IMAGE * in,IMAGE * out)1602 im_sign( IMAGE *in, IMAGE *out )
1603 {
1604 	VipsImage *t;
1605 
1606 	if( vips_sign( in, &t,
1607 		NULL ) )
1608 		return( -1 );
1609 	if( vips_image_write( t, out ) ) {
1610 		g_object_unref( t );
1611 		return( -1 );
1612 	}
1613 	g_object_unref( t );
1614 
1615 	return( 0 );
1616 }
1617 
1618 int
im_abs(IMAGE * in,IMAGE * out)1619 im_abs( IMAGE *in, IMAGE *out )
1620 {
1621 	VipsImage *t;
1622 
1623 	if( vips_abs( in, &t,
1624 		NULL ) )
1625 		return( -1 );
1626 	if( vips_image_write( t, out ) ) {
1627 		g_object_unref( t );
1628 		return( -1 );
1629 	}
1630 	g_object_unref( t );
1631 
1632 	return( 0 );
1633 }
1634 
1635 int
im_bandmean(IMAGE * in,IMAGE * out)1636 im_bandmean( IMAGE *in, IMAGE *out )
1637 {
1638 	VipsImage *t;
1639 
1640 	if( vips_bandmean( in, &t,
1641 		NULL ) )
1642 		return( -1 );
1643 	if( vips_image_write( t, out ) ) {
1644 		g_object_unref( t );
1645 		return( -1 );
1646 	}
1647 	g_object_unref( t );
1648 
1649 	return( 0 );
1650 }
1651 
1652 int
im_lintra(double a,IMAGE * in,double b,IMAGE * out)1653 im_lintra( double a, IMAGE *in, double b, IMAGE *out )
1654 {
1655 	VipsImage *t;
1656 
1657 	if( vips_linear1( in, &t, a, b,
1658 		NULL ) )
1659 		return( -1 );
1660 	if( vips_image_write( t, out ) ) {
1661 		g_object_unref( t );
1662 		return( -1 );
1663 	}
1664 	g_object_unref( t );
1665 
1666 	return( 0 );
1667 }
1668 
1669 int
im_lintra_vec(int n,double * a,IMAGE * in,double * b,IMAGE * out)1670 im_lintra_vec( int n, double *a, IMAGE *in, double *b, IMAGE *out )
1671 {
1672 	VipsImage *t;
1673 
1674 	if( vips_linear( in, &t, a, b, n,
1675 		NULL ) )
1676 		return( -1 );
1677 	if( vips_image_write( t, out ) ) {
1678 		g_object_unref( t );
1679 		return( -1 );
1680 	}
1681 	g_object_unref( t );
1682 
1683 	return( 0 );
1684 }
1685 
1686 int
im_black(IMAGE * out,int x,int y,int bands)1687 im_black( IMAGE *out, int x, int y, int bands )
1688 {
1689 	VipsImage *t;
1690 
1691 	if( vips_black( &t, x, y,
1692 		"bands", bands,
1693 		NULL ) )
1694 		return( -1 );
1695 	if( vips_image_write( t, out ) ) {
1696 		g_object_unref( t );
1697 		return( -1 );
1698 	}
1699 	g_object_unref( t );
1700 
1701 	return( 0 );
1702 }
1703 
1704 int
im_identity_ushort(VipsImage * lut,int bands,int sz)1705 im_identity_ushort( VipsImage *lut, int bands, int sz )
1706 {
1707 	VipsImage *t;
1708 
1709 	if( vips_identity( &t,
1710 		"bands", bands,
1711 		"ushort", TRUE,
1712 		"size", sz,
1713 		NULL ) )
1714 		return( -1 );
1715 	if( vips_image_write( t, lut ) ) {
1716 		g_object_unref( t );
1717 		return( -1 );
1718 	}
1719 	g_object_unref( t );
1720 
1721 	return( 0 );
1722 }
1723 
1724 int
im_identity(VipsImage * lut,int bands)1725 im_identity( VipsImage *lut, int bands )
1726 {
1727 	VipsImage *t;
1728 
1729 	if( vips_identity( &t,
1730 		"bands", bands,
1731 		NULL ) )
1732 		return( -1 );
1733 	if( vips_image_write( t, lut ) ) {
1734 		g_object_unref( t );
1735 		return( -1 );
1736 	}
1737 	g_object_unref( t );
1738 
1739 	return( 0 );
1740 }
1741 
1742 int
im_gaussnoise(VipsImage * out,int x,int y,double mean,double sigma)1743 im_gaussnoise( VipsImage *out, int x, int y, double mean, double sigma )
1744 {
1745 	VipsImage *t;
1746 
1747 	if( vips_gaussnoise( &t, x, y,
1748 		"mean", mean,
1749 		"sigma", sigma,
1750 		NULL ) )
1751 		return( -1 );
1752 	if( vips_image_write( t, out ) ) {
1753 		g_object_unref( t );
1754 		return( -1 );
1755 	}
1756 	g_object_unref( t );
1757 
1758 	return( 0 );
1759 }
1760 
1761 int
im_grid(VipsImage * in,VipsImage * out,int tile_height,int across,int down)1762 im_grid( VipsImage *in, VipsImage *out, int tile_height, int across, int down )
1763 {
1764 	VipsImage *t;
1765 
1766 	if( vips_grid( in, &t, tile_height, across, down, NULL ) )
1767 		return( -1 );
1768 	if( vips_image_write( t, out ) ) {
1769 		g_object_unref( t );
1770 		return( -1 );
1771 	}
1772 	g_object_unref( t );
1773 
1774 	return( 0 );
1775 }
1776 
1777 int
im_scale(VipsImage * in,VipsImage * out)1778 im_scale( VipsImage *in, VipsImage *out )
1779 {
1780 	VipsImage *t;
1781 
1782 	if( vips_scale( in, &t, NULL ) )
1783 		return( -1 );
1784 	if( vips_image_write( t, out ) ) {
1785 		g_object_unref( t );
1786 		return( -1 );
1787 	}
1788 	g_object_unref( t );
1789 
1790 	return( 0 );
1791 }
1792 
1793 int
im_msb(VipsImage * in,VipsImage * out)1794 im_msb( VipsImage *in, VipsImage *out )
1795 {
1796 	VipsImage *t;
1797 
1798 	if( vips_msb( in, &t, NULL ) )
1799 		return( -1 );
1800 	if( vips_image_write( t, out ) ) {
1801 		g_object_unref( t );
1802 		return( -1 );
1803 	}
1804 	g_object_unref( t );
1805 
1806 	return( 0 );
1807 }
1808 
1809 int
im_msb_band(VipsImage * in,VipsImage * out,int band)1810 im_msb_band( VipsImage *in, VipsImage *out, int band )
1811 {
1812 	VipsImage *t;
1813 
1814 	if( vips_msb( in, &t, "band", band, NULL ) )
1815 		return( -1 );
1816 	if( vips_image_write( t, out ) ) {
1817 		g_object_unref( t );
1818 		return( -1 );
1819 	}
1820 	g_object_unref( t );
1821 
1822 	return( 0 );
1823 }
1824 
1825 int
im_make_xy(IMAGE * out,const int xsize,const int ysize)1826 im_make_xy( IMAGE *out, const int xsize, const int ysize )
1827 {
1828 	VipsImage *t;
1829 
1830 	if( vips_xyz( &t, xsize, ysize, NULL ) )
1831 		return( -1 );
1832 	if( vips_image_write( t, out ) ) {
1833 		g_object_unref( t );
1834 		return( -1 );
1835 	}
1836 	g_object_unref( t );
1837 
1838 	return( 0 );
1839 }
1840 
1841 int
im_zone(IMAGE * out,int size)1842 im_zone( IMAGE *out, int size )
1843 {
1844 	VipsImage *t;
1845 
1846 	if( vips_zone( &t, size, size,
1847 		"uchar", TRUE,
1848 		NULL ) )
1849 		return( -1 );
1850 	if( vips_image_write( t, out ) ) {
1851 		g_object_unref( t );
1852 		return( -1 );
1853 	}
1854 	g_object_unref( t );
1855 
1856 	return( 0 );
1857 }
1858 
1859 int
im_fzone(IMAGE * out,int size)1860 im_fzone( IMAGE *out, int size )
1861 {
1862 	VipsImage *t;
1863 
1864 	if( vips_zone( &t, size, size, NULL ) )
1865 		return( -1 );
1866 	if( vips_image_write( t, out ) ) {
1867 		g_object_unref( t );
1868 		return( -1 );
1869 	}
1870 	g_object_unref( t );
1871 
1872 	return( 0 );
1873 }
1874 
1875 int
im_sines(IMAGE * out,int xsize,int ysize,double horfreq,double verfreq)1876 im_sines( IMAGE *out, int xsize, int ysize, double horfreq, double verfreq )
1877 {
1878 	VipsImage *t;
1879 
1880 	if( vips_sines( &t, xsize, ysize,
1881 		"hfreq", horfreq,
1882 		"vfreq", verfreq,
1883 		NULL ) )
1884 		return( -1 );
1885 	if( vips_image_write( t, out ) ) {
1886 		g_object_unref( t );
1887 		return( -1 );
1888 	}
1889 	g_object_unref( t );
1890 
1891 	return( 0 );
1892 }
1893 
1894 int
im_text(IMAGE * out,const char * text,const char * font,int width,int align,int dpi)1895 im_text( IMAGE *out, const char *text, const char *font,
1896 	int width, int align, int dpi )
1897 {
1898 	VipsImage *t;
1899 
1900 	if( vips_text( &t, text,
1901 		"font", font,
1902 		"width", width,
1903 		"align", align,
1904 		"dpi", dpi,
1905 		NULL ) )
1906 		return( -1 );
1907 	if( vips_image_write( t, out ) ) {
1908 		g_object_unref( t );
1909 		return( -1 );
1910 	}
1911 	g_object_unref( t );
1912 
1913 	return( 0 );
1914 }
1915 
1916 int
im_system(VipsImage * im,const char * cmd,char ** out)1917 im_system( VipsImage *im, const char *cmd, char **out )
1918 {
1919 	VipsArea *area;
1920 	VipsImage **array;
1921 	char *str;
1922 
1923 	area = vips_area_new_array_object( 1 );
1924 	array = (VipsImage **) area->data;
1925 	array[0] = im;
1926 
1927 	if( vips_system( cmd,
1928 		"in", area,
1929 		"in_format", "%s.v",
1930 		"log", &str,
1931 		NULL ) ) {
1932 		vips_area_unref( area );
1933 		return( -1 );
1934 	}
1935 
1936 	vips_area_unref( area );
1937 
1938 	if( out )
1939 		*out = str;
1940 
1941 	return( 0 );
1942 }
1943 
1944 VipsImage *
im_system_image(VipsImage * im,const char * in_format,const char * out_format,const char * cmd_format,char ** log)1945 im_system_image( VipsImage *im,
1946 	const char *in_format, const char *out_format, const char *cmd_format,
1947 	char **log )
1948 {
1949 	VipsArrayImage *array;
1950 	char *str;
1951 	VipsImage *out;
1952 
1953 	array = vips_array_image_newv( 1, im );
1954 
1955 	/* im will be unreffed when area is unreffed.
1956 	 */
1957 	g_object_ref( im );
1958 
1959 	if( vips_system( cmd_format,
1960 		"in", array,
1961 		"out", &out,
1962 		"in_format", in_format,
1963 		"out_format", out_format,
1964 		"log", &str,
1965 		NULL ) ) {
1966 		vips_area_unref( VIPS_AREA( array ) );
1967 		return( NULL );
1968 	}
1969 
1970 	vips_area_unref( VIPS_AREA( array ) );
1971 
1972 	if( log )
1973 		*log = str;
1974 	else
1975 		g_free( str );
1976 
1977 	return( out );
1978 }
1979 
1980 int
im_wrap(IMAGE * in,IMAGE * out,int x,int y)1981 im_wrap( IMAGE *in, IMAGE *out, int x, int y )
1982 {
1983 	VipsImage *t;
1984 
1985 	if( vips_wrap( in, &t, "x", x, "y", y, NULL ) )
1986 		return( -1 );
1987 	if( vips_image_write( t, out ) ) {
1988 		g_object_unref( t );
1989 		return( -1 );
1990 	}
1991 	g_object_unref( t );
1992 
1993 	return( 0 );
1994 }
1995 
1996 int
im_rotquad(IMAGE * in,IMAGE * out)1997 im_rotquad( IMAGE *in, IMAGE *out )
1998 {
1999 	return( im_wrap( in, out, in->Xsize / 2, in->Ysize / 2 ) );
2000 }
2001 
2002 int
im_scaleps(VipsImage * in,VipsImage * out)2003 im_scaleps( VipsImage *in, VipsImage *out )
2004 {
2005 	VipsImage *t;
2006 
2007 	if( vips_scale( in, &t, "log", TRUE, NULL ) )
2008 		return( -1 );
2009 	if( vips_image_write( t, out ) ) {
2010 		g_object_unref( t );
2011 		return( -1 );
2012 	}
2013 	g_object_unref( t );
2014 
2015 	return( 0 );
2016 }
2017 
2018 int
im_zoom(VipsImage * in,VipsImage * out,int xfac,int yfac)2019 im_zoom( VipsImage *in, VipsImage *out, int xfac, int yfac )
2020 {
2021 	VipsImage *t;
2022 
2023 	if( vips_zoom( in, &t, xfac, yfac, NULL ) )
2024 		return( -1 );
2025 	if( vips_image_write( t, out ) ) {
2026 		g_object_unref( t );
2027 		return( -1 );
2028 	}
2029 	g_object_unref( t );
2030 
2031 	return( 0 );
2032 }
2033 
2034 int
im_subsample(VipsImage * in,VipsImage * out,int xfac,int yfac)2035 im_subsample( VipsImage *in, VipsImage *out, int xfac, int yfac )
2036 {
2037 	VipsImage *t;
2038 
2039 	if( vips_subsample( in, &t, xfac, yfac, NULL ) )
2040 		return( -1 );
2041 	if( vips_image_write( t, out ) ) {
2042 		g_object_unref( t );
2043 		return( -1 );
2044 	}
2045 	g_object_unref( t );
2046 
2047 	return( 0 );
2048 }
2049 
2050 static int
vips__math(VipsImage * in,VipsImage * out,VipsOperationMath math)2051 vips__math( VipsImage *in, VipsImage *out, VipsOperationMath math )
2052 {
2053 	VipsImage *t;
2054 
2055 	if( vips_math( in, &t, math,
2056 		NULL ) )
2057 		return( -1 );
2058 	if( vips_image_write( t, out ) ) {
2059 		g_object_unref( t );
2060 		return( -1 );
2061 	}
2062 	g_object_unref( t );
2063 
2064 	return( 0 );
2065 }
2066 
2067 int
im_sintra(IMAGE * in,IMAGE * out)2068 im_sintra( IMAGE *in, IMAGE *out )
2069 {
2070 	return( vips__math( in, out, VIPS_OPERATION_MATH_SIN ) );
2071 }
2072 
2073 int
im_costra(IMAGE * in,IMAGE * out)2074 im_costra( IMAGE *in, IMAGE *out )
2075 {
2076 	return( vips__math( in, out, VIPS_OPERATION_MATH_COS ) );
2077 }
2078 
2079 int
im_tantra(IMAGE * in,IMAGE * out)2080 im_tantra( IMAGE *in, IMAGE *out )
2081 {
2082 	return( vips__math( in, out, VIPS_OPERATION_MATH_TAN ) );
2083 }
2084 
2085 int
im_asintra(IMAGE * in,IMAGE * out)2086 im_asintra( IMAGE *in, IMAGE *out )
2087 {
2088 	return( vips__math( in, out, VIPS_OPERATION_MATH_ASIN ) );
2089 }
2090 
2091 int
im_acostra(IMAGE * in,IMAGE * out)2092 im_acostra( IMAGE *in, IMAGE *out )
2093 {
2094 	return( vips__math( in, out, VIPS_OPERATION_MATH_ACOS ) );
2095 }
2096 
2097 int
im_atantra(IMAGE * in,IMAGE * out)2098 im_atantra( IMAGE *in, IMAGE *out )
2099 {
2100 	return( vips__math( in, out, VIPS_OPERATION_MATH_ATAN ) );
2101 }
2102 
2103 int
im_logtra(IMAGE * in,IMAGE * out)2104 im_logtra( IMAGE *in, IMAGE *out )
2105 {
2106 	return( vips__math( in, out, VIPS_OPERATION_MATH_LOG ) );
2107 }
2108 
2109 int
im_log10tra(IMAGE * in,IMAGE * out)2110 im_log10tra( IMAGE *in, IMAGE *out )
2111 {
2112 	return( vips__math( in, out, VIPS_OPERATION_MATH_LOG10 ) );
2113 }
2114 
2115 int
im_exptra(IMAGE * in,IMAGE * out)2116 im_exptra( IMAGE *in, IMAGE *out )
2117 {
2118 	return( vips__math( in, out, VIPS_OPERATION_MATH_EXP ) );
2119 }
2120 
2121 int
im_exp10tra(IMAGE * in,IMAGE * out)2122 im_exp10tra( IMAGE *in, IMAGE *out )
2123 {
2124 	return( vips__math( in, out, VIPS_OPERATION_MATH_EXP10 ) );
2125 }
2126 
2127 DOUBLEMASK *
im_stats(VipsImage * in)2128 im_stats( VipsImage *in )
2129 {
2130 	VipsImage *t;
2131 	DOUBLEMASK *msk;
2132 
2133 	if( vips_stats( in, &t,
2134 		NULL ) )
2135 		return( NULL );
2136 	if( !(msk = im_vips2mask( t, "im_stats" )) ) {
2137 		g_object_unref( t );
2138 		return( NULL );
2139 	}
2140 	g_object_unref( t );
2141 
2142 	return( msk );
2143 }
2144 
2145 DOUBLEMASK *
im_gauss_dmask(const char * filename,double sigma,double min_ampl)2146 im_gauss_dmask( const char *filename, double sigma, double min_ampl )
2147 {
2148 	VipsImage *t;
2149 	DOUBLEMASK *msk;
2150 
2151 	if( vips_gaussmat( &t, sigma, min_ampl,
2152 		"precision", VIPS_PRECISION_FLOAT,
2153 		NULL ) )
2154 		return( NULL );
2155 	if( !(msk = im_vips2mask( t, filename )) ) {
2156 		g_object_unref( t );
2157 		return( NULL );
2158 	}
2159 	g_object_unref( t );
2160 
2161 	return( msk );
2162 }
2163 
2164 DOUBLEMASK *
im_gauss_dmask_sep(const char * filename,double sigma,double min_ampl)2165 im_gauss_dmask_sep( const char *filename, double sigma, double min_ampl )
2166 {
2167 	VipsImage *t;
2168 	DOUBLEMASK *msk;
2169 
2170 	if( vips_gaussmat( &t, sigma, min_ampl,
2171 		"precision", VIPS_PRECISION_FLOAT,
2172 		"separable", TRUE,
2173 		NULL ) )
2174 		return( NULL );
2175 	if( !(msk = im_vips2mask( t, filename )) ) {
2176 		g_object_unref( t );
2177 		return( NULL );
2178 	}
2179 	g_object_unref( t );
2180 
2181 	return( msk );
2182 }
2183 
2184 INTMASK *
im_gauss_imask(const char * filename,double sigma,double min_ampl)2185 im_gauss_imask( const char *filename, double sigma, double min_ampl )
2186 {
2187 	VipsImage *t;
2188 	INTMASK *msk;
2189 
2190 	if( vips_gaussmat( &t, sigma, min_ampl, NULL ) )
2191 		return( NULL );
2192 	if( !(msk = im_vips2imask( t, filename )) ) {
2193 		g_object_unref( t );
2194 		return( NULL );
2195 	}
2196 	g_object_unref( t );
2197 
2198 	return( msk );
2199 }
2200 
2201 INTMASK *
im_gauss_imask_sep(const char * filename,double sigma,double min_ampl)2202 im_gauss_imask_sep( const char *filename, double sigma, double min_ampl )
2203 {
2204 	VipsImage *t;
2205 	INTMASK *msk;
2206 
2207 	if( vips_gaussmat( &t, sigma, min_ampl,
2208 		"separable", TRUE,
2209 		NULL ) )
2210 		return( NULL );
2211 	if( !(msk = im_vips2imask( t, filename )) ) {
2212 		g_object_unref( t );
2213 		return( NULL );
2214 	}
2215 	g_object_unref( t );
2216 
2217 	return( msk );
2218 }
2219 
2220 INTMASK *
im_log_imask(const char * filename,double sigma,double min_ampl)2221 im_log_imask( const char *filename, double sigma, double min_ampl )
2222 {
2223 	VipsImage *t;
2224 	INTMASK *msk;
2225 
2226 	if( vips_logmat( &t, sigma, min_ampl, NULL ) )
2227 		return( NULL );
2228 	if( !(msk = im_vips2imask( t, filename )) ) {
2229 		g_object_unref( t );
2230 		return( NULL );
2231 	}
2232 	g_object_unref( t );
2233 
2234 	return( msk );
2235 }
2236 
2237 DOUBLEMASK *
im_log_dmask(const char * filename,double sigma,double min_ampl)2238 im_log_dmask( const char *filename, double sigma, double min_ampl )
2239 {
2240 	VipsImage *t;
2241 	DOUBLEMASK *msk;
2242 
2243 	if( vips_logmat( &t, sigma, min_ampl,
2244 		"precision", VIPS_PRECISION_FLOAT,
2245 		NULL ) )
2246 		return( NULL );
2247 	if( !(msk = im_vips2mask( t, filename )) ) {
2248 		g_object_unref( t );
2249 		return( NULL );
2250 	}
2251 	g_object_unref( t );
2252 
2253 	return( msk );
2254 }
2255 
2256 int
im_recomb(IMAGE * in,IMAGE * out,DOUBLEMASK * recomb)2257 im_recomb( IMAGE *in, IMAGE *out, DOUBLEMASK *recomb )
2258 {
2259 	VipsImage *t1, *t2;
2260 
2261 	if( !(t1 = vips_image_new()) ||
2262 		im_mask2vips( recomb, t1 ) )
2263 		return( -1 );
2264 	if( vips_recomb( in, &t2, t1,
2265 		NULL ) ) {
2266 		g_object_unref( t1 );
2267 		return( -1 );
2268 	}
2269 	g_object_unref( t1 );
2270 	if( vips_image_write( t2, out ) ) {
2271 		g_object_unref( t2 );
2272 		return( -1 );
2273 	}
2274 	g_object_unref( t2 );
2275 
2276 	return( 0 );
2277 }
2278 
2279 int
im_compass(VipsImage * in,VipsImage * out,INTMASK * mask)2280 im_compass( VipsImage *in, VipsImage *out, INTMASK *mask )
2281 {
2282 	VipsImage *t1, *t2;
2283 
2284 	if( !(t1 = vips_image_new()) ||
2285 		im_imask2vips( mask, t1 ) )
2286 		return( -1 );
2287 	if( vips_compass( in, &t2, t1,
2288 		"times", 8,
2289 		"angle", VIPS_ANGLE45_D45,
2290 		"precision", VIPS_PRECISION_INTEGER,
2291 		NULL ) ) {
2292 		g_object_unref( t1 );
2293 		return( -1 );
2294 	}
2295 	g_object_unref( t1 );
2296 	if( vips_image_write( t2, out ) ) {
2297 		g_object_unref( t2 );
2298 		return( -1 );
2299 	}
2300 	g_object_unref( t2 );
2301 
2302 	return( 0 );
2303 }
2304 
2305 int
im_lindetect(IMAGE * in,IMAGE * out,INTMASK * mask)2306 im_lindetect( IMAGE *in, IMAGE *out, INTMASK *mask )
2307 {
2308 	VipsImage *t1, *t2;
2309 
2310 	if( !(t1 = vips_image_new()) ||
2311 		im_imask2vips( mask, t1 ) )
2312 		return( -1 );
2313 	if( vips_compass( in, &t2, t1,
2314 		"times", 4,
2315 		"angle", VIPS_ANGLE45_D45,
2316 		"precision", VIPS_PRECISION_INTEGER,
2317 		NULL ) ) {
2318 		g_object_unref( t1 );
2319 		return( -1 );
2320 	}
2321 	g_object_unref( t1 );
2322 	if( vips_image_write( t2, out ) ) {
2323 		g_object_unref( t2 );
2324 		return( -1 );
2325 	}
2326 	g_object_unref( t2 );
2327 
2328 	return( 0 );
2329 }
2330 
2331 int
im_gradient(IMAGE * in,IMAGE * out,INTMASK * mask)2332 im_gradient( IMAGE *in, IMAGE *out, INTMASK *mask )
2333 {
2334 	VipsImage *t1, *t2;
2335 
2336 	if( !(t1 = vips_image_new()) ||
2337 		im_imask2vips( mask, t1 ) )
2338 		return( -1 );
2339 	if( vips_compass( in, &t2, t1,
2340 		"times", 2,
2341 		"angle", VIPS_ANGLE45_D90,
2342 		"combine", VIPS_COMBINE_SUM,
2343 		"precision", VIPS_PRECISION_INTEGER,
2344 		NULL ) ) {
2345 		g_object_unref( t1 );
2346 		return( -1 );
2347 	}
2348 	g_object_unref( t1 );
2349 	if( vips_image_write( t2, out ) ) {
2350 		g_object_unref( t2 );
2351 		return( -1 );
2352 	}
2353 	g_object_unref( t2 );
2354 
2355 	return( 0 );
2356 }
2357 
2358 int
im_convsep_raw(IMAGE * in,IMAGE * out,INTMASK * mask)2359 im_convsep_raw( IMAGE *in, IMAGE *out, INTMASK *mask )
2360 {
2361 	im_error( "im_convsep_raw", "no compat function" );
2362 	return( -1 );
2363 }
2364 
2365 int
im_convsep(IMAGE * in,IMAGE * out,INTMASK * mask)2366 im_convsep( IMAGE *in, IMAGE *out, INTMASK *mask )
2367 {
2368 	VipsImage *t1, *t2;
2369 
2370 	if( !(t1 = vips_image_new()) ||
2371 		im_imask2vips( mask, t1 ) )
2372 		return( -1 );
2373 	if( vips_convsep( in, &t2, t1,
2374 		"precision", VIPS_PRECISION_INTEGER,
2375 		NULL ) ) {
2376 		g_object_unref( t1 );
2377 		return( -1 );
2378 	}
2379 	g_object_unref( t1 );
2380 	if( vips_image_write( t2, out ) ) {
2381 		g_object_unref( t2 );
2382 		return( -1 );
2383 	}
2384 	g_object_unref( t2 );
2385 
2386 	return( 0 );
2387 }
2388 
2389 int
im_convsep_f_raw(IMAGE * in,IMAGE * out,DOUBLEMASK * mask)2390 im_convsep_f_raw( IMAGE *in, IMAGE *out, DOUBLEMASK *mask )
2391 {
2392 	im_error( "im_convsep_raw", "no compat function" );
2393 	return( -1 );
2394 }
2395 
2396 int
im_convsep_f(IMAGE * in,IMAGE * out,DOUBLEMASK * mask)2397 im_convsep_f( IMAGE *in, IMAGE *out, DOUBLEMASK *mask )
2398 {
2399 	VipsImage *t1, *t2;
2400 
2401 	if( !(t1 = vips_image_new()) ||
2402 		im_mask2vips( mask, t1 ) )
2403 		return( -1 );
2404 	if( vips_convsep( in, &t2, t1, NULL ) ) {
2405 		g_object_unref( t1 );
2406 		return( -1 );
2407 	}
2408 	g_object_unref( t1 );
2409 	if( vips_image_write( t2, out ) ) {
2410 		g_object_unref( t2 );
2411 		return( -1 );
2412 	}
2413 	g_object_unref( t2 );
2414 
2415 	return( 0 );
2416 }
2417 
2418 int
im_conv(VipsImage * in,VipsImage * out,INTMASK * mask)2419 im_conv( VipsImage *in, VipsImage *out, INTMASK *mask )
2420 {
2421 	VipsImage *t1, *t2;
2422 
2423 	if( !(t1 = vips_image_new()) ||
2424 		im_imask2vips( mask, t1 ) )
2425 		return( -1 );
2426 	if( vips_convi( in, &t2, t1,
2427 		NULL ) ) {
2428 		g_object_unref( t1 );
2429 		return( -1 );
2430 	}
2431 	g_object_unref( t1 );
2432 	if( vips_image_write( t2, out ) ) {
2433 		g_object_unref( t2 );
2434 		return( -1 );
2435 	}
2436 	g_object_unref( t2 );
2437 
2438 	return( 0 );
2439 }
2440 
2441 int
im_conv_raw(VipsImage * in,VipsImage * out,INTMASK * mask)2442 im_conv_raw( VipsImage *in, VipsImage *out, INTMASK *mask )
2443 {
2444 	im_error( "im_conv_raw", "no compat function" );
2445 	return( -1 );
2446 }
2447 
2448 int
im_conv_f(VipsImage * in,VipsImage * out,DOUBLEMASK * mask)2449 im_conv_f( VipsImage *in, VipsImage *out, DOUBLEMASK *mask )
2450 {
2451 	VipsImage *t1, *t2;
2452 
2453 	if( !(t1 = vips_image_new()) ||
2454 		im_mask2vips( mask, t1 ) )
2455 		return( -1 );
2456 	if( vips_convf( in, &t2, t1,
2457 		NULL ) ) {
2458 		g_object_unref( t1 );
2459 		return( -1 );
2460 	}
2461 	g_object_unref( t1 );
2462 	if( vips_image_write( t2, out ) ) {
2463 		g_object_unref( t2 );
2464 		return( -1 );
2465 	}
2466 	g_object_unref( t2 );
2467 
2468 	return( 0 );
2469 }
2470 
2471 int
im_aconvsep(VipsImage * in,VipsImage * out,DOUBLEMASK * mask,int n_layers)2472 im_aconvsep( VipsImage *in, VipsImage *out, DOUBLEMASK *mask, int n_layers )
2473 {
2474 	VipsImage *t1, *t2;
2475 
2476 	if( !(t1 = vips_image_new()) ||
2477 		im_mask2vips( mask, t1 ) )
2478 		return( -1 );
2479 	if( vips_convasep( in, &t2, t1,
2480 		"layers", n_layers,
2481 		NULL ) ) {
2482 		g_object_unref( t1 );
2483 		return( -1 );
2484 	}
2485 	g_object_unref( t1 );
2486 	if( vips_image_write( t2, out ) ) {
2487 		g_object_unref( t2 );
2488 		return( -1 );
2489 	}
2490 	g_object_unref( t2 );
2491 
2492 	return( 0 );
2493 }
2494 
2495 int
im_aconv(VipsImage * in,VipsImage * out,DOUBLEMASK * mask,int n_layers,int cluster)2496 im_aconv( VipsImage *in, VipsImage *out,
2497 	DOUBLEMASK *mask, int n_layers, int cluster )
2498 {
2499 	VipsImage *t1, *t2;
2500 
2501 	if( !(t1 = vips_image_new()) ||
2502 		im_mask2vips( mask, t1 ) )
2503 		return( -1 );
2504 	if( vips_conva( in, &t2, t1,
2505 		"layers", n_layers,
2506 		"cluster", cluster,
2507 		NULL ) ) {
2508 		g_object_unref( t1 );
2509 		return( -1 );
2510 	}
2511 	g_object_unref( t1 );
2512 	if( vips_image_write( t2, out ) ) {
2513 		g_object_unref( t2 );
2514 		return( -1 );
2515 	}
2516 	g_object_unref( t2 );
2517 
2518 	return( 0 );
2519 }
2520 
2521 int
im_conv_f_raw(VipsImage * in,VipsImage * out,DOUBLEMASK * mask)2522 im_conv_f_raw( VipsImage *in, VipsImage *out, DOUBLEMASK *mask )
2523 {
2524 	im_error( "im_conv_f_raw", "no compat function" );
2525 	return( -1 );
2526 }
2527 
2528 int
im_addgnoise(IMAGE * in,IMAGE * out,double sigma)2529 im_addgnoise( IMAGE *in, IMAGE *out, double sigma )
2530 {
2531 	IMAGE *t;
2532 
2533 	if( !(t = im_open_local( out, "im_addgnoise", "p" )) ||
2534 		im_gaussnoise( t, in->Xsize, in->Ysize, 0, sigma ) ||
2535 		im_add( in, t, out ) )
2536 		return( -1 );
2537 
2538 	return( 0 );
2539 }
2540 
2541 int
im_contrast_surface_raw(IMAGE * in,IMAGE * out,int half_win_size,int spacing)2542 im_contrast_surface_raw( IMAGE *in, IMAGE *out, int half_win_size, int spacing )
2543 {
2544 	im_error( "im_contrast_surface_raw", "no compat function" );
2545 	return( -1 );
2546 }
2547 
2548 /* This replaces some custom code in 7.36 and earlier. The hand-made one was
2549  * slower for spacing == 1, though faster for large values of spacing.
2550  *
2551  * Not worth maintaining a special operator for.
2552  */
2553 int
im_contrast_surface(IMAGE * in,IMAGE * out,int half_win_size,int spacing)2554 im_contrast_surface( IMAGE *in, IMAGE *out, int half_win_size, int spacing )
2555 {
2556 	VipsImage **t = (VipsImage **)
2557 		vips_object_local_array( VIPS_OBJECT( out ), 10 );
2558 	int size = half_win_size * 2;
2559 
2560 	int x, y;
2561 
2562 	t[0] = vips_image_new_matrixv( 1, 2, -1.0, 1.0 );
2563 	t[1] = vips_image_new_matrixv( 2, 1, -1.0, 1.0 );
2564 	t[8] = vips_image_new_matrix( size, size );
2565 
2566 	for( y = 0; y < size; y++ )
2567 		for( x = 0; x < size; x++ )
2568 			*VIPS_MATRIX( t[8], x, y ) = 1.0;
2569 
2570 	if( vips_conv( in, &t[2], t[0],
2571 			"precision", VIPS_PRECISION_INTEGER,
2572 			NULL ) ||
2573 		vips_conv( in, &t[3], t[1],
2574 			"precision", VIPS_PRECISION_INTEGER,
2575 			NULL ) ||
2576 		vips_abs( t[2], &t[4], NULL ) ||
2577 		vips_abs( t[3], &t[5], NULL ) ||
2578 		vips_add( t[4], t[5], &t[6], NULL ) ||
2579 		vips_conv( t[6], &t[7], t[8],
2580 			"precision", VIPS_PRECISION_INTEGER,
2581 			NULL ) ||
2582 		vips_subsample( t[7], &t[9], spacing, spacing, NULL ) ||
2583 		vips_image_write( t[9], out ) )
2584 		return( -1 );
2585 
2586 	return( 0 );
2587 }
2588 
2589 int
im_spcor_raw(IMAGE * in,IMAGE * ref,IMAGE * out)2590 im_spcor_raw( IMAGE *in, IMAGE *ref, IMAGE *out )
2591 {
2592 	im_error( "im_spcor_raw", "no compat function" );
2593 	return( -1 );
2594 }
2595 
2596 int
im_spcor(IMAGE * in,IMAGE * ref,IMAGE * out)2597 im_spcor( IMAGE *in, IMAGE *ref, IMAGE *out )
2598 {
2599 	VipsImage *x;
2600 
2601 	if( vips_call( "spcor", in, ref, &x, NULL ) )
2602 		return( -1 );
2603 	if( vips_image_write( x, out ) ) {
2604 		g_object_unref( x );
2605 		return( -1 );
2606 	}
2607 	g_object_unref( x );
2608 
2609 	return( 0 );
2610 }
2611 
2612 int
im_fastcor_raw(IMAGE * in,IMAGE * ref,IMAGE * out)2613 im_fastcor_raw( IMAGE *in, IMAGE *ref, IMAGE *out )
2614 {
2615 	im_error( "im_fastcor_raw", "no compat function" );
2616 	return( -1 );
2617 }
2618 
2619 int
im_fastcor(IMAGE * in,IMAGE * ref,IMAGE * out)2620 im_fastcor( IMAGE *in, IMAGE *ref, IMAGE *out )
2621 {
2622 	VipsImage *x;
2623 
2624 	if( vips_call( "fastcor", in, ref, &x, NULL ) )
2625 		return( -1 );
2626 	if( vips_image_write( x, out ) ) {
2627 		g_object_unref( x );
2628 		return( -1 );
2629 	}
2630 	g_object_unref( x );
2631 
2632 	return( 0 );
2633 }
2634 
2635 int
im_sharpen(IMAGE * in,IMAGE * out,int mask_size,double x1,double y2,double y3,double m1,double m2)2636 im_sharpen( IMAGE *in, IMAGE *out,
2637 	int mask_size,
2638 	double x1, double y2, double y3,
2639 	double m1, double m2 )
2640 {
2641 	VipsImage **t = (VipsImage **)
2642 		vips_object_local_array( VIPS_OBJECT( out ), 2 );
2643 
2644 	/* im_sharpen() always recoded as labq and im_benchmark() depends
2645 	 * upon this behaviour.
2646 	 */
2647 	if( vips_call( "sharpen", in, &t[0],
2648 		"sigma", mask_size / 4.0,
2649 		"x1", x1,
2650 		"y2", y2,
2651 		"y3", y3,
2652 		"m1", m1,
2653 		"m2", m2,
2654 		NULL ) ||
2655 		vips_colourspace( t[0], &t[1],
2656 			VIPS_INTERPRETATION_LABQ, NULL ) ||
2657 		vips_image_write( t[1], out ) )
2658 		return( -1 );
2659 
2660 	return( 0 );
2661 }
2662 
2663 static int
vips__round(VipsImage * in,VipsImage * out,VipsOperationRound round)2664 vips__round( VipsImage *in, VipsImage *out, VipsOperationRound round )
2665 {
2666 	VipsImage *t;
2667 
2668 	if( vips_round( in, &t, round,
2669 		NULL ) )
2670 		return( -1 );
2671 	if( vips_image_write( t, out ) ) {
2672 		g_object_unref( t );
2673 		return( -1 );
2674 	}
2675 	g_object_unref( t );
2676 
2677 	return( 0 );
2678 }
2679 
2680 int
im_rint(IMAGE * in,IMAGE * out)2681 im_rint( IMAGE *in, IMAGE *out )
2682 {
2683 	return( vips__round( in, out, VIPS_OPERATION_ROUND_RINT ) );
2684 }
2685 
2686 int
im_floor(IMAGE * in,IMAGE * out)2687 im_floor( IMAGE *in, IMAGE *out )
2688 {
2689 	return( vips__round( in, out, VIPS_OPERATION_ROUND_FLOOR ) );
2690 }
2691 
2692 int
im_ceil(IMAGE * in,IMAGE * out)2693 im_ceil( IMAGE *in, IMAGE *out )
2694 {
2695 	return( vips__round( in, out, VIPS_OPERATION_ROUND_CEIL ) );
2696 }
2697 
2698 static int
vips__relational(IMAGE * in1,IMAGE * in2,IMAGE * out,VipsOperationRelational relational)2699 vips__relational( IMAGE *in1, IMAGE *in2, IMAGE *out,
2700 	VipsOperationRelational relational )
2701 {
2702 	VipsImage *t;
2703 
2704 	if( vips_relational( in1, in2, &t, relational,
2705 		NULL ) )
2706 		return( -1 );
2707 	if( vips_image_write( t, out ) ) {
2708 		g_object_unref( t );
2709 		return( -1 );
2710 	}
2711 	g_object_unref( t );
2712 
2713 	return( 0 );
2714 }
2715 
2716 int
im_equal(IMAGE * in1,IMAGE * in2,IMAGE * out)2717 im_equal( IMAGE *in1, IMAGE *in2, IMAGE *out )
2718 {
2719 	return( vips__relational( in1, in2, out,
2720 		VIPS_OPERATION_RELATIONAL_EQUAL ) );
2721 }
2722 
2723 int
im_notequal(IMAGE * in1,IMAGE * in2,IMAGE * out)2724 im_notequal( IMAGE *in1, IMAGE *in2, IMAGE *out )
2725 {
2726 	return( vips__relational( in1, in2, out,
2727 		VIPS_OPERATION_RELATIONAL_NOTEQ ) );
2728 }
2729 
2730 int
im_less(IMAGE * in1,IMAGE * in2,IMAGE * out)2731 im_less( IMAGE *in1, IMAGE *in2, IMAGE *out )
2732 {
2733 	return( vips__relational( in1, in2, out,
2734 		VIPS_OPERATION_RELATIONAL_LESS ) );
2735 }
2736 
2737 int
im_lesseq(IMAGE * in1,IMAGE * in2,IMAGE * out)2738 im_lesseq( IMAGE *in1, IMAGE *in2, IMAGE *out )
2739 {
2740 	return( vips__relational( in1, in2, out,
2741 		VIPS_OPERATION_RELATIONAL_LESSEQ ) );
2742 }
2743 
2744 int
im_more(IMAGE * in1,IMAGE * in2,IMAGE * out)2745 im_more( IMAGE *in1, IMAGE *in2, IMAGE *out )
2746 {
2747 	return( vips__relational( in1, in2, out,
2748 		VIPS_OPERATION_RELATIONAL_MORE ) );
2749 }
2750 
2751 int
im_moreeq(IMAGE * in1,IMAGE * in2,IMAGE * out)2752 im_moreeq( IMAGE *in1, IMAGE *in2, IMAGE *out )
2753 {
2754 	return( vips__relational( in1, in2, out,
2755 		VIPS_OPERATION_RELATIONAL_MOREEQ ) );
2756 }
2757 
2758 static int
vips__relational_vec(IMAGE * in,IMAGE * out,VipsOperationRelational relational,double * c,int n)2759 vips__relational_vec( IMAGE *in, IMAGE *out,
2760 	VipsOperationRelational relational, double *c, int n )
2761 {
2762 	VipsImage *t;
2763 
2764 	if( vips_relational_const( in, &t, relational, c, n,
2765 		NULL ) )
2766 		return( -1 );
2767 	if( vips_image_write( t, out ) ) {
2768 		g_object_unref( t );
2769 		return( -1 );
2770 	}
2771 	g_object_unref( t );
2772 
2773 	return( 0 );
2774 }
2775 
2776 int
im_equal_vec(VipsImage * in,VipsImage * out,int n,double * c)2777 im_equal_vec( VipsImage *in, VipsImage *out, int n, double *c )
2778 {
2779 	return( vips__relational_vec( in, out,
2780 		VIPS_OPERATION_RELATIONAL_EQUAL, c, n ) );
2781 }
2782 
2783 int
im_notequal_vec(VipsImage * in,VipsImage * out,int n,double * c)2784 im_notequal_vec( VipsImage *in, VipsImage *out, int n, double *c )
2785 {
2786 	return( vips__relational_vec( in, out,
2787 		VIPS_OPERATION_RELATIONAL_NOTEQ, c, n ) );
2788 }
2789 
2790 int
im_less_vec(VipsImage * in,VipsImage * out,int n,double * c)2791 im_less_vec( VipsImage *in, VipsImage *out, int n, double *c )
2792 {
2793 	return( vips__relational_vec( in, out,
2794 		VIPS_OPERATION_RELATIONAL_LESS, c, n ) );
2795 }
2796 
2797 int
im_lesseq_vec(VipsImage * in,VipsImage * out,int n,double * c)2798 im_lesseq_vec( VipsImage *in, VipsImage *out, int n, double *c )
2799 {
2800 	return( vips__relational_vec( in, out,
2801 		VIPS_OPERATION_RELATIONAL_LESSEQ, c, n ) );
2802 }
2803 
2804 int
im_more_vec(VipsImage * in,VipsImage * out,int n,double * c)2805 im_more_vec( VipsImage *in, VipsImage *out, int n, double *c )
2806 {
2807 	return( vips__relational_vec( in, out,
2808 		VIPS_OPERATION_RELATIONAL_MORE, c, n ) );
2809 }
2810 
2811 int
im_moreeq_vec(VipsImage * in,VipsImage * out,int n,double * c)2812 im_moreeq_vec( VipsImage *in, VipsImage *out, int n, double *c )
2813 {
2814 	return( vips__relational_vec( in, out,
2815 		VIPS_OPERATION_RELATIONAL_MOREEQ, c, n ) );
2816 }
2817 
2818 int
im_equalconst(IMAGE * in,IMAGE * out,double c)2819 im_equalconst( IMAGE *in, IMAGE *out, double c )
2820 {
2821 	return( im_equal_vec( in, out, 1, &c ) );
2822 }
2823 
2824 int
im_notequalconst(IMAGE * in,IMAGE * out,double c)2825 im_notequalconst( IMAGE *in, IMAGE *out, double c )
2826 {
2827 	return( im_notequal_vec( in, out, 1, &c ) );
2828 }
2829 
2830 int
im_lessconst(IMAGE * in,IMAGE * out,double c)2831 im_lessconst( IMAGE *in, IMAGE *out, double c )
2832 {
2833 	return( im_less_vec( in, out, 1, &c ) );
2834 }
2835 
2836 int
im_lesseqconst(IMAGE * in,IMAGE * out,double c)2837 im_lesseqconst( IMAGE *in, IMAGE *out, double c )
2838 {
2839 	return( im_lesseq_vec( in, out, 1, &c ) );
2840 }
2841 
2842 int
im_moreconst(IMAGE * in,IMAGE * out,double c)2843 im_moreconst( IMAGE *in, IMAGE *out, double c )
2844 {
2845 	return( im_more_vec( in, out, 1, &c ) );
2846 }
2847 
2848 int
im_moreeqconst(IMAGE * in,IMAGE * out,double c)2849 im_moreeqconst( IMAGE *in, IMAGE *out, double c )
2850 {
2851 	return( im_moreeq_vec( in, out, 1, &c ) );
2852 }
2853 
2854 int
im_remainder(IMAGE * in1,IMAGE * in2,IMAGE * out)2855 im_remainder( IMAGE *in1, IMAGE *in2, IMAGE *out )
2856 {
2857 	VipsImage *t;
2858 
2859 	if( vips_remainder( in1, in2, &t,
2860 		NULL ) )
2861 		return( -1 );
2862 	if( vips_image_write( t, out ) ) {
2863 		g_object_unref( t );
2864 		return( -1 );
2865 	}
2866 	g_object_unref( t );
2867 
2868 	return( 0 );
2869 }
2870 
2871 int
im_remainder_vec(IMAGE * in,IMAGE * out,int n,double * c)2872 im_remainder_vec( IMAGE *in, IMAGE *out, int n, double *c )
2873 {
2874 	VipsImage *t;
2875 
2876 	if( vips_remainder_const( in, &t, c, n,
2877 		NULL ) )
2878 		return( -1 );
2879 	if( vips_image_write( t, out ) ) {
2880 		g_object_unref( t );
2881 		return( -1 );
2882 	}
2883 	g_object_unref( t );
2884 
2885 	return( 0 );
2886 }
2887 
2888 int
im_remainderconst(IMAGE * in,IMAGE * out,double c)2889 im_remainderconst( IMAGE *in, IMAGE *out, double c )
2890 {
2891 	return( im_remainder_vec( in, out, 1, &c ) );
2892 }
2893 
2894 static int
vips__boolean(IMAGE * in1,IMAGE * in2,IMAGE * out,VipsOperationBoolean boolean)2895 vips__boolean( IMAGE *in1, IMAGE *in2, IMAGE *out,
2896 	VipsOperationBoolean boolean )
2897 {
2898 	VipsImage *t;
2899 
2900 	if( vips_boolean( in1, in2, &t, boolean,
2901 		NULL ) )
2902 		return( -1 );
2903 	if( vips_image_write( t, out ) ) {
2904 		g_object_unref( t );
2905 		return( -1 );
2906 	}
2907 	g_object_unref( t );
2908 
2909 	return( 0 );
2910 }
2911 
2912 int
im_andimage(VipsImage * in1,VipsImage * in2,VipsImage * out)2913 im_andimage( VipsImage *in1, VipsImage *in2, VipsImage *out )
2914 {
2915 	return( vips__boolean( in1, in2, out, VIPS_OPERATION_BOOLEAN_AND ) );
2916 }
2917 
2918 int
im_orimage(VipsImage * in1,VipsImage * in2,VipsImage * out)2919 im_orimage( VipsImage *in1, VipsImage *in2, VipsImage *out )
2920 {
2921 	return( vips__boolean( in1, in2, out, VIPS_OPERATION_BOOLEAN_OR ) );
2922 }
2923 
2924 int
im_eorimage(VipsImage * in1,VipsImage * in2,VipsImage * out)2925 im_eorimage( VipsImage *in1, VipsImage *in2, VipsImage *out )
2926 {
2927 	return( vips__boolean( in1, in2, out, VIPS_OPERATION_BOOLEAN_EOR ) );
2928 }
2929 
2930 static int
vips__boolean_vec(IMAGE * in,IMAGE * out,VipsOperationBoolean boolean,double * c,int n)2931 vips__boolean_vec( IMAGE *in, IMAGE *out,
2932 	VipsOperationBoolean boolean, double *c, int n )
2933 {
2934 	VipsImage *t;
2935 
2936 	if( vips_boolean_const( in, &t, boolean, c, n,
2937 		NULL ) )
2938 		return( -1 );
2939 	if( vips_image_write( t, out ) ) {
2940 		g_object_unref( t );
2941 		return( -1 );
2942 	}
2943 	g_object_unref( t );
2944 
2945 	return( 0 );
2946 }
2947 
2948 int
im_andimage_vec(VipsImage * in,VipsImage * out,int n,double * c)2949 im_andimage_vec( VipsImage *in, VipsImage *out, int n, double *c )
2950 {
2951 	return( vips__boolean_vec( in, out,
2952 		VIPS_OPERATION_BOOLEAN_AND, c, n ) );
2953 }
2954 
2955 int
im_orimage_vec(VipsImage * in,VipsImage * out,int n,double * c)2956 im_orimage_vec( VipsImage *in, VipsImage *out, int n, double *c )
2957 {
2958 	return( vips__boolean_vec( in, out,
2959 		VIPS_OPERATION_BOOLEAN_OR, c, n ) );
2960 }
2961 
2962 int
im_eorimage_vec(VipsImage * in,VipsImage * out,int n,double * c)2963 im_eorimage_vec( VipsImage *in, VipsImage *out, int n, double *c )
2964 {
2965 	return( vips__boolean_vec( in, out,
2966 		VIPS_OPERATION_BOOLEAN_EOR, c, n ) );
2967 }
2968 
2969 int
im_shiftleft_vec(IMAGE * in,IMAGE * out,int n,double * c)2970 im_shiftleft_vec( IMAGE *in, IMAGE *out, int n, double *c )
2971 {
2972 	return( vips__boolean_vec( in, out,
2973 		VIPS_OPERATION_BOOLEAN_LSHIFT, c, n ) );
2974 }
2975 
2976 int
im_shiftright_vec(IMAGE * in,IMAGE * out,int n,double * c)2977 im_shiftright_vec( IMAGE *in, IMAGE *out, int n, double *c )
2978 {
2979 	return( vips__boolean_vec( in, out,
2980 		VIPS_OPERATION_BOOLEAN_RSHIFT, c, n ) );
2981 }
2982 
2983 int
im_andimageconst(IMAGE * in,IMAGE * out,double c)2984 im_andimageconst( IMAGE *in, IMAGE *out, double c )
2985 {
2986 	return( im_andimage_vec( in, out, 1, &c ) );
2987 }
2988 
2989 int
im_orimageconst(IMAGE * in,IMAGE * out,double c)2990 im_orimageconst( IMAGE *in, IMAGE *out, double c )
2991 {
2992 	return( im_orimage_vec( in, out, 1, &c ) );
2993 }
2994 
2995 int
im_eorimageconst(IMAGE * in,IMAGE * out,double c)2996 im_eorimageconst( IMAGE *in, IMAGE *out, double c )
2997 {
2998 	return( im_eorimage_vec( in, out, 1, &c ) );
2999 }
3000 
3001 int
im_shiftleft(IMAGE * in,IMAGE * out,int n)3002 im_shiftleft( IMAGE *in, IMAGE *out, int n )
3003 {
3004 	double c = n;
3005 
3006 	return( im_shiftleft_vec( in, out, 1, &c ) );
3007 }
3008 
3009 int
im_shiftright(IMAGE * in,IMAGE * out,int n)3010 im_shiftright( IMAGE *in, IMAGE *out, int n )
3011 {
3012 	double c = n;
3013 
3014 	return( im_shiftright_vec( in, out, 1, &c ) );
3015 }
3016 
3017 static int
vips__math2_vec(IMAGE * in,IMAGE * out,VipsOperationMath2 math2,double * c,int n)3018 vips__math2_vec( IMAGE *in, IMAGE *out,
3019 	VipsOperationMath2 math2, double *c, int n )
3020 {
3021 	VipsImage *t;
3022 
3023 	if( vips_math2_const( in, &t, math2, c, n,
3024 		NULL ) )
3025 		return( -1 );
3026 	if( vips_image_write( t, out ) ) {
3027 		g_object_unref( t );
3028 		return( -1 );
3029 	}
3030 	g_object_unref( t );
3031 
3032 	return( 0 );
3033 }
3034 
3035 int
im_powtra_vec(VipsImage * in,VipsImage * out,int n,double * c)3036 im_powtra_vec( VipsImage *in, VipsImage *out, int n, double *c )
3037 {
3038 	return( vips__math2_vec( in, out, VIPS_OPERATION_MATH2_POW, c, n ) );
3039 }
3040 
3041 int
im_powtra(IMAGE * in,IMAGE * out,double c)3042 im_powtra( IMAGE *in, IMAGE *out, double c )
3043 {
3044 	return( im_powtra_vec( in, out, 1, &c ) );
3045 }
3046 
3047 int
im_expntra_vec(IMAGE * in,IMAGE * out,int n,double * c)3048 im_expntra_vec( IMAGE *in, IMAGE *out, int n, double *c )
3049 {
3050 	return( vips__math2_vec( in, out, VIPS_OPERATION_MATH2_WOP, c, n ) );
3051 }
3052 
3053 int
im_expntra(IMAGE * in,IMAGE * out,double c)3054 im_expntra( IMAGE *in, IMAGE *out, double c )
3055 {
3056 	return( im_expntra_vec( in, out, 1, &c ) );
3057 }
3058 
3059 int
im_ifthenelse(VipsImage * c,VipsImage * a,VipsImage * b,VipsImage * out)3060 im_ifthenelse( VipsImage *c, VipsImage *a, VipsImage *b, VipsImage *out )
3061 {
3062 	VipsImage *t;
3063 
3064 	if( vips_ifthenelse( c, a, b, &t,
3065 		NULL ) )
3066 		return( -1 );
3067 	if( vips_image_write( t, out ) ) {
3068 		g_object_unref( t );
3069 		return( -1 );
3070 	}
3071 	g_object_unref( t );
3072 
3073 	return( 0 );
3074 }
3075 
3076 int
im_blend(VipsImage * c,VipsImage * a,VipsImage * b,VipsImage * out)3077 im_blend( VipsImage *c, VipsImage *a, VipsImage *b, VipsImage *out )
3078 {
3079 	VipsImage *t;
3080 
3081 	if( vips_ifthenelse( c, a, b, &t,
3082 		"blend", TRUE,
3083 		NULL ) )
3084 		return( -1 );
3085 	if( vips_image_write( t, out ) ) {
3086 		g_object_unref( t );
3087 		return( -1 );
3088 	}
3089 	g_object_unref( t );
3090 
3091 	return( 0 );
3092 }
3093 
3094 static int
vips__complex(VipsImage * in,VipsImage * out,VipsOperationComplex cmplx)3095 vips__complex( VipsImage *in, VipsImage *out, VipsOperationComplex cmplx )
3096 {
3097 	VipsImage *t;
3098 
3099 	if( vips_complex( in, &t, cmplx,
3100 		NULL ) )
3101 		return( -1 );
3102 	if( vips_image_write( t, out ) ) {
3103 		g_object_unref( t );
3104 		return( -1 );
3105 	}
3106 	g_object_unref( t );
3107 
3108 	return( 0 );
3109 }
3110 
3111 int
im_c2amph(IMAGE * in,IMAGE * out)3112 im_c2amph( IMAGE *in, IMAGE *out )
3113 {
3114 	return( vips__complex( in, out, VIPS_OPERATION_COMPLEX_POLAR ) );
3115 }
3116 
3117 int
im_c2rect(IMAGE * in,IMAGE * out)3118 im_c2rect( IMAGE *in, IMAGE *out )
3119 {
3120 	return( vips__complex( in, out, VIPS_OPERATION_COMPLEX_RECT ) );
3121 }
3122 
3123 static int
vips__complexget(VipsImage * in,VipsImage * out,VipsOperationComplexget get)3124 vips__complexget( VipsImage *in, VipsImage *out, VipsOperationComplexget get )
3125 {
3126 	VipsImage *t;
3127 
3128 	if( vips_complexget( in, &t, get,
3129 		NULL ) )
3130 		return( -1 );
3131 	if( vips_image_write( t, out ) ) {
3132 		g_object_unref( t );
3133 		return( -1 );
3134 	}
3135 	g_object_unref( t );
3136 
3137 	return( 0 );
3138 }
3139 
3140 int
im_c2real(IMAGE * in,IMAGE * out)3141 im_c2real( IMAGE *in, IMAGE *out )
3142 {
3143 	return( vips__complexget( in, out, VIPS_OPERATION_COMPLEXGET_REAL ) );
3144 }
3145 
3146 int
im_c2imag(IMAGE * in,IMAGE * out)3147 im_c2imag( IMAGE *in, IMAGE *out )
3148 {
3149 	return( vips__complexget( in, out, VIPS_OPERATION_COMPLEXGET_IMAG ) );
3150 }
3151 
3152 int
im_ri2c(IMAGE * in1,IMAGE * in2,IMAGE * out)3153 im_ri2c( IMAGE *in1, IMAGE *in2, IMAGE *out )
3154 {
3155 	VipsImage *x;
3156 
3157 	if( vips_call( "complexform", in1, in2, &x, NULL ) )
3158 		return( -1 );
3159 	if( vips_image_write( x, out ) ) {
3160 		g_object_unref( x );
3161 		return( -1 );
3162 	}
3163 	g_object_unref( x );
3164 
3165 	return( 0 );
3166 }
3167 
3168 int
im_cache(VipsImage * in,VipsImage * out,int width,int height,int max)3169 im_cache( VipsImage *in, VipsImage *out,
3170 	int width, int height, int max )
3171 {
3172 	return( vips_sink_screen( in, out, NULL,
3173 		width, height, max, 0, NULL, NULL ) );
3174 }
3175 
3176 int
im_argb2rgba(VipsImage * in,VipsImage * out)3177 im_argb2rgba( VipsImage *in, VipsImage *out )
3178 {
3179 	/* No longer exists, just a null op.
3180 	 */
3181 	return( vips_image_write( in, out ) );
3182 }
3183 
3184 int
im_shrink(VipsImage * in,VipsImage * out,double xshrink,double yshrink)3185 im_shrink( VipsImage *in, VipsImage *out, double xshrink, double yshrink )
3186 {
3187 	VipsImage *x;
3188 
3189 	if( vips_shrink( in, &x, xshrink, yshrink, NULL ) )
3190 		return( -1 );
3191 	if( vips_image_write( x, out ) ) {
3192 		g_object_unref( x );
3193 		return( -1 );
3194 	}
3195 	g_object_unref( x );
3196 
3197 	return( 0 );
3198 }
3199 
3200 int
im_eye(IMAGE * out,const int xsize,const int ysize,const double factor)3201 im_eye( IMAGE *out, const int xsize, const int ysize, const double factor )
3202 {
3203 	VipsImage *x;
3204 
3205 	if( vips_eye( &x, xsize, ysize,
3206 		"factor", factor,
3207 		"uchar", TRUE,
3208 		NULL ) )
3209 		return( -1 );
3210 	if( vips_image_write( x, out ) ) {
3211 		g_object_unref( x );
3212 		return( -1 );
3213 	}
3214 	g_object_unref( x );
3215 
3216 	return( 0 );
3217 }
3218 
3219 int
im_feye(IMAGE * out,const int xsize,const int ysize,const double factor)3220 im_feye( IMAGE *out, const int xsize, const int ysize, const double factor )
3221 {
3222 	VipsImage *x;
3223 
3224 	if( vips_eye( &x, xsize, ysize,
3225 		"factor", factor,
3226 		NULL ) )
3227 		return( -1 );
3228 	if( vips_image_write( x, out ) ) {
3229 		g_object_unref( x );
3230 		return( -1 );
3231 	}
3232 	g_object_unref( x );
3233 
3234 	return( 0 );
3235 }
3236 
3237 int
im_grey(IMAGE * out,const int xsize,const int ysize)3238 im_grey( IMAGE *out, const int xsize, const int ysize )
3239 {
3240 	VipsImage *x;
3241 
3242 	if( vips_grey( &x, xsize, ysize,
3243 		"uchar", TRUE,
3244 		NULL ) )
3245 		return( -1 );
3246 	if( vips_image_write( x, out ) ) {
3247 		g_object_unref( x );
3248 		return( -1 );
3249 	}
3250 	g_object_unref( x );
3251 
3252 	return( 0 );
3253 }
3254 
3255 int
im_fgrey(IMAGE * out,const int xsize,const int ysize)3256 im_fgrey( IMAGE *out, const int xsize, const int ysize )
3257 {
3258 	VipsImage *x;
3259 
3260 	if( vips_grey( &x, xsize, ysize,
3261 		NULL ) )
3262 		return( -1 );
3263 	if( vips_image_write( x, out ) ) {
3264 		g_object_unref( x );
3265 		return( -1 );
3266 	}
3267 	g_object_unref( x );
3268 
3269 	return( 0 );
3270 }
3271 
3272 int
im_buildlut(DOUBLEMASK * input,VipsImage * out)3273 im_buildlut( DOUBLEMASK *input, VipsImage *out )
3274 {
3275 	VipsImage *mat;
3276 	VipsImage *x;
3277 
3278 	mat = vips_image_new();
3279 	if( im_mask2vips( input, mat ) )
3280 		return( -1 );
3281 	if( vips_buildlut( mat, &x,
3282 		NULL ) ) {
3283 		g_object_unref( mat );
3284 		return( -1 );
3285 	}
3286 	g_object_unref( mat );
3287 	if( vips_image_write( x, out ) ) {
3288 		g_object_unref( x );
3289 		return( -1 );
3290 	}
3291 	g_object_unref( x );
3292 
3293 	return( 0 );
3294 }
3295 
3296 int
im_invertlut(DOUBLEMASK * input,VipsImage * out,int size)3297 im_invertlut( DOUBLEMASK *input, VipsImage *out, int size )
3298 {
3299 	VipsImage *mat;
3300 	VipsImage *x;
3301 
3302 	mat = vips_image_new();
3303 	if( im_mask2vips( input, mat ) )
3304 		return( -1 );
3305 	if( vips_invertlut( mat, &x,
3306 		"size", size,
3307 		NULL ) ) {
3308 		g_object_unref( mat );
3309 		return( -1 );
3310 	}
3311 	g_object_unref( mat );
3312 	if( vips_image_write( x, out ) ) {
3313 		g_object_unref( x );
3314 		return( -1 );
3315 	}
3316 	g_object_unref( x );
3317 
3318 	return( 0 );
3319 }
3320 
3321 int
im_tone_build_range(IMAGE * out,int in_max,int out_max,double Lb,double Lw,double Ps,double Pm,double Ph,double S,double M,double H)3322 im_tone_build_range( IMAGE *out,
3323 	int in_max, int out_max,
3324 	double Lb, double Lw,
3325 	double Ps, double Pm, double Ph,
3326 	double S, double M, double H )
3327 {
3328 	VipsImage *t;
3329 
3330 	if( vips_tonelut( &t,
3331 		"in_max", in_max,
3332 		"out_max", out_max,
3333 		"Lb", Lb,
3334 		"Lw", Lw,
3335 		"Ps", Ps,
3336 		"Pm", Pm,
3337 		"Ph", Ph,
3338 		"S", S,
3339 		"M", M,
3340 		"H", H,
3341 		NULL ) )
3342 		return( -1 );
3343 	if( vips_image_write( t, out ) ) {
3344 		g_object_unref( t );
3345 		return( -1 );
3346 	}
3347 	g_object_unref( t );
3348 
3349 	return( 0 );
3350 }
3351 
3352 int
im_tone_build(IMAGE * out,double Lb,double Lw,double Ps,double Pm,double Ph,double S,double M,double H)3353 im_tone_build( IMAGE *out,
3354 	double Lb, double Lw,
3355 	double Ps, double Pm, double Ph,
3356 	double S, double M, double H )
3357 {
3358 	IMAGE *t1;
3359 
3360 	if( !(t1 = im_open_local( out, "im_tone_build", "p" )) ||
3361 		im_tone_build_range( t1, 32767, 32767,
3362 			Lb, Lw, Ps, Pm, Ph, S, M, H ) ||
3363 		im_clip2fmt( t1, out, IM_BANDFMT_SHORT ) )
3364 		return( -1 );
3365 
3366 	return( 0 );
3367 }
3368 
3369 int
im_rightshift_size(IMAGE * in,IMAGE * out,int xshift,int yshift,int band_fmt)3370 im_rightshift_size( IMAGE *in, IMAGE *out,
3371 	int xshift, int yshift, int band_fmt )
3372 {
3373 	VipsImage **t = (VipsImage **)
3374 		vips_object_local_array( VIPS_OBJECT( out ), 2 );
3375 
3376 	if( vips_shrink( in, &t[0], 1 << xshift, 1 << yshift, NULL ) ||
3377 		vips_cast( t[0], &t[1], band_fmt, NULL ) ||
3378 		vips_image_write( t[1], out ) )
3379 		return( -1 );
3380 
3381 	return( 0 );
3382 }
3383 
3384 int
im_Lab2XYZ_temp(IMAGE * in,IMAGE * out,double X0,double Y0,double Z0)3385 im_Lab2XYZ_temp( IMAGE *in, IMAGE *out, double X0, double Y0, double Z0 )
3386 {
3387 	VipsArea *temp;
3388 	VipsImage *x;
3389 
3390 	temp = VIPS_AREA( vips_array_double_newv( 3, X0, Y0, Z0 ) );
3391 	if( vips_Lab2XYZ( in, &x, "temp", temp, NULL ) ) {
3392 		vips_area_unref( temp );
3393 		return( -1 );
3394 	}
3395 	vips_area_unref( temp );
3396 
3397 	if( vips_image_write( x, out ) ) {
3398 		g_object_unref( x );
3399 		return( -1 );
3400 	}
3401 	g_object_unref( x );
3402 
3403 	return( 0 );
3404 }
3405 
3406 int
im_Lab2XYZ(IMAGE * in,IMAGE * out)3407 im_Lab2XYZ( IMAGE *in, IMAGE *out )
3408 {
3409 	VipsImage *x;
3410 
3411 	if( vips_Lab2XYZ( in, &x, NULL ) )
3412 		return( -1 );
3413 	if( vips_image_write( x, out ) ) {
3414 		g_object_unref( x );
3415 		return( -1 );
3416 	}
3417 	g_object_unref( x );
3418 
3419 	return( 0 );
3420 }
3421 
3422 int
im_XYZ2Lab_temp(IMAGE * in,IMAGE * out,double X0,double Y0,double Z0)3423 im_XYZ2Lab_temp( IMAGE *in, IMAGE *out, double X0, double Y0, double Z0 )
3424 {
3425 	double ary[3];
3426 	VipsArea *temp;
3427 	VipsImage *x;
3428 
3429 	ary[0] = X0;
3430 	ary[1] = Y0;
3431 	ary[2] = Z0;
3432 	temp = VIPS_AREA( vips_array_double_new( ary, 3 ) );
3433 	if( vips_XYZ2Lab( in, &x, "temp", temp, NULL ) ) {
3434 		vips_area_unref( temp );
3435 		return( -1 );
3436 	}
3437 	vips_area_unref( temp );
3438 
3439 	if( vips_image_write( x, out ) ) {
3440 		g_object_unref( x );
3441 		return( -1 );
3442 	}
3443 	g_object_unref( x );
3444 
3445 	return( 0 );
3446 }
3447 
3448 int
im_XYZ2Lab(IMAGE * in,IMAGE * out)3449 im_XYZ2Lab( IMAGE *in, IMAGE *out )
3450 {
3451 	VipsImage *x;
3452 
3453 	if( vips_XYZ2Lab( in, &x, NULL ) )
3454 		return( -1 );
3455 	if( vips_image_write( x, out ) ) {
3456 		g_object_unref( x );
3457 		return( -1 );
3458 	}
3459 	g_object_unref( x );
3460 
3461 	return( 0 );
3462 }
3463 
3464 int
im_Lab2LCh(IMAGE * in,IMAGE * out)3465 im_Lab2LCh( IMAGE *in, IMAGE *out )
3466 {
3467 	VipsImage *x;
3468 
3469 	if( vips_Lab2LCh( in, &x, NULL ) )
3470 		return( -1 );
3471 	if( vips_image_write( x, out ) ) {
3472 		g_object_unref( x );
3473 		return( -1 );
3474 	}
3475 	g_object_unref( x );
3476 
3477 	return( 0 );
3478 }
3479 
3480 int
im_LCh2Lab(IMAGE * in,IMAGE * out)3481 im_LCh2Lab( IMAGE *in, IMAGE *out )
3482 {
3483 	VipsImage *x;
3484 
3485 	if( vips_LCh2Lab( in, &x, NULL ) )
3486 		return( -1 );
3487 	if( vips_image_write( x, out ) ) {
3488 		g_object_unref( x );
3489 		return( -1 );
3490 	}
3491 	g_object_unref( x );
3492 
3493 	return( 0 );
3494 }
3495 
3496 int
im_LCh2UCS(IMAGE * in,IMAGE * out)3497 im_LCh2UCS( IMAGE *in, IMAGE *out )
3498 {
3499 	VipsImage *x;
3500 
3501 	if( vips_LCh2CMC( in, &x, NULL ) )
3502 		return( -1 );
3503 	if( vips_image_write( x, out ) ) {
3504 		g_object_unref( x );
3505 		return( -1 );
3506 	}
3507 	g_object_unref( x );
3508 
3509 	return( 0 );
3510 }
3511 
3512 int
im_UCS2LCh(IMAGE * in,IMAGE * out)3513 im_UCS2LCh( IMAGE *in, IMAGE *out )
3514 {
3515 	VipsImage *x;
3516 
3517 	if( vips_CMC2LCh( in, &x, NULL ) )
3518 		return( -1 );
3519 	if( vips_image_write( x, out ) ) {
3520 		g_object_unref( x );
3521 		return( -1 );
3522 	}
3523 	g_object_unref( x );
3524 
3525 	return( 0 );
3526 }
3527 
3528 int
im_XYZ2Yxy(IMAGE * in,IMAGE * out)3529 im_XYZ2Yxy( IMAGE *in, IMAGE *out )
3530 {
3531 	VipsImage *x;
3532 
3533 	if( vips_XYZ2Yxy( in, &x, NULL ) )
3534 		return( -1 );
3535 	if( vips_image_write( x, out ) ) {
3536 		g_object_unref( x );
3537 		return( -1 );
3538 	}
3539 	g_object_unref( x );
3540 
3541 	return( 0 );
3542 }
3543 
3544 int
im_Yxy2XYZ(IMAGE * in,IMAGE * out)3545 im_Yxy2XYZ( IMAGE *in, IMAGE *out )
3546 {
3547 	VipsImage *x;
3548 
3549 	if( vips_Yxy2XYZ( in, &x, NULL ) )
3550 		return( -1 );
3551 	if( vips_image_write( x, out ) ) {
3552 		g_object_unref( x );
3553 		return( -1 );
3554 	}
3555 	g_object_unref( x );
3556 
3557 	return( 0 );
3558 }
3559 
3560 int
im_float2rad(IMAGE * in,IMAGE * out)3561 im_float2rad( IMAGE *in, IMAGE *out )
3562 {
3563 	VipsImage *x;
3564 
3565 	if( vips_float2rad( in, &x, NULL ) )
3566 		return( -1 );
3567 	if( vips_image_write( x, out ) ) {
3568 		g_object_unref( x );
3569 		return( -1 );
3570 	}
3571 	g_object_unref( x );
3572 
3573 	return( 0 );
3574 }
3575 
3576 int
im_rad2float(IMAGE * in,IMAGE * out)3577 im_rad2float( IMAGE *in, IMAGE *out )
3578 {
3579 	VipsImage *x;
3580 
3581 	if( vips_rad2float( in, &x, NULL ) )
3582 		return( -1 );
3583 	if( vips_image_write( x, out ) ) {
3584 		g_object_unref( x );
3585 		return( -1 );
3586 	}
3587 	g_object_unref( x );
3588 
3589 	return( 0 );
3590 }
3591 
3592 int
im_Lab2LabQ(IMAGE * in,IMAGE * out)3593 im_Lab2LabQ( IMAGE *in, IMAGE *out )
3594 {
3595 	VipsImage *x;
3596 
3597 	if( vips_Lab2LabQ( in, &x, NULL ) )
3598 		return( -1 );
3599 	if( vips_image_write( x, out ) ) {
3600 		g_object_unref( x );
3601 		return( -1 );
3602 	}
3603 	g_object_unref( x );
3604 
3605 	return( 0 );
3606 }
3607 
3608 int
im_LabQ2Lab(IMAGE * in,IMAGE * out)3609 im_LabQ2Lab( IMAGE *in, IMAGE *out )
3610 {
3611 	VipsImage *x;
3612 
3613 	if( vips_LabQ2Lab( in, &x, NULL ) )
3614 		return( -1 );
3615 	if( vips_image_write( x, out ) ) {
3616 		g_object_unref( x );
3617 		return( -1 );
3618 	}
3619 	g_object_unref( x );
3620 
3621 	return( 0 );
3622 }
3623 
3624 int
im_Lab2LabS(IMAGE * in,IMAGE * out)3625 im_Lab2LabS( IMAGE *in, IMAGE *out )
3626 {
3627 	VipsImage *x;
3628 
3629 	if( vips_Lab2LabS( in, &x, NULL ) )
3630 		return( -1 );
3631 	if( vips_image_write( x, out ) ) {
3632 		g_object_unref( x );
3633 		return( -1 );
3634 	}
3635 	g_object_unref( x );
3636 
3637 	return( 0 );
3638 }
3639 
3640 int
im_LabS2Lab(IMAGE * in,IMAGE * out)3641 im_LabS2Lab( IMAGE *in, IMAGE *out )
3642 {
3643 	VipsImage *x;
3644 
3645 	if( vips_LabS2Lab( in, &x, NULL ) )
3646 		return( -1 );
3647 	if( vips_image_write( x, out ) ) {
3648 		g_object_unref( x );
3649 		return( -1 );
3650 	}
3651 	g_object_unref( x );
3652 
3653 	return( 0 );
3654 }
3655 
3656 int
im_LabQ2LabS(IMAGE * in,IMAGE * out)3657 im_LabQ2LabS( IMAGE *in, IMAGE *out )
3658 {
3659 	VipsImage *x;
3660 
3661 	if( vips_LabQ2LabS( in, &x, NULL ) )
3662 		return( -1 );
3663 	if( vips_image_write( x, out ) ) {
3664 		g_object_unref( x );
3665 		return( -1 );
3666 	}
3667 	g_object_unref( x );
3668 
3669 	return( 0 );
3670 }
3671 
3672 int
im_LabS2LabQ(IMAGE * in,IMAGE * out)3673 im_LabS2LabQ( IMAGE *in, IMAGE *out )
3674 {
3675 	VipsImage *x;
3676 
3677 	if( vips_LabS2LabQ( in, &x, NULL ) )
3678 		return( -1 );
3679 	if( vips_image_write( x, out ) ) {
3680 		g_object_unref( x );
3681 		return( -1 );
3682 	}
3683 	g_object_unref( x );
3684 
3685 	return( 0 );
3686 }
3687 
3688 int
im_Lab2disp(IMAGE * in,IMAGE * out,struct im_col_display * disp)3689 im_Lab2disp( IMAGE *in, IMAGE *out, struct im_col_display *disp )
3690 {
3691 	IMAGE *t[1];
3692 
3693 	if( im_open_local_array( out, t, 1, "im_Lab2disp:1", "p" ) ||
3694 		im_Lab2XYZ( in, t[0] ) ||
3695 		im_XYZ2disp( t[0], out, disp ) )
3696 		return( -1 );
3697 
3698 	return( 0 );
3699 }
3700 
3701 int
im_dECMC_fromdisp(IMAGE * im1,IMAGE * im2,IMAGE * out,struct im_col_display * d)3702 im_dECMC_fromdisp( IMAGE *im1, IMAGE *im2,
3703 	IMAGE *out, struct im_col_display *d )
3704 {
3705 	IMAGE *t[4];
3706 
3707 	if( im_open_local_array( out, t, 4, "im_dECMC_fromdisp:1", "p" ) ||
3708 		im_disp2XYZ( im1, t[0], d ) ||
3709 		im_XYZ2Lab( t[0], t[1] ) ||
3710 		im_disp2XYZ( im2, t[2], d ) ||
3711 		im_XYZ2Lab( t[2], t[3] ) ||
3712 		im_dECMC_fromLab( t[1], t[3], out ) )
3713 		return( -1 );
3714 
3715 	return( 0 );
3716 }
3717 
3718 int
im_dE_fromdisp(IMAGE * im1,IMAGE * im2,IMAGE * out,struct im_col_display * d)3719 im_dE_fromdisp( IMAGE *im1, IMAGE *im2, IMAGE *out, struct im_col_display *d )
3720 {
3721 	IMAGE *t[2];
3722 
3723 	if( im_open_local_array( out, t, 2, "im_dE_fromdisp:1", "p" ) ||
3724 		im_disp2XYZ( im1, t[0], d ) ||
3725 		im_disp2XYZ( im2, t[1], d ) ||
3726 		im_dE_fromXYZ( t[0], t[1], out ) )
3727 		return( -1 );
3728 
3729 	return( 0 );
3730 }
3731 
3732 int
im_disp2Lab(IMAGE * in,IMAGE * out,struct im_col_display * d)3733 im_disp2Lab( IMAGE *in, IMAGE *out, struct im_col_display *d )
3734 {
3735 	VipsImage *t[1];
3736 
3737 	if( im_open_local_array( out, t, 1, "im_disp2Lab:1", "p" ) ||
3738 		im_disp2XYZ( in, t[0], d ) ||
3739 		im_XYZ2Lab( t[0], out ) )
3740 		return( -1 );
3741 
3742 	return( 0 );
3743 }
3744 
3745 int
im_sRGB2XYZ(IMAGE * in,IMAGE * out)3746 im_sRGB2XYZ( IMAGE *in, IMAGE *out )
3747 {
3748 	VipsImage **t = (VipsImage **)
3749 		vips_object_local_array( (VipsObject *) out, 2 );
3750 
3751 	if( vips_sRGB2scRGB( in, &t[0], NULL ) ||
3752 		vips_scRGB2XYZ( t[0], &t[1], NULL ) ||
3753 		vips_image_write( t[1], out ) )
3754 		return( -1 );
3755 
3756 	return( 0 );
3757 }
3758 
3759 int
im_XYZ2sRGB(IMAGE * in,IMAGE * out)3760 im_XYZ2sRGB( IMAGE *in, IMAGE *out )
3761 {
3762 	VipsImage **t = (VipsImage **)
3763 		vips_object_local_array( (VipsObject *) out, 2 );
3764 
3765 	if( vips_XYZ2scRGB( in, &t[0], NULL ) ||
3766 		vips_scRGB2sRGB( t[0], &t[1], NULL ) ||
3767 		vips_image_write( t[1], out ) )
3768 		return( -1 );
3769 
3770 	return( 0 );
3771 }
3772 
3773 int
im_LabQ2sRGB(IMAGE * in,IMAGE * out)3774 im_LabQ2sRGB( IMAGE *in, IMAGE *out )
3775 {
3776 	VipsImage *x;
3777 
3778 	if( vips_LabQ2sRGB( in, &x, NULL ) )
3779 		return( -1 );
3780 	if( vips_image_write( x, out ) ) {
3781 		g_object_unref( x );
3782 		return( -1 );
3783 	}
3784 	g_object_unref( x );
3785 
3786 	return( 0 );
3787 }
3788 
3789 int
im_icc_transform(VipsImage * in,VipsImage * out,const char * input_profile_filename,const char * output_profile_filename,VipsIntent intent)3790 im_icc_transform( VipsImage *in, VipsImage *out,
3791 	const char *input_profile_filename,
3792 	const char *output_profile_filename,
3793 	VipsIntent intent )
3794 {
3795 	VipsImage *x;
3796 
3797 	if( vips_icc_transform( in, &x, output_profile_filename,
3798 		"input_profile", input_profile_filename,
3799 		"intent", intent,
3800 		NULL ) )
3801 		return( -1 );
3802 	if( vips_image_write( x, out ) ) {
3803 		g_object_unref( x );
3804 		return( -1 );
3805 	}
3806 	g_object_unref( x );
3807 
3808 	return( 0 );
3809 }
3810 
3811 int
im_icc_import(VipsImage * in,VipsImage * out,const char * input_profile_filename,VipsIntent intent)3812 im_icc_import( VipsImage *in, VipsImage *out,
3813 	const char *input_profile_filename, VipsIntent intent )
3814 {
3815 	VipsImage *x;
3816 
3817 	if( vips_icc_import( in, &x,
3818 		"input_profile", input_profile_filename,
3819 		"intent", intent,
3820 		NULL ) )
3821 		return( -1 );
3822 	if( vips_image_write( x, out ) ) {
3823 		g_object_unref( x );
3824 		return( -1 );
3825 	}
3826 	g_object_unref( x );
3827 
3828 	return( 0 );
3829 }
3830 
3831 int
im_icc_import_embedded(VipsImage * in,VipsImage * out,VipsIntent intent)3832 im_icc_import_embedded( VipsImage *in, VipsImage *out, VipsIntent intent )
3833 {
3834 	VipsImage *x;
3835 
3836 	if( vips_icc_import( in, &x,
3837 		"embedded", TRUE,
3838 		"intent", intent,
3839 		NULL ) )
3840 		return( -1 );
3841 	if( vips_image_write( x, out ) ) {
3842 		g_object_unref( x );
3843 		return( -1 );
3844 	}
3845 	g_object_unref( x );
3846 
3847 	return( 0 );
3848 }
3849 
3850 int
im_icc_export_depth(VipsImage * in,VipsImage * out,int depth,const char * output_profile_filename,VipsIntent intent)3851 im_icc_export_depth( VipsImage *in, VipsImage *out, int depth,
3852 	const char *output_profile_filename, VipsIntent intent )
3853 {
3854 	VipsImage *x;
3855 
3856 	if( vips_icc_export( in, &x,
3857 		"output_profile", output_profile_filename,
3858 		"depth", depth,
3859 		"intent", intent,
3860 		NULL ) )
3861 		return( -1 );
3862 	if( vips_image_write( x, out ) ) {
3863 		g_object_unref( x );
3864 		return( -1 );
3865 	}
3866 	g_object_unref( x );
3867 
3868 	return( 0 );
3869 }
3870 
3871 /**
3872  * im_LabQ2XYZ:
3873  * @in: input image
3874  * @out: output image
3875  *
3876  * Convert an image from LabQ (Coding == IM_CODING_LABQ) to XYZ.
3877  *
3878  * Returns: 0 on success, -1 on error.
3879  */
3880 int
im_LabQ2XYZ(IMAGE * in,IMAGE * out)3881 im_LabQ2XYZ( IMAGE *in, IMAGE *out )
3882 {
3883 	IMAGE *t[1];
3884 
3885 	if( im_open_local_array( out, t, 1, "im_LabQ2XYZ:1", "p" ) ||
3886 		im_LabQ2Lab( in, t[0] ) ||
3887 		im_Lab2XYZ( t[0], out ) )
3888 		return( -1 );
3889 
3890 	return( 0 );
3891 }
3892 
3893 int
im_Lab2UCS(IMAGE * in,IMAGE * out)3894 im_Lab2UCS( IMAGE *in, IMAGE *out )
3895 {
3896 	IMAGE *t[1];
3897 
3898 	if( im_open_local_array( out, t, 1, "im_Lab2UCS:1", "p" ) ||
3899 		im_Lab2LCh( in, t[0] ) ||
3900 		im_LCh2UCS( t[0], out ) )
3901 		return( -1 );
3902 
3903 	return( 0 );
3904 }
3905 
3906 int
im_UCS2Lab(IMAGE * in,IMAGE * out)3907 im_UCS2Lab( IMAGE *in, IMAGE *out )
3908 {
3909 	IMAGE *t[1];
3910 
3911 	if( im_open_local_array( out, t, 1, "im_UCS2Lab:1", "p" ) ||
3912 		im_UCS2LCh( in, t[0] ) ||
3913 		im_LCh2Lab( t[0], out ) )
3914 		return( -1 );
3915 
3916 	return( 0 );
3917 }
3918 
3919 int
im_UCS2XYZ(IMAGE * in,IMAGE * out)3920 im_UCS2XYZ( IMAGE *in, IMAGE *out )
3921 {
3922 	IMAGE *t[1];
3923 
3924 	if( im_open_local_array( out, t, 1, "im_UCS2XYZ:1", "p" ) ||
3925 		im_UCS2Lab( in, t[0] ) ||
3926 		im_Lab2XYZ( t[0], out ) )
3927 		return( -1 );
3928 
3929 	return( 0 );
3930 }
3931 
3932 int
im_XYZ2UCS(IMAGE * in,IMAGE * out)3933 im_XYZ2UCS( IMAGE *in, IMAGE *out )
3934 {
3935 	IMAGE *t[1];
3936 
3937 	if( im_open_local_array( out, t, 1, "im_XYZ2UCS:1", "p" ) ||
3938 		im_XYZ2Lab( in, t[0] ) ||
3939 		im_Lab2UCS( t[0], out ) )
3940 		return( -1 );
3941 
3942 	return( 0 );
3943 }
3944 
3945 int
im_dE_fromXYZ(IMAGE * in1,IMAGE * in2,IMAGE * out)3946 im_dE_fromXYZ( IMAGE *in1, IMAGE *in2, IMAGE *out )
3947 {
3948 	IMAGE *t[2];
3949 
3950 	if( im_open_local_array( out, t, 2, "im_dE_fromXYZ:1", "p" ) ||
3951 		im_XYZ2Lab( in1, t[0] ) ||
3952 		im_XYZ2Lab( in2, t[1] ) ||
3953 		im_dE_fromLab( t[0], t[1], out ) )
3954 		return( -1 );
3955 
3956 	return( 0 );
3957 }
3958 
3959 int
im_dE_fromLab(IMAGE * in1,IMAGE * in2,IMAGE * out)3960 im_dE_fromLab( IMAGE *in1, IMAGE *in2, IMAGE *out )
3961 {
3962 	VipsImage *x;
3963 
3964 	if( vips_dE76( in1, in2, &x,
3965 		NULL ) )
3966 		return( -1 );
3967 	if( vips_image_write( x, out ) ) {
3968 		g_object_unref( x );
3969 		return( -1 );
3970 	}
3971 	g_object_unref( x );
3972 
3973 	return( 0 );
3974 }
3975 
3976 int
im_dECMC_fromLab(IMAGE * in1,IMAGE * in2,IMAGE * out)3977 im_dECMC_fromLab( IMAGE *in1, IMAGE *in2, IMAGE *out )
3978 {
3979 	VipsImage *x;
3980 
3981 	if( vips_dECMC( in1, in2, &x,
3982 		NULL ) )
3983 		return( -1 );
3984 	if( vips_image_write( x, out ) ) {
3985 		g_object_unref( x );
3986 		return( -1 );
3987 	}
3988 	g_object_unref( x );
3989 
3990 	return( 0 );
3991 }
3992 
3993 int
im_dE00_fromLab(IMAGE * in1,IMAGE * in2,IMAGE * out)3994 im_dE00_fromLab( IMAGE *in1, IMAGE *in2, IMAGE *out )
3995 {
3996 	VipsImage *x;
3997 
3998 	if( vips_dE00( in1, in2, &x,
3999 		NULL ) )
4000 		return( -1 );
4001 	if( vips_image_write( x, out ) ) {
4002 		g_object_unref( x );
4003 		return( -1 );
4004 	}
4005 	g_object_unref( x );
4006 
4007 	return( 0 );
4008 }
4009 
4010 int
im_icc_ac2rc(VipsImage * in,VipsImage * out,const char * profile_filename)4011 im_icc_ac2rc( VipsImage *in, VipsImage *out, const char *profile_filename )
4012 {
4013 	VipsImage *x;
4014 
4015 	if( vips_icc_ac2rc( in, &x, profile_filename ) )
4016 		return( -1 );
4017 	if( vips_image_write( x, out ) ) {
4018 		g_object_unref( x );
4019 		return( -1 );
4020 	}
4021 	g_object_unref( x );
4022 
4023 	return( 0 );
4024 }
4025 
4026 int
im_quadratic(IMAGE * in,IMAGE * out,IMAGE * coeff)4027 im_quadratic( IMAGE *in, IMAGE *out, IMAGE *coeff )
4028 {
4029 	VipsImage *x;
4030 
4031 	if( vips_quadratic( in, &x, coeff,
4032 		NULL ) )
4033 		return( -1 );
4034 	if( vips_image_write( x, out ) ) {
4035 		g_object_unref( x );
4036 		return( -1 );
4037 	}
4038 	g_object_unref( x );
4039 
4040 	return( 0 );
4041 }
4042 
4043 int
im_maxpos_vec(VipsImage * im,int * xpos,int * ypos,double * maxima,int n)4044 im_maxpos_vec( VipsImage *im, int *xpos, int *ypos, double *maxima, int n )
4045 {
4046 	double max;
4047 	VipsArrayDouble *out_array;
4048 	VipsArrayInt *x_array;
4049 	VipsArrayInt *y_array;
4050 
4051 	if( vips_max( im, &max,
4052 		"size", n,
4053 		"out_array", &out_array,
4054 		"x_array", &x_array,
4055 		"y_array", &y_array,
4056 		NULL ) )
4057 		return( -1 );
4058 
4059 	memcpy( xpos, VIPS_ARRAY_ADDR( x_array, 0 ), n * sizeof( int ) );
4060 	memcpy( ypos, VIPS_ARRAY_ADDR( y_array, 0 ), n * sizeof( int ) );
4061 	memcpy( maxima, VIPS_ARRAY_ADDR( out_array, 0 ), n * sizeof( double ) );
4062 
4063 	vips_area_unref( VIPS_AREA( out_array ) );
4064 	vips_area_unref( VIPS_AREA( x_array ) );
4065 	vips_area_unref( VIPS_AREA( y_array ) );
4066 
4067 	return( 0 );
4068 }
4069 
4070 int
im_minpos_vec(VipsImage * im,int * xpos,int * ypos,double * minima,int n)4071 im_minpos_vec( VipsImage *im, int *xpos, int *ypos, double *minima, int n )
4072 {
4073 	double min;
4074 	VipsArrayDouble *out_array;
4075 	VipsArrayInt *x_array;
4076 	VipsArrayInt *y_array;
4077 
4078 	if( vips_min( im, &min,
4079 		"size", n,
4080 		"out_array", &out_array,
4081 		"x_array", &x_array,
4082 		"y_array", &y_array,
4083 		NULL ) )
4084 		return( -1 );
4085 
4086 	memcpy( xpos, VIPS_ARRAY_ADDR( x_array, 0 ), n * sizeof( int ) );
4087 	memcpy( ypos, VIPS_ARRAY_ADDR( y_array, 0 ), n * sizeof( int ) );
4088 	memcpy( minima, VIPS_ARRAY_ADDR( out_array, 0 ), n * sizeof( double ) );
4089 
4090 	vips_area_unref( VIPS_AREA( out_array ) );
4091 	vips_area_unref( VIPS_AREA( x_array ) );
4092 	vips_area_unref( VIPS_AREA( y_array ) );
4093 
4094 	return( 0 );
4095 }
4096 
4097 int
im_cross_phase(IMAGE * in1,IMAGE * in2,IMAGE * out)4098 im_cross_phase( IMAGE *in1, IMAGE *in2, IMAGE *out )
4099 {
4100 	VipsImage *x;
4101 
4102 	if( vips_call( "cross_phase", in1, in2, &x, NULL ) )
4103 		return( -1 );
4104 
4105 	if( vips_image_write( x, out ) ) {
4106 		g_object_unref( x );
4107 		return( -1 );
4108 	}
4109 	g_object_unref( x );
4110 
4111 	return( 0 );
4112 }
4113 
4114 int
im_maplut(IMAGE * in,IMAGE * out,IMAGE * lut)4115 im_maplut( IMAGE *in, IMAGE *out, IMAGE *lut )
4116 {
4117 	VipsImage *x;
4118 
4119 	if( vips_maplut( in, &x, lut, NULL ) )
4120 		return( -1 );
4121 
4122 	if( vips_image_write( x, out ) ) {
4123 		g_object_unref( x );
4124 		return( -1 );
4125 	}
4126 	g_object_unref( x );
4127 
4128 	return( 0 );
4129 }
4130 
4131 int
im_ismonotonic(IMAGE * lut,int * out)4132 im_ismonotonic( IMAGE *lut, int *out )
4133 {
4134 	gboolean monotonic;
4135 
4136 	if( vips_hist_ismonotonic( lut, &monotonic, NULL ) )
4137 		return( -1 );
4138 
4139 	*out = monotonic ? 255 : 0;
4140 
4141 	return( 0 );
4142 }
4143 
4144 int
im_histcum(IMAGE * in,IMAGE * out)4145 im_histcum( IMAGE *in, IMAGE *out )
4146 {
4147 	VipsImage *x;
4148 
4149 	if( vips_hist_cum( in, &x, NULL ) )
4150 		return( -1 );
4151 
4152 	if( vips_image_write( x, out ) ) {
4153 		g_object_unref( x );
4154 		return( -1 );
4155 	}
4156 	g_object_unref( x );
4157 
4158 	return( 0 );
4159 }
4160 
4161 int
im_histnorm(IMAGE * in,IMAGE * out)4162 im_histnorm( IMAGE *in, IMAGE *out )
4163 {
4164 	VipsImage *x;
4165 
4166 	if( vips_hist_norm( in, &x, NULL ) )
4167 		return( -1 );
4168 
4169 	if( vips_image_write( x, out ) ) {
4170 		g_object_unref( x );
4171 		return( -1 );
4172 	}
4173 	g_object_unref( x );
4174 
4175 	return( 0 );
4176 }
4177 
4178 int
im_histeq(IMAGE * in,IMAGE * out)4179 im_histeq( IMAGE *in, IMAGE *out )
4180 {
4181 	IMAGE *t1;
4182 
4183 	if( !(t1 = im_open_local( out, "im_histeq", "p" )) ||
4184 		im_histcum( in, t1 ) ||
4185 		im_histnorm( t1, out ) )
4186 		return( -1 );
4187 
4188 	return( 0 );
4189 }
4190 
4191 int
im_heq(VipsImage * in,VipsImage * out,int bandno)4192 im_heq( VipsImage *in, VipsImage *out, int bandno )
4193 {
4194 	VipsImage *x;
4195 
4196 	if( vips_hist_equal( in, &x, "band", bandno, NULL ) )
4197 		return( -1 );
4198 
4199 	if( vips_image_write( x, out ) ) {
4200 		g_object_unref( x );
4201 		return( -1 );
4202 	}
4203 	g_object_unref( x );
4204 
4205 	return( 0 );
4206 }
4207 
4208 int
im_hist(IMAGE * in,IMAGE * out,int bandno)4209 im_hist( IMAGE *in, IMAGE *out, int bandno )
4210 {
4211 	IMAGE *hist;
4212 
4213 	if( !(hist = im_open_local( out, "im_hist", "p" )) ||
4214 		im_histgr( in, hist, bandno ) ||
4215 		im_histplot( hist, out ) )
4216 		return( -1 );
4217 
4218 	return( 0 );
4219 }
4220 
4221 int
im_histgr(IMAGE * in,IMAGE * out,int bandno)4222 im_histgr( IMAGE *in, IMAGE *out, int bandno )
4223 {
4224 	VipsImage *x;
4225 
4226 	if( vips_hist_find( in, &x,
4227 		"band", bandno,
4228 		NULL ) )
4229 		return( -1 );
4230 
4231 	if( vips_image_write( x, out ) ) {
4232 		g_object_unref( x );
4233 		return( -1 );
4234 	}
4235 	g_object_unref( x );
4236 
4237 	return( 0 );
4238 }
4239 
4240 int
im_stdif(IMAGE * in,IMAGE * out,double a,double m0,double b,double s0,int width,int height)4241 im_stdif( IMAGE *in, IMAGE *out,
4242 	double a, double m0, double b, double s0,
4243 	int width, int height )
4244 {
4245 	VipsImage *x;
4246 
4247 	if( vips_stdif( in, &x, width, height,
4248 		"a", a,
4249 		"b", b,
4250 		"m0", m0,
4251 		"s0", s0,
4252 		NULL ) )
4253 		return( -1 );
4254 
4255 	if( vips_image_write( x, out ) ) {
4256 		g_object_unref( x );
4257 		return( -1 );
4258 	}
4259 	g_object_unref( x );
4260 
4261 	return( 0 );
4262 }
4263 
4264 int
im_lhisteq(VipsImage * in,VipsImage * out,int width,int height)4265 im_lhisteq( VipsImage *in, VipsImage *out, int width, int height )
4266 {
4267 	VipsImage *x;
4268 
4269 	if( vips_hist_local( in, &x, width, height, NULL ) )
4270 		return( -1 );
4271 
4272 	if( vips_image_write( x, out ) ) {
4273 		g_object_unref( x );
4274 		return( -1 );
4275 	}
4276 	g_object_unref( x );
4277 
4278 	return( 0 );
4279 }
4280 
4281 int
im_histnD(VipsImage * in,VipsImage * out,int bins)4282 im_histnD( VipsImage *in, VipsImage *out, int bins )
4283 {
4284 	VipsImage *x;
4285 
4286 	if( vips_hist_find_ndim( in, &x,
4287 		"bins", bins,
4288 		NULL ) )
4289 		return( -1 );
4290 
4291 	if( vips_image_write( x, out ) ) {
4292 		g_object_unref( x );
4293 		return( -1 );
4294 	}
4295 	g_object_unref( x );
4296 
4297 	return( 0 );
4298 }
4299 
4300 int
im_hist_indexed(VipsImage * index,VipsImage * value,VipsImage * out)4301 im_hist_indexed( VipsImage *index, VipsImage *value, VipsImage *out )
4302 {
4303 	VipsImage *x;
4304 
4305 	if( vips_hist_find_indexed( value, index, &x, NULL ) )
4306 		return( -1 );
4307 
4308 	if( vips_image_write( x, out ) ) {
4309 		g_object_unref( x );
4310 		return( -1 );
4311 	}
4312 	g_object_unref( x );
4313 
4314 	return( 0 );
4315 }
4316 
4317 int
im_project(IMAGE * in,IMAGE * hout,IMAGE * vout)4318 im_project( IMAGE *in, IMAGE *hout, IMAGE *vout )
4319 {
4320 	VipsImage *x, *y;
4321 
4322 	if( vips_project( in, &x, &y, NULL ) )
4323 		return( -1 );
4324 
4325 	if( vips_image_write( x, hout ) ) {
4326 		g_object_unref( x );
4327 		g_object_unref( y );
4328 		return( -1 );
4329 	}
4330 	g_object_unref( x );
4331 
4332 	if( vips_image_write( y, vout ) ) {
4333 		g_object_unref( y );
4334 		return( -1 );
4335 	}
4336 	g_object_unref( y );
4337 
4338 	return( 0 );
4339 }
4340 
4341 int
im_profile(IMAGE * in,IMAGE * out,int dir)4342 im_profile( IMAGE *in, IMAGE *out, int dir )
4343 {
4344 	VipsImage *columns, *rows;
4345 	VipsImage *t1, *t2;
4346 
4347 	if( vips_profile( in, &columns, &rows, NULL ) )
4348 		return( -1 );
4349 	if( dir == 0 ) {
4350 		t1 = columns;
4351 		g_object_unref( rows );
4352 	}
4353 	else {
4354 		t1 = rows;
4355 		g_object_unref( columns );
4356 	}
4357 
4358 	if( vips_cast( t1, &t2, VIPS_FORMAT_USHORT, NULL ) ) {
4359 		g_object_unref( t1 );
4360 		return( -1 );
4361 	}
4362 	g_object_unref( t1 );
4363 
4364 	if( vips_image_write( t2, out ) ) {
4365 		g_object_unref( t2 );
4366 		return( -1 );
4367 	}
4368 	g_object_unref( t2 );
4369 
4370 	return( 0 );
4371 }
4372 
4373 int
im_erode(IMAGE * in,IMAGE * out,INTMASK * mask)4374 im_erode( IMAGE *in, IMAGE *out, INTMASK *mask )
4375 {
4376 	VipsImage *t1, *t2;
4377 
4378 	if( !(t1 = vips_image_new()) ||
4379 		im_imask2vips( mask, t1 ) )
4380 		return( -1 );
4381 
4382 	if( vips_morph( in, &t2, t1, VIPS_OPERATION_MORPHOLOGY_ERODE,
4383 		NULL ) ) {
4384 		g_object_unref( t1 );
4385 		return( -1 );
4386 	}
4387 	g_object_unref( t1 );
4388 
4389 	if( vips_image_write( t2, out ) ) {
4390 		g_object_unref( t2 );
4391 		return( -1 );
4392 	}
4393 	g_object_unref( t2 );
4394 
4395 	return( 0 );
4396 }
4397 
4398 int
im_erode_raw(IMAGE * in,IMAGE * out,INTMASK * m)4399 im_erode_raw( IMAGE *in, IMAGE *out, INTMASK *m )
4400 {
4401 	return( im_erode( in, out, m ) );
4402 }
4403 
4404 int
im_dilate(IMAGE * in,IMAGE * out,INTMASK * mask)4405 im_dilate( IMAGE *in, IMAGE *out, INTMASK *mask )
4406 {
4407 	VipsImage *t1, *t2;
4408 
4409 	if( !(t1 = vips_image_new()) ||
4410 		im_imask2vips( mask, t1 ) )
4411 		return( -1 );
4412 
4413 	if( vips_morph( in, &t2, t1, VIPS_OPERATION_MORPHOLOGY_DILATE,
4414 		NULL ) ) {
4415 		g_object_unref( t1 );
4416 		return( -1 );
4417 	}
4418 	g_object_unref( t1 );
4419 
4420 	if( vips_image_write( t2, out ) ) {
4421 		g_object_unref( t2 );
4422 		return( -1 );
4423 	}
4424 	g_object_unref( t2 );
4425 
4426 	return( 0 );
4427 }
4428 
4429 int
im_dilate_raw(IMAGE * in,IMAGE * out,INTMASK * m)4430 im_dilate_raw( IMAGE *in, IMAGE *out, INTMASK *m )
4431 {
4432 	return( im_dilate( in, out, m ) );
4433 }
4434 
4435 int
im_mpercent(IMAGE * in,double percent,int * out)4436 im_mpercent( IMAGE *in, double percent, int *out )
4437 {
4438 	if( vips_percent( in, percent * 100.0, out, NULL ) )
4439 		return( -1 );
4440 
4441 	return( 0 );
4442 }
4443 
4444 int
im_mpercent_hist(IMAGE * in,double percent,int * out)4445 im_mpercent_hist( IMAGE *in, double percent, int *out )
4446 {
4447 	/* Hard to do this in a wrapper.
4448 	 */
4449 	vips_error( "im_mpercent_hist", "%s", _( "no compat implemented" ) );
4450 
4451 	return( -1 );
4452 }
4453 
4454 int
im_hsp(IMAGE * in,IMAGE * ref,IMAGE * out)4455 im_hsp( IMAGE *in, IMAGE *ref, IMAGE *out )
4456 {
4457 	IMAGE *t[3];
4458 
4459 	if( im_open_local_array( out, t, 3, "im_hsp", "p" ) ||
4460 		im_histgr( in, t[0], -1 ) ||
4461 		im_histgr( ref, t[1], -1 ) ||
4462 		im_histspec( t[0], t[1], t[2] ) ||
4463 		im_maplut( in, out, t[2] ) )
4464 		return( -1 );
4465 
4466 	return( 0 );
4467 }
4468 
4469 static int
match(VipsImage * in,VipsImage * ref,VipsImage * out)4470 match( VipsImage *in, VipsImage *ref, VipsImage *out )
4471 {
4472 	VipsImage *x;
4473 
4474 	if( vips_hist_match( in, ref, &x, NULL ) )
4475 		return( -1 );
4476 
4477 	if( vips_image_write( x, out ) ) {
4478 		g_object_unref( x );
4479 		return( -1 );
4480 	}
4481 	g_object_unref( x );
4482 
4483 	return( 0 );
4484 }
4485 
4486 int
im_histspec(IMAGE * in,IMAGE * ref,IMAGE * out)4487 im_histspec( IMAGE *in, IMAGE *ref, IMAGE *out )
4488 {
4489 	IMAGE *t[5];
4490 	guint64 px;
4491 	int fmt;
4492 
4493 	if( im_check_uint( "im_histspec", in ) ||
4494 		im_check_uint( "im_histspec", ref ) )
4495 		return( -1 );
4496 
4497 	if( im_open_local_array( out, t, 5, "im_histspec", "p" ) ||
4498 		im_histeq( in, t[0] ) ||
4499 		im_histeq( ref, t[2] ) ||
4500 		match( t[0], t[2], t[4] ) )
4501 		return( -1 );
4502 
4503 	px = VIPS_IMAGE_N_PELS( t[4] );
4504 	if( px <= 256 )
4505 		fmt = IM_BANDFMT_UCHAR;
4506 	else if( px <= 65536 )
4507 		fmt = IM_BANDFMT_USHORT;
4508 	else
4509 		fmt = IM_BANDFMT_UINT;
4510 
4511 	if( im_clip2fmt( t[4], out, fmt ) )
4512 		return( -1 );
4513 
4514         return( 0 );
4515 }
4516 
4517 int
im_falsecolour(IMAGE * in,IMAGE * out)4518 im_falsecolour( IMAGE *in, IMAGE *out )
4519 {
4520 	VipsImage *x;
4521 
4522 	if( vips_falsecolour( in, &x, NULL ) )
4523 		return( -1 );
4524 
4525 	if( vips_image_write( x, out ) ) {
4526 		g_object_unref( x );
4527 		return( -1 );
4528 	}
4529 	g_object_unref( x );
4530 
4531 	return( 0 );
4532 }
4533 
4534 int
im_gammacorrect(IMAGE * in,IMAGE * out,double exponent)4535 im_gammacorrect( IMAGE *in, IMAGE *out, double exponent )
4536 {
4537 	VipsImage *x;
4538 
4539 	if( vips_gamma( in, &x,
4540 		"exponent", 1.0 / exponent,
4541 		NULL ) )
4542 		return( -1 );
4543 
4544 	if( vips_image_write( x, out ) ) {
4545 		g_object_unref( x );
4546 		return( -1 );
4547 	}
4548 	g_object_unref( x );
4549 
4550 	return( 0 );
4551 }
4552 
4553 /* This is used by the carrierwave shrinker to cache the
4554  * output of shrink before doing the final affine.
4555  *
4556  * We use the vips8 threaded tilecache to avoid a deadlock: suppose thread1,
4557  * evaluating the top block of the output is delayed, and thread2, evaluating
4558  * the second block gets here first (this can happen on a heavily-loaded
4559  * system).
4560  *
4561  * With an unthreaded tilecache (as we had before), thread2 will get
4562  * the cache lock and start evaling the second block of the shrink. When it
4563  * reaches the png reader it will stall until the first block has been used ...
4564  * but it never will, since thread1 will block on this cache lock.
4565  *
4566  * This function is only used in this place (I think), so it's OK to
4567  * hard-wire this to be a sequential threaded cache.
4568  */
4569 int
im_tile_cache(IMAGE * in,IMAGE * out,int tile_width,int tile_height,int max_tiles)4570 im_tile_cache( IMAGE *in, IMAGE *out,
4571 	int tile_width, int tile_height, int max_tiles )
4572 {
4573 	VipsImage *x;
4574 
4575 	if( vips_tilecache( in, &x,
4576 		"tile_width", tile_width,
4577 		"tile_height", tile_height,
4578 		"max_tiles", max_tiles,
4579 		"access", VIPS_ACCESS_SEQUENTIAL,
4580 		"threaded", TRUE,
4581 		NULL ) )
4582 		return( -1 );
4583 
4584 	if( vips_image_write( x, out ) ) {
4585 		g_object_unref( x );
4586 		return( -1 );
4587 	}
4588 	g_object_unref( x );
4589 
4590 	return( 0 );
4591 }
4592 
4593 /* This is the one used by nip2's menu for caching images. Random access and
4594  * persistent.
4595  */
4596 int
im_tile_cache_random(IMAGE * in,IMAGE * out,int tile_width,int tile_height,int max_tiles)4597 im_tile_cache_random( IMAGE *in, IMAGE *out,
4598 	int tile_width, int tile_height, int max_tiles )
4599 {
4600 	VipsImage *x;
4601 
4602 	if( vips_tilecache( in, &x,
4603 		"tile_width", tile_width,
4604 		"tile_height", tile_height,
4605 		"max_tiles", max_tiles,
4606 		"access", VIPS_ACCESS_RANDOM,
4607 		"persistent", TRUE,
4608 		"threaded", TRUE,
4609 		NULL ) )
4610 		return( -1 );
4611 
4612 	if( vips_image_write( x, out ) ) {
4613 		g_object_unref( x );
4614 		return( -1 );
4615 	}
4616 	g_object_unref( x );
4617 
4618 	return( 0 );
4619 }
4620 
4621 static int
im__affinei(VipsImage * in,VipsImage * out,VipsInterpolate * interpolate,VipsTransformation * trn)4622 im__affinei( VipsImage *in, VipsImage *out,
4623 	VipsInterpolate *interpolate, VipsTransformation *trn )
4624 {
4625 	VipsImage **t = (VipsImage **)
4626 		vips_object_local_array( VIPS_OBJECT( out ), 2 );
4627 
4628 	VipsArea *oarea;
4629 	gboolean repack;
4630 
4631 	oarea = VIPS_AREA( vips_array_int_newv( 4,
4632 		trn->oarea.left, trn->oarea.top,
4633 		trn->oarea.width, trn->oarea.height ) );
4634 
4635 	/* vips7 affine would repack labq and im_benchmark() depends upon
4636 	 * this.
4637 	 */
4638 	repack = in->Coding == IM_CODING_LABQ;
4639 
4640 	if( vips_affine( in, &t[0],
4641 		trn->a, trn->b, trn->c, trn->d,
4642 		"interpolate", interpolate,
4643 		"oarea", oarea,
4644 		"odx", trn->odx,
4645 		"ody", trn->ody,
4646 		NULL ) ) {
4647 		vips_area_unref( oarea );
4648 		return( -1 );
4649 	}
4650 	vips_area_unref( oarea );
4651 	in = t[0];
4652 
4653 	if( repack ) {
4654 		if( vips_colourspace( in, &t[1],
4655 			VIPS_INTERPRETATION_LABQ, NULL ) )
4656 			return( -1 );
4657 		in = t[1];
4658 	}
4659 
4660 	if( vips_image_write( in, out ) )
4661 		return( -1 );
4662 
4663 	return( 0 );
4664 }
4665 
4666 int
im_affinei(VipsImage * in,VipsImage * out,VipsInterpolate * interpolate,double a,double b,double c,double d,double odx,double ody,int ox,int oy,int ow,int oh)4667 im_affinei( VipsImage *in, VipsImage *out, VipsInterpolate *interpolate,
4668 	double a, double b, double c, double d, double odx, double ody,
4669 	int ox, int oy, int ow, int oh )
4670 {
4671 	VipsTransformation trn;
4672 
4673 	trn.iarea.left = 0;
4674 	trn.iarea.top = 0;
4675 	trn.iarea.width = in->Xsize;
4676 	trn.iarea.height = in->Ysize;
4677 
4678 	trn.oarea.left = ox;
4679 	trn.oarea.top = oy;
4680 	trn.oarea.width = ow;
4681 	trn.oarea.height = oh;
4682 
4683 	trn.a = a;
4684 	trn.b = b;
4685 	trn.c = c;
4686 	trn.d = d;
4687 	trn.idx = 0;
4688 	trn.idy = 0;
4689 	trn.odx = odx;
4690 	trn.ody = ody;
4691 
4692 	return( im__affinei( in, out, interpolate, &trn ) );
4693 }
4694 
4695 int
im_affinei_all(VipsImage * in,VipsImage * out,VipsInterpolate * interpolate,double a,double b,double c,double d,double odx,double ody)4696 im_affinei_all( VipsImage *in, VipsImage *out, VipsInterpolate *interpolate,
4697 	double a, double b, double c, double d, double odx, double ody )
4698 {
4699 	VipsTransformation trn;
4700 
4701 	trn.iarea.left = 0;
4702 	trn.iarea.top = 0;
4703 	trn.iarea.width = in->Xsize;
4704 	trn.iarea.height = in->Ysize;
4705 	trn.a = a;
4706 	trn.b = b;
4707 	trn.c = c;
4708 	trn.d = d;
4709 	trn.idx = 0;
4710 	trn.idy = 0;
4711 	trn.odx = odx;
4712 	trn.ody = ody;
4713 
4714 	vips__transform_set_area( &trn );
4715 
4716 	return( im__affinei( in, out, interpolate, &trn ) );
4717 }
4718 
4719 /* Still needed by some parts of mosaic.
4720  */
4721 int
vips__affine(VipsImage * in,VipsImage * out,VipsTransformation * trn)4722 vips__affine( VipsImage *in, VipsImage *out, VipsTransformation *trn )
4723 {
4724 	return( im__affinei( in, out,
4725 		vips_interpolate_bilinear_static(), trn ) );
4726 }
4727 
4728 int
im_copy_file(IMAGE * in,IMAGE * out)4729 im_copy_file( IMAGE *in, IMAGE *out )
4730 {
4731 	VipsImage *x;
4732 
4733 	if( vips_copy_file( in, &x, NULL ) )
4734 		return( -1 );
4735 	if( vips_image_write( x, out ) ) {
4736 		g_object_unref( x );
4737 		return( -1 );
4738 	}
4739 	g_object_unref( x );
4740 
4741 	return( 0 );
4742 }
4743 
4744 int
im_video_v4l1(IMAGE * im,const char * device,int channel,int brightness,int colour,int contrast,int hue,int ngrabs)4745 im_video_v4l1( IMAGE *im, const char *device,
4746 	int channel, int brightness, int colour, int contrast, int hue,
4747 	int ngrabs )
4748 {
4749 	im_error( "im_video_v4l1",
4750 		"%s", _( "compiled without im_video_v4l1 support" ) );
4751 	return( -1 );
4752 }
4753 
4754 int
im_fwfft(IMAGE * in,IMAGE * out)4755 im_fwfft( IMAGE *in, IMAGE *out )
4756 {
4757 	VipsImage *x;
4758 
4759 	if( vips_fwfft( in, &x, NULL ) )
4760 		return( -1 );
4761 
4762 	if( vips_image_write( x, out ) ) {
4763 		g_object_unref( x );
4764 		return( -1 );
4765 	}
4766 	g_object_unref( x );
4767 
4768 	return( 0 );
4769 }
4770 
4771 int
im_invfft(IMAGE * in,IMAGE * out)4772 im_invfft( IMAGE *in, IMAGE *out )
4773 {
4774 	VipsImage *x;
4775 
4776 	if( vips_invfft( in, &x, NULL ) )
4777 		return( -1 );
4778 
4779 	if( vips_image_write( x, out ) ) {
4780 		g_object_unref( x );
4781 		return( -1 );
4782 	}
4783 	g_object_unref( x );
4784 
4785 	return( 0 );
4786 }
4787 
4788 int
im_invfftr(IMAGE * in,IMAGE * out)4789 im_invfftr( IMAGE *in, IMAGE *out )
4790 {
4791 	VipsImage *x;
4792 
4793 	if( vips_invfft( in, &x,
4794 		"real", TRUE,
4795 		NULL ) )
4796 		return( -1 );
4797 
4798 	if( vips_image_write( x, out ) ) {
4799 		g_object_unref( x );
4800 		return( -1 );
4801 	}
4802 	g_object_unref( x );
4803 
4804 	return( 0 );
4805 }
4806 
4807 int
im_freqflt(IMAGE * in,IMAGE * mask,IMAGE * out)4808 im_freqflt( IMAGE *in, IMAGE *mask, IMAGE *out )
4809 {
4810 	VipsImage *x;
4811 
4812 	if( vips_freqmult( in, mask, &x, NULL ) )
4813 		return( -1 );
4814 
4815 	if( vips_image_write( x, out ) ) {
4816 		g_object_unref( x );
4817 		return( -1 );
4818 	}
4819 	g_object_unref( x );
4820 
4821 	return( 0 );
4822 }
4823 
4824 int
im_disp_ps(IMAGE * in,IMAGE * out)4825 im_disp_ps( IMAGE *in, IMAGE *out )
4826 {
4827 	VipsImage *t;
4828 
4829 	if( vips_spectrum( in, &t, NULL ) )
4830 		return( -1 );
4831 	if( vips_image_write( t, out ) ) {
4832 		g_object_unref( t );
4833 		return( -1 );
4834 	}
4835 	g_object_unref( t );
4836 
4837 	return( 0 );
4838 }
4839 
4840 int
im_fractsurf(IMAGE * out,int size,double frd)4841 im_fractsurf( IMAGE *out, int size, double frd )
4842 {
4843 	VipsImage *t;
4844 
4845 	if( vips_fractsurf( &t, size, size, frd, NULL ) )
4846 		return( -1 );
4847 	if( vips_image_write( t, out ) ) {
4848 		g_object_unref( t );
4849 		return( -1 );
4850 	}
4851 	g_object_unref( t );
4852 
4853 	return( 0 );
4854 }
4855 
4856 int
im_phasecor_fft(IMAGE * in1,IMAGE * in2,IMAGE * out)4857 im_phasecor_fft( IMAGE *in1, IMAGE *in2, IMAGE *out )
4858 {
4859 	VipsImage *x;
4860 
4861 	if( vips_phasecor( in1, in2, &x, NULL ) )
4862 		return( -1 );
4863 
4864 	if( vips_image_write( x, out ) ) {
4865 		g_object_unref( x );
4866 		return( -1 );
4867 	}
4868 	g_object_unref( x );
4869 
4870 	return( 0 );
4871 }
4872 
4873 int
im_cntlines(VipsImage * im,double * nolines,int flag)4874 im_cntlines( VipsImage *im, double *nolines, int flag )
4875 {
4876 	return( vips_countlines( im, nolines,
4877 		flag == 0 ?
4878 			VIPS_DIRECTION_HORIZONTAL : VIPS_DIRECTION_VERTICAL,
4879 		NULL ) );
4880 }
4881 
4882 int
im_label_regions(IMAGE * test,IMAGE * mask,int * segments)4883 im_label_regions( IMAGE *test, IMAGE *mask, int *segments )
4884 {
4885 	VipsImage *x;
4886 
4887 	if( vips_labelregions( test, &x, "segments", segments, NULL ) )
4888 		return( -1 );
4889 
4890 	if( vips_image_write( x, mask ) ) {
4891 		g_object_unref( x );
4892 		return( -1 );
4893 	}
4894 	g_object_unref( x );
4895 
4896 	return( 0 );
4897 }
4898 
4899 int
im_rank(IMAGE * in,IMAGE * out,int width,int height,int index)4900 im_rank( IMAGE *in, IMAGE *out, int width, int height, int index )
4901 {
4902 	VipsImage *x;
4903 
4904 	if( vips_rank( in, &x, width, height, index, NULL ) )
4905 		return( -1 );
4906 
4907 	if( vips_image_write( x, out ) ) {
4908 		g_object_unref( x );
4909 		return( -1 );
4910 	}
4911 	g_object_unref( x );
4912 
4913 	return( 0 );
4914 }
4915 
4916 int
im_rank_raw(IMAGE * in,IMAGE * out,int width,int height,int index)4917 im_rank_raw( IMAGE *in, IMAGE *out, int width, int height, int index )
4918 {
4919 	im_error( "im_rank_raw", "no compat function" );
4920 	return( -1 );
4921 }
4922 
4923 int
im_draw_circle(VipsImage * image,int x,int y,int radius,gboolean fill,VipsPel * ink)4924 im_draw_circle( VipsImage *image,
4925 	int x, int y, int radius, gboolean fill, VipsPel *ink )
4926 {
4927 	double *vec;
4928 	int n;
4929 
4930 	if( !(vec = vips__ink_to_vector( "im_draw_circle", image, ink, &n )) )
4931 		return( -1 );
4932 
4933 	return( vips_draw_circle( image, vec, n, x, y, radius,
4934 		"fill", fill,
4935 		NULL ) );
4936 }
4937 
4938 int
im_draw_line(VipsImage * image,int x1,int y1,int x2,int y2,VipsPel * ink)4939 im_draw_line( VipsImage *image, int x1, int y1, int x2, int y2, VipsPel *ink )
4940 {
4941 	double *vec;
4942 	int n;
4943 
4944 	if( !(vec = vips__ink_to_vector( "im_draw_line", image, ink, &n )) )
4945 		return( -1 );
4946 
4947 	return( vips_draw_line( image, vec, n, x1, y1, x2, y2, NULL ) );
4948 }
4949 
4950 typedef struct _Line {
4951 	VipsPlotFn plot;
4952 	void *a;
4953 	void *b;
4954 	void *c;
4955 } Line;
4956 
4957 static void
draw_line_wrapper(VipsImage * image,int x,int y,void * client)4958 draw_line_wrapper( VipsImage *image, int x, int y, void *client )
4959 {
4960 	Line *line = (Line *) client;
4961 
4962 	line->plot( image, x, y, line->a, line->b, line->c );
4963 }
4964 
4965 int
im_draw_line_user(VipsImage * image,int x1,int y1,int x2,int y2,VipsPlotFn plot,void * a,void * b,void * c)4966 im_draw_line_user( VipsImage *image,
4967 	int x1, int y1, int x2, int y2,
4968 	VipsPlotFn plot, void *a, void *b, void *c )
4969 {
4970 	Line line;
4971 
4972 	line.plot = plot;
4973 	line.a = a;
4974 	line.b = b;
4975 	line.c = c;
4976 
4977 	vips__draw_line_direct( image, x1, y1, x2, y2,
4978 		draw_line_wrapper, &line );
4979 
4980 	return( 0 );
4981 }
4982 
4983 int
im_draw_mask(VipsImage * image,VipsImage * mask,int x,int y,VipsPel * ink)4984 im_draw_mask( VipsImage *image, VipsImage *mask, int x, int y, VipsPel *ink )
4985 {
4986 	/* Direct call, since this has to be very quick.
4987 	 */
4988 	return( vips__draw_mask_direct( image, mask, ink, x, y ) );
4989 }
4990 
4991 int
im_draw_image(VipsImage * image,VipsImage * sub,int x,int y)4992 im_draw_image( VipsImage *image, VipsImage *sub, int x, int y )
4993 {
4994 	return( vips_draw_image( image, sub, x, y, NULL ) );
4995 }
4996 
4997 int
im_draw_rect(IMAGE * image,int left,int top,int width,int height,int fill,VipsPel * ink)4998 im_draw_rect( IMAGE *image,
4999 	int left, int top, int width, int height, int fill, VipsPel *ink )
5000 {
5001 	double *vec;
5002 	int n;
5003 
5004 	if( !(vec = vips__ink_to_vector( "im_draw_rect", image, ink, &n )) )
5005 		return( -1 );
5006 
5007 	return( vips_draw_rect( image, vec, n, left, top, width, height,
5008 		"fill", fill,
5009 		NULL ) );
5010 }
5011 
5012 int
im_draw_point(VipsImage * image,int x,int y,VipsPel * ink)5013 im_draw_point( VipsImage *image, int x, int y, VipsPel *ink )
5014 {
5015 	double *vec;
5016 	int n;
5017 
5018 	if( !(vec = vips__ink_to_vector( "im_draw_rect", image, ink, &n )) )
5019 		return( -1 );
5020 
5021 	return( vips_draw_point( image, vec, n, x, y, NULL ) );
5022 }
5023 
5024 int
im_draw_smudge(VipsImage * im,int left,int top,int width,int height)5025 im_draw_smudge( VipsImage *im, int left, int top, int width, int height )
5026 {
5027 	return( vips_draw_smudge( im, left, top, width, height, NULL ) );
5028 }
5029 
5030 int
im_read_point(VipsImage * image,int x,int y,VipsPel * ink)5031 im_read_point( VipsImage *image, int x, int y, VipsPel *ink )
5032 {
5033 	double *vector;
5034 	int n;
5035 	VipsPel *pixel_vector;
5036 
5037 	if( vips_getpoint( image, &vector, &n, x, y, NULL ) )
5038 		return( -1 );
5039 
5040 	if( !(pixel_vector = vips__vector_to_ink( "im_read_point",
5041 		image, vector, NULL, n )) ) {
5042 		g_free( vector );
5043 		return( -1 );
5044 	}
5045 
5046 	memcpy( ink, pixel_vector, VIPS_IMAGE_SIZEOF_PEL( image ) );
5047 
5048 	g_free( vector );
5049 
5050 	return( 0 );
5051 }
5052 
5053 int
im_draw_flood(IMAGE * image,int x,int y,VipsPel * ink,Rect * dout)5054 im_draw_flood( IMAGE *image, int x, int y, VipsPel *ink, Rect *dout )
5055 {
5056 	double *vec;
5057 	int n;
5058 	int left;
5059 	int top;
5060 	int width;
5061 	int height;
5062 
5063 	if( !(vec = vips__ink_to_vector( "im_draw_flood", image, ink, &n )) )
5064 		return( -1 );
5065 
5066 	if( vips_draw_flood( image, vec, n, x, y,
5067 		"left", &left,
5068 		"top", &top,
5069 		"width", &width,
5070 		"height", &height,
5071 		NULL ) )
5072 		return( -1 );
5073 
5074 	if( dout ) {
5075 		dout->left = left;
5076 		dout->top = top;
5077 		dout->width = width;
5078 		dout->height = height;
5079 	}
5080 
5081 	return( 0 );
5082 }
5083 
5084 int
im_draw_flood_blob(IMAGE * image,int x,int y,VipsPel * ink,Rect * dout)5085 im_draw_flood_blob( IMAGE *image, int x, int y, VipsPel *ink, Rect *dout )
5086 {
5087 	double *vec;
5088 	int n;
5089 	int left;
5090 	int top;
5091 	int width;
5092 	int height;
5093 
5094 	if( !(vec = vips__ink_to_vector( "im_draw_flood", image, ink, &n )) )
5095 		return( -1 );
5096 
5097 	if( vips_draw_flood( image, vec, n, x, y,
5098 		"equal", TRUE,
5099 		"left", &left,
5100 		"top", &top,
5101 		"width", &width,
5102 		"height", &height,
5103 		NULL ) )
5104 		return( -1 );
5105 
5106 	if( dout ) {
5107 		dout->left = left;
5108 		dout->top = top;
5109 		dout->width = width;
5110 		dout->height = height;
5111 	}
5112 
5113 	return( 0 );
5114 }
5115 
5116 int
im_draw_flood_other(IMAGE * image,IMAGE * test,int x,int y,int serial,Rect * dout)5117 im_draw_flood_other( IMAGE *image,
5118 	IMAGE *test, int x, int y, int serial, Rect *dout )
5119 {
5120 	int left;
5121 	int top;
5122 	int width;
5123 	int height;
5124 
5125 	if( vips_draw_flood1( image, serial, x, y,
5126 		"test", test,
5127 		"equal", TRUE,
5128 		"left", &left,
5129 		"top", &top,
5130 		"width", &width,
5131 		"height", &height,
5132 		NULL ) )
5133 		return( -1 );
5134 
5135 	if( dout ) {
5136 		dout->left = left;
5137 		dout->top = top;
5138 		dout->width = width;
5139 		dout->height = height;
5140 	}
5141 
5142 	return( 0 );
5143 }
5144 
5145 int
im_lineset(IMAGE * in,IMAGE * out,IMAGE * mask,IMAGE * ink,int n,int * x1v,int * y1v,int * x2v,int * y2v)5146 im_lineset( IMAGE *in, IMAGE *out, IMAGE *mask, IMAGE *ink,
5147 	int n, int *x1v, int *y1v, int *x2v, int *y2v )
5148 {
5149 	Rect mask_rect;
5150 	int i;
5151 
5152 	if( mask->Bands != 1 || mask->BandFmt != IM_BANDFMT_UCHAR ||
5153 		mask->Coding != IM_CODING_NONE ) {
5154 		im_error( "im_lineset",
5155 			"%s", _( "mask image not 1 band 8 bit uncoded" ) );
5156 		return( -1 );
5157 	}
5158 	if( ink->Bands != in->Bands || ink->BandFmt != in->BandFmt ||
5159 		ink->Coding != in->Coding ) {
5160 		im_error( "im_lineset",
5161 			"%s", _( "ink image does not match in image" ) );
5162 		return( -1 );
5163 	}
5164 	if( ink->Xsize != 1 || ink->Ysize != 1 ) {
5165 		im_error( "im_lineset", "%s", _( "ink image not 1x1 pixels" ) );
5166 		return( -1 );
5167 	}
5168 
5169 	/* Copy the image then fastline to it ... this will render to a "t"
5170 	 * usually.
5171 	 */
5172 	if( vips_image_write( in, out ) )
5173 		return( -1 );
5174 
5175 	mask_rect.left = mask->Xsize / 2;
5176 	mask_rect.top = mask->Ysize / 2;
5177 	mask_rect.width = mask->Xsize;
5178 	mask_rect.height = mask->Ysize;
5179 
5180 	if( im_incheck( ink ) ||
5181 		im_incheck( mask ) )
5182 		return( -1 );
5183 
5184 	for( i = 0; i < n; i++ ) {
5185 		if( im_fastlineuser( out, x1v[i], y1v[i], x2v[i], y2v[i],
5186 			(VipsPlotFn) im_plotmask, ink->data, mask->data, &mask_rect ) )
5187 			return( -1 );
5188 	}
5189 
5190 	return( 0 );
5191 }
5192 
5193 int
im_match_linear_search(IMAGE * ref,IMAGE * sec,IMAGE * out,int xr1,int yr1,int xs1,int ys1,int xr2,int yr2,int xs2,int ys2,int hwindowsize,int hsearchsize)5194 im_match_linear_search( IMAGE *ref, IMAGE *sec, IMAGE *out,
5195 	int xr1, int yr1, int xs1, int ys1,
5196 	int xr2, int yr2, int xs2, int ys2,
5197 	int hwindowsize, int hsearchsize )
5198 {
5199 	VipsImage *x;
5200 
5201 	if( vips_match( ref, sec, &x,
5202 		xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
5203 		"search", TRUE,
5204 		"hwindow", hwindowsize,
5205 		"harea", hsearchsize,
5206 		NULL ) )
5207 		return( -1 );
5208 
5209 	if( vips_image_write( x, out ) ) {
5210 		g_object_unref( x );
5211 		return( -1 );
5212 	}
5213 	g_object_unref( x );
5214 
5215 	return( 0 );
5216 }
5217 
5218 int
im_match_linear(IMAGE * ref,IMAGE * sec,IMAGE * out,int xr1,int yr1,int xs1,int ys1,int xr2,int yr2,int xs2,int ys2)5219 im_match_linear( IMAGE *ref, IMAGE *sec, IMAGE *out,
5220 	int xr1, int yr1, int xs1, int ys1,
5221 	int xr2, int yr2, int xs2, int ys2 )
5222 {
5223 	VipsImage *x;
5224 
5225 	if( vips_match( ref, sec, &x,
5226 		xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
5227 		NULL ) )
5228 		return( -1 );
5229 
5230 	if( vips_image_write( x, out ) ) {
5231 		g_object_unref( x );
5232 		return( -1 );
5233 	}
5234 	g_object_unref( x );
5235 
5236 	return( 0 );
5237 }
5238 
5239 int
im_global_balance(IMAGE * in,IMAGE * out,double gamma)5240 im_global_balance( IMAGE *in, IMAGE *out, double gamma )
5241 {
5242 	VipsImage *x;
5243 
5244 	if( vips_globalbalance( in, &x,
5245 		"gamma", gamma,
5246 		"int_output", TRUE,
5247 		NULL ) )
5248 		return( -1 );
5249 
5250 	if( vips_image_write( x, out ) ) {
5251 		g_object_unref( x );
5252 		return( -1 );
5253 	}
5254 	g_object_unref( x );
5255 
5256 	return( 0 );
5257 }
5258 
5259 int
im_histplot(IMAGE * in,IMAGE * out)5260 im_histplot( IMAGE *in, IMAGE *out )
5261 {
5262 	VipsImage *x;
5263 
5264 	if( vips_hist_plot( in, &x, NULL ) )
5265 		return( -1 );
5266 
5267 	if( vips_image_write( x, out ) ) {
5268 		g_object_unref( x );
5269 		return( -1 );
5270 	}
5271 	g_object_unref( x );
5272 
5273 	return( 0 );
5274 }
5275 
5276 int
im_global_balancef(IMAGE * in,IMAGE * out,double gamma)5277 im_global_balancef( IMAGE *in, IMAGE *out, double gamma )
5278 {
5279 	VipsImage *x;
5280 
5281 	if( vips_globalbalance( in, &x,
5282 		"gamma", gamma,
5283 		NULL ) )
5284 		return( -1 );
5285 
5286 	if( vips_image_write( x, out ) ) {
5287 		g_object_unref( x );
5288 		return( -1 );
5289 	}
5290 	g_object_unref( x );
5291 
5292 	return( 0 );
5293 }
5294 
5295 int
im_remosaic(IMAGE * in,IMAGE * out,const char * old_str,const char * new_str)5296 im_remosaic( IMAGE *in, IMAGE *out, const char *old_str, const char *new_str )
5297 {
5298 	VipsImage *x;
5299 
5300 	if( vips_remosaic( in, &x, old_str, new_str, NULL ) )
5301 		return( -1 );
5302 
5303 	if( vips_image_write( x, out ) ) {
5304 		g_object_unref( x );
5305 		return( -1 );
5306 	}
5307 	g_object_unref( x );
5308 
5309 	return( 0 );
5310 }
5311 
5312 int
im_lrmosaic(IMAGE * ref,IMAGE * sec,IMAGE * out,int bandno,int xref,int yref,int xsec,int ysec,int hwindowsize,int hsearchsize,int balancetype,int mwidth)5313 im_lrmosaic( IMAGE *ref, IMAGE *sec, IMAGE *out,
5314 	int bandno,
5315 	int xref, int yref, int xsec, int ysec,
5316  	int hwindowsize, int hsearchsize,
5317 	int balancetype,
5318 	int mwidth )
5319 {
5320 	VipsImage *x;
5321 
5322 	if( vips_mosaic( ref, sec, &x, VIPS_DIRECTION_HORIZONTAL,
5323 		xref, yref, xsec, ysec,
5324 		"hwindow", hwindowsize,
5325 		"harea", hsearchsize,
5326 		"mblend", mwidth,
5327 		NULL ) )
5328 		return( -1 );
5329 	if( vips_image_write( x, out ) ) {
5330 		g_object_unref( x );
5331 		return( -1 );
5332 	}
5333 	g_object_unref( x );
5334 
5335 	return( 0 );
5336 }
5337 
5338 int
im_lrmosaic1(IMAGE * ref,IMAGE * sec,IMAGE * out,int bandno,int xr1,int yr1,int xs1,int ys1,int xr2,int yr2,int xs2,int ys2,int hwindowsize,int hsearchsize,int balancetype,int mwidth)5339 im_lrmosaic1( IMAGE *ref, IMAGE *sec, IMAGE *out,
5340 	int bandno,
5341 	int xr1, int yr1, int xs1, int ys1,
5342 	int xr2, int yr2, int xs2, int ys2,
5343 	int hwindowsize, int hsearchsize,
5344 	int balancetype,
5345 	int mwidth )
5346 {
5347 	VipsImage *x;
5348 
5349 	if( vips_mosaic1( ref, sec, &x, VIPS_DIRECTION_HORIZONTAL,
5350 		xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
5351 		"search", TRUE,
5352 		"bandno", bandno,
5353 		"hwindow", hwindowsize,
5354 		"harea", hsearchsize,
5355 		"mblend", mwidth,
5356 		NULL ) )
5357 		return( -1 );
5358 	if( vips_image_write( x, out ) ) {
5359 		g_object_unref( x );
5360 		return( -1 );
5361 	}
5362 	g_object_unref( x );
5363 
5364 	return( 0 );
5365 }
5366 
5367 int
im_tbmosaic(IMAGE * ref,IMAGE * sec,IMAGE * out,int bandno,int xref,int yref,int xsec,int ysec,int hwindowsize,int hsearchsize,int balancetype,int mwidth)5368 im_tbmosaic( IMAGE *ref, IMAGE *sec, IMAGE *out,
5369 	int bandno,
5370 	int xref, int yref, int xsec, int ysec,
5371  	int hwindowsize, int hsearchsize,
5372 	int balancetype,
5373 	int mwidth )
5374 {
5375 	VipsImage *x;
5376 
5377 	if( vips_mosaic( ref, sec, &x, VIPS_DIRECTION_VERTICAL,
5378 		xref, yref, xsec, ysec,
5379 		"hwindow", hwindowsize,
5380 		"harea", hsearchsize,
5381 		"mblend", mwidth,
5382 		NULL ) )
5383 		return( -1 );
5384 	if( vips_image_write( x, out ) ) {
5385 		g_object_unref( x );
5386 		return( -1 );
5387 	}
5388 	g_object_unref( x );
5389 
5390 	return( 0 );
5391 }
5392 
5393 int
im_tbmosaic1(IMAGE * ref,IMAGE * sec,IMAGE * out,int bandno,int xr1,int yr1,int xs1,int ys1,int xr2,int yr2,int xs2,int ys2,int hwindowsize,int hsearchsize,int balancetype,int mwidth)5394 im_tbmosaic1( IMAGE *ref, IMAGE *sec, IMAGE *out,
5395 	int bandno,
5396 	int xr1, int yr1, int xs1, int ys1,
5397 	int xr2, int yr2, int xs2, int ys2,
5398 	int hwindowsize, int hsearchsize,
5399 	int balancetype,
5400 	int mwidth )
5401 {
5402 	VipsImage *x;
5403 
5404 	if( vips_mosaic1( ref, sec, &x, VIPS_DIRECTION_VERTICAL,
5405 		xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
5406 		"search", TRUE,
5407 		"bandno", bandno,
5408 		"hwindow", hwindowsize,
5409 		"harea", hsearchsize,
5410 		"mblend", mwidth,
5411 		NULL ) )
5412 		return( -1 );
5413 	if( vips_image_write( x, out ) ) {
5414 		g_object_unref( x );
5415 		return( -1 );
5416 	}
5417 	g_object_unref( x );
5418 
5419 	return( 0 );
5420 }
5421 
5422 int
im_correl(VipsImage * ref,VipsImage * sec,int xref,int yref,int xsec,int ysec,int hwindowsize,int hsearchsize,double * correlation,int * x,int * y)5423 im_correl( VipsImage *ref, VipsImage *sec,
5424 	int xref, int yref, int xsec, int ysec,
5425 	int hwindowsize, int hsearchsize,
5426 	double *correlation, int *x, int *y )
5427 {
5428 	return( vips__correl( ref, sec, xref, yref, xsec, ysec,
5429 		hwindowsize, hsearchsize, correlation, x, y ) );
5430 }
5431 
5432 int
im_lrmerge(IMAGE * ref,IMAGE * sec,IMAGE * out,int dx,int dy,int mwidth)5433 im_lrmerge( IMAGE *ref, IMAGE *sec, IMAGE *out,
5434 	int dx, int dy, int mwidth )
5435 {
5436 	VipsImage *x;
5437 
5438 	if( vips_merge( ref, sec, &x, VIPS_DIRECTION_HORIZONTAL, dx, dy,
5439 		"mblend", mwidth,
5440 		NULL ) )
5441 		return( -1 );
5442 	if( vips_image_write( x, out ) ) {
5443 		g_object_unref( x );
5444 		return( -1 );
5445 	}
5446 	g_object_unref( x );
5447 
5448 	return( 0 );
5449 }
5450 
5451 int
im_lrmerge1(IMAGE * ref,IMAGE * sec,IMAGE * out,int xr1,int yr1,int xs1,int ys1,int xr2,int yr2,int xs2,int ys2,int mwidth)5452 im_lrmerge1( IMAGE *ref, IMAGE *sec, IMAGE *out,
5453 	int xr1, int yr1, int xs1, int ys1,
5454 	int xr2, int yr2, int xs2, int ys2,
5455 	int mwidth )
5456 {
5457 	VipsImage *x;
5458 
5459 	if( vips_mosaic1( ref, sec, &x, VIPS_DIRECTION_HORIZONTAL,
5460 		xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
5461 		"mblend", mwidth,
5462 		NULL ) )
5463 		return( -1 );
5464 	if( vips_image_write( x, out ) ) {
5465 		g_object_unref( x );
5466 		return( -1 );
5467 	}
5468 	g_object_unref( x );
5469 
5470 	return( 0 );
5471 }
5472 
5473 int
im_tbmerge(IMAGE * ref,IMAGE * sec,IMAGE * out,int dx,int dy,int mwidth)5474 im_tbmerge( IMAGE *ref, IMAGE *sec, IMAGE *out,
5475 	int dx, int dy, int mwidth )
5476 {
5477 	VipsImage *x;
5478 
5479 	if( vips_merge( ref, sec, &x, VIPS_DIRECTION_VERTICAL, dx, dy,
5480 		"mblend", mwidth,
5481 		NULL ) )
5482 		return( -1 );
5483 	if( vips_image_write( x, out ) ) {
5484 		g_object_unref( x );
5485 		return( -1 );
5486 	}
5487 	g_object_unref( x );
5488 
5489 	return( 0 );
5490 }
5491 
5492 int
im_tbmerge1(IMAGE * ref,IMAGE * sec,IMAGE * out,int xr1,int yr1,int xs1,int ys1,int xr2,int yr2,int xs2,int ys2,int mwidth)5493 im_tbmerge1( IMAGE *ref, IMAGE *sec, IMAGE *out,
5494 	int xr1, int yr1, int xs1, int ys1,
5495 	int xr2, int yr2, int xs2, int ys2,
5496 	int mwidth )
5497 {
5498 	VipsImage *x;
5499 
5500 	if( vips_mosaic1( ref, sec, &x, VIPS_DIRECTION_VERTICAL,
5501 		xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
5502 		"mblend", mwidth,
5503 		NULL ) )
5504 		return( -1 );
5505 	if( vips_image_write( x, out ) ) {
5506 		g_object_unref( x );
5507 		return( -1 );
5508 	}
5509 	g_object_unref( x );
5510 
5511 	return( 0 );
5512 }
5513 
5514 /* The common part of most binary conversion
5515  * operators. We:
5516  *
5517  * - check in and out
5518  * - cast in1 and in2 up to a common format
5519  * - equalise bands
5520  * - make an input array
5521  * - return the matched images in vec[0] and vec[1]
5522  *
5523  * A left-over, remove soon.
5524  */
5525 IMAGE **
im__insert_base(const char * domain,IMAGE * in1,IMAGE * in2,IMAGE * out)5526 im__insert_base( const char *domain,
5527 	IMAGE *in1, IMAGE *in2, IMAGE *out )
5528 {
5529 	IMAGE *t[4];
5530 	IMAGE **vec;
5531 
5532 	if( im_piocheck( in1, out ) ||
5533 		im_pincheck( in2 ) ||
5534 		im_check_bands_1orn( domain, in1, in2 ) ||
5535 		im_check_coding_known( domain, in1 ) ||
5536 		im_check_coding_same( domain, in1, in2 ) )
5537 		return( NULL );
5538 
5539 	/* Cast our input images up to a common format and bands.
5540 	 */
5541 	if( im_open_local_array( out, t, 4, domain, "p" ) ||
5542 		im__formatalike( in1, in2, t[0], t[1] ) ||
5543 		im__bandalike( domain, t[0], t[1], t[2], t[3] ) ||
5544 		!(vec = im_allocate_input_array( out, t[2], t[3], NULL )) )
5545 		return( NULL );
5546 
5547 	/* Generate the output.
5548 	 */
5549 	if( im_cp_descv( out, vec[0], vec[1], NULL ) ||
5550 		im_demand_hint_array( out, IM_SMALLTILE, vec ) )
5551 		return( NULL );
5552 
5553 	return( vec );
5554 }
5555 
5556 /**
5557  * im_insertset:
5558  * @main: big image
5559  * @sub: small image
5560  * @out: output image
5561  * @n: number of positions
5562  * @x: left positions of @sub
5563  * @y: top positions of @sub
5564  *
5565  * Insert @sub repeatedly into @main at the positions listed in the arrays @x,
5566  * @y of length @n. @out is the same
5567  * size as @main. @sub is clipped against the edges of @main.
5568  *
5569  * This operation is fast for large @n, but will use a memory buffer the size
5570  * of @out. It's useful for things like making scatter plots.
5571  *
5572  * If the number of bands differs, one of the images
5573  * must have one band. In this case, an n-band image is formed from the
5574  * one-band image by joining n copies of the one-band image together, and then
5575  * the two n-band images are operated upon.
5576  *
5577  * The two input images are cast up to the smallest common type (see table
5578  * Smallest common format in
5579  * <link linkend="VIPS-arithmetic">arithmetic</link>).
5580  *
5581  * See also: im_insert(), im_lrjoin().
5582  *
5583  * Returns: 0 on success, -1 on error
5584  */
5585 int
im_insertset(IMAGE * main,IMAGE * sub,IMAGE * out,int n,int * x,int * y)5586 im_insertset( IMAGE *main, IMAGE *sub, IMAGE *out, int n, int *x, int *y )
5587 {
5588 	IMAGE **vec;
5589 	IMAGE *t;
5590 	int i;
5591 
5592 	if( !(vec = im__insert_base( "im_insert", main, sub, out )) )
5593 		return( -1 );
5594 
5595 	/* Copy to a memory image, zap that, then copy to out.
5596 	 */
5597 	if( !(t = im_open_local( out, "im_insertset", "t" )) ||
5598 		im_copy( vec[0], t ) )
5599 		return( -1 );
5600 
5601 	for( i = 0; i < n; i++ )
5602 		if( im_insertplace( t, vec[1], x[i], y[i] ) )
5603 			return( -1 );
5604 
5605 	if( im_copy( t, out ) )
5606 		return( -1 );
5607 
5608 	return( 0 );
5609 }
5610 
5611 /* We had this entry point in earlier libvipses, hilariously.
5612  */
5613 int
vips__init(const char * argv0)5614 vips__init( const char *argv0 )
5615 {
5616 	return( vips_init( argv0 ) );
5617 }
5618 
5619 int
im_greyc_mask(IMAGE * in,IMAGE * out,IMAGE * mask,int iterations,float amplitude,float sharpness,float anisotropy,float alpha,float sigma,float dl,float da,float gauss_prec,int interpolation,int fast_approx)5620 im_greyc_mask( IMAGE *in, IMAGE *out, IMAGE *mask,
5621 	int iterations,
5622 	float amplitude, float sharpness, float anisotropy,
5623 	float alpha, float sigma,
5624 	float dl, float da, float gauss_prec,
5625 	int interpolation, int fast_approx )
5626 {
5627 	vips_error( "im_greyc_mask",
5628 		"This function is no longer in the core library" );
5629 
5630 	return( -1 );
5631 }
5632 
5633 int
vips_check_imask(const char * domain,INTMASK * mask)5634 vips_check_imask( const char *domain, INTMASK *mask )
5635 {
5636 	if( !mask ||
5637 		mask->xsize > 1000 ||
5638 		mask->ysize > 1000 ||
5639 		mask->xsize <= 0 ||
5640 		mask->ysize <= 0 ||
5641 		mask->scale == 0 ||
5642 		!mask->coeff ) {
5643 		vips_error( domain, "%s", _( "nonsense mask parameters" ) );
5644 		return( -1 );
5645 	}
5646 
5647 	return( 0 );
5648 }
5649 
5650 int
vips_check_dmask(const char * domain,DOUBLEMASK * mask)5651 vips_check_dmask( const char *domain, DOUBLEMASK *mask )
5652 {
5653 	if( !mask ||
5654 		mask->xsize > 1000 ||
5655 		mask->ysize > 1000 ||
5656 		mask->xsize <= 0 ||
5657 		mask->ysize <= 0 ||
5658 		mask->scale == 0 ||
5659 		!mask->coeff ) {
5660 		vips_error( domain, "%s", _( "nonsense mask parameters" ) );
5661 		return( -1 );
5662 	}
5663 
5664 	return( 0 );
5665 }
5666 
5667 int
vips_check_dmask_1d(const char * domain,DOUBLEMASK * mask)5668 vips_check_dmask_1d( const char *domain, DOUBLEMASK *mask )
5669 {
5670 	if( vips_check_dmask( domain, mask ) )
5671 		return( -1 );
5672 	if( mask->xsize != 1 &&
5673 		mask->ysize != 1 ) {
5674 		vips_error( domain, "%s", _( "mask must be 1D" ) );
5675 		return( -1 );
5676 	}
5677 
5678 	return( 0 );
5679 }
5680 
5681 GOptionGroup *
vips_get_option_group(void)5682 vips_get_option_group( void )
5683 {
5684 	static GOptionGroup *option_group = NULL;
5685 
5686 	if( !option_group ) {
5687 		option_group = g_option_group_new( "vips",
5688 				_( "VIPS Options" ), _( "Show VIPS options" ),
5689 				NULL, NULL );
5690 		vips_add_option_entries( option_group );
5691 	}
5692 
5693 	return( option_group );
5694 }
5695 
5696 /* We used to use this for system() back in the day. But it's awkward to make
5697  * it work properly on win32, so this is now deprecated.
5698  */
5699 FILE *
vips_popenf(const char * fmt,const char * mode,...)5700 vips_popenf( const char *fmt, const char *mode, ... )
5701 {
5702         vips_error( "popenf", "%s", _( "deprecated" ) );
5703         return( NULL );
5704 }
5705 
5706 /* We used to use this for getpoint(), but since it was the only caller in
5707  * vips8 it's now deprecated.
5708  */
5709 double *
vips__ink_to_vector(const char * domain,VipsImage * im,VipsPel * ink,int * n)5710 vips__ink_to_vector( const char *domain, VipsImage *im, VipsPel *ink, int *n )
5711 {
5712 	VipsImage **t = (VipsImage **)
5713 		vips_object_local_array( VIPS_OBJECT( im ), 6 );
5714 
5715 	double *result;
5716 
5717 #ifdef VIPS_DEBUG
5718 	printf( "vips__ink_to_vector: starting\n" );
5719 #endif /*VIPS_DEBUG*/
5720 
5721 	/* Wrap a VipsImage around ink.
5722 	 */
5723 	t[0] = vips_image_new_from_memory( ink, VIPS_IMAGE_SIZEOF_PEL( im ),
5724 		1, 1, VIPS_IMAGE_SIZEOF_PEL( im ), VIPS_FORMAT_UCHAR );
5725 	if( vips_copy( t[0], &t[1],
5726 		"bands", im->Bands,
5727 		"format", im->BandFmt,
5728 		"coding", im->Coding,
5729 		"interpretation", im->Type,
5730 		NULL ) )
5731 		return( NULL );
5732 
5733 	/* The image may be coded .. unpack to double.
5734 	 */
5735 	if( vips_image_decode( t[1], &t[2] ) ||
5736 		vips_cast( t[2], &t[3], VIPS_FORMAT_DOUBLE, NULL ) )
5737 		return( NULL );
5738 
5739 	/* To a mem buffer, then copy to out.
5740 	 */
5741 	if( !(t[4] = vips_image_new_memory()) ||
5742 		vips_image_write( t[3], t[4] ) )
5743 		return( NULL );
5744 
5745 	if( !(result = VIPS_ARRAY( im, t[4]->Bands, double )) )
5746 		return( NULL );
5747 	memcpy( result, t[4]->data, VIPS_IMAGE_SIZEOF_PEL( t[4] ) );
5748 	*n = t[4]->Bands;
5749 
5750 #ifdef VIPS_DEBUG
5751 {
5752 	int i;
5753 
5754 	printf( "vips__ink_to_vector:\n" );
5755 	printf( "\tink = " );
5756 	for( i = 0; i < n; i++ )
5757 		printf( "%d ", ink[i] );
5758 	printf( "\n" );
5759 
5760 	printf( "\tvec = " );
5761 	for( i = 0; i < *n; i++ )
5762 		printf( "%g ", result[i] );
5763 	printf( "\n" );
5764 }
5765 #endif /*VIPS_DEBUG*/
5766 
5767 	return( result );
5768 }
5769 
5770