1 /* relational.c --- various relational operations
2  *
3  * Modified:
4  * 26/7/93 JC
5  *	- >,<,>=,<= tests now as (double) to prevent compiler warnings. Should
6  *	  split into int/float cases really for speed.
7  * 25/1/95 JC
8  * 	- partialized
9  * 	- updated
10  * 7/2/95 JC
11  *	- oops! bug with doubles fixed
12  * 3/7/98 JC
13  *	- vector versions added ... im_equal_vec(), im_lesseq_vec() etc
14  * 	- small tidies
15  *	- should be a bit faster, lots of *q++ changed to q[x]
16  * 10/3/03 JC
17  *	- reworked to remove nested #defines: a bit slower, but much smaller
18  *	- all except _vec forms now work on complex
19  * 31/7/03 JC
20  *	- oops, relational_format was broken for some combinations
21  * 23/9/09
22  * 	- gtkdoc
23  * 	- use new im__arith_binary*() functions
24  * 	- more meta-programming
25  * 23/6/10
26  * 	- oops, moreconst and moreeqconst were the same
27  * 4/11/11
28  * 	- redone as a class
29  * 1/2/12
30  * 	- complex ==, != were broken
31  * 16/7/12
32  * 	- im1 > im2, im1 >= im2 were broken
33  * 17/9/14
34  * 	- im1 > im2, im1 >= im2 were still broken, but in a more subtle way
35  */
36 
37 /*
38 
39     Copyright (C) 1991-2005 The National Gallery
40 
41     This library is free software; you can redistribute it and/or
42     modify it under the terms of the GNU Lesser General Public
43     License as published by the Free Software Foundation; either
44     version 2.1 of the License, or (at your option) any later version.
45 
46     This library is distributed in the hope that it will be useful,
47     but WITHOUT ANY WARRANTY; without even the implied warranty of
48     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
49     Lesser General Public License for more details.
50 
51     You should have received a copy of the GNU Lesser General Public
52     License along with this library; if not, write to the Free Software
53     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
54     02110-1301  USA
55 
56  */
57 
58 /*
59 
60     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
61 
62  */
63 
64 /*
65 #define DEBUG
66  */
67 
68 #ifdef HAVE_CONFIG_H
69 #include <config.h>
70 #endif /*HAVE_CONFIG_H*/
71 #include <vips/intl.h>
72 
73 #include <stdio.h>
74 #include <stdlib.h>
75 
76 #include <vips/vips.h>
77 
78 #include "binary.h"
79 #include "unaryconst.h"
80 
81 typedef struct _VipsRelational {
82 	VipsBinary parent_instance;
83 
84 	VipsOperationRelational relational;
85 
86 } VipsRelational;
87 
88 typedef VipsBinaryClass VipsRelationalClass;
89 
90 G_DEFINE_TYPE( VipsRelational, vips_relational, VIPS_TYPE_BINARY );
91 
92 #define RLOOP( TYPE, ROP ) { \
93 	TYPE * restrict left = (TYPE *) in0; \
94 	TYPE * restrict right = (TYPE *) in1; \
95 	VipsPel * restrict q = (VipsPel *) out; \
96 	\
97 	for( x = 0; x < sz; x++ ) \
98 		q[x] = (left[x] ROP right[x]) ? 255 : 0; \
99 }
100 
101 #define CLOOP( TYPE, COP ) { \
102 	TYPE * restrict left = (TYPE *) in0; \
103 	TYPE * restrict right = (TYPE *) in1; \
104 	VipsPel * restrict q = (VipsPel *) out; \
105 	\
106 	for( x = 0; x < sz; x++ ) { \
107 		q[x] = COP( left[0], left[1], right[0], right[1]) ? 255 : 0; \
108 		\
109 		left += 2; \
110 		right += 2; \
111 	} \
112 }
113 
114 #define SWITCH( R, C, ROP, COP ) \
115 	switch( vips_image_get_format( im ) ) { \
116 	case VIPS_FORMAT_UCHAR:		R( unsigned char, ROP ); break; \
117 	case VIPS_FORMAT_CHAR:		R( signed char, ROP ); break; \
118 	case VIPS_FORMAT_USHORT: 	R( unsigned short, ROP ); break; \
119 	case VIPS_FORMAT_SHORT: 	R( signed short, ROP ); break; \
120 	case VIPS_FORMAT_UINT: 		R( unsigned int, ROP ); break; \
121 	case VIPS_FORMAT_INT: 		R( signed int, ROP ); break; \
122 	case VIPS_FORMAT_FLOAT: 	R( float, ROP ); break; \
123 	case VIPS_FORMAT_DOUBLE: 	R( double, ROP ); break;\
124 	case VIPS_FORMAT_COMPLEX: 	C( float, COP ); break; \
125 	case VIPS_FORMAT_DPCOMPLEX: 	C( double, COP ); break;\
126  	\
127 	default: \
128 		g_assert_not_reached(); \
129 	}
130 
131 #define CEQUAL( x1, y1, x2, y2 ) (x1 == x2 && y1 == y2)
132 #define CNOTEQ( x1, y1, x2, y2 ) (x1 != x2 || y1 != y2)
133 #define CLESS( x1, y1, x2, y2 ) (x1 * x1 + y1 * y1 < x2 * x2 + y2 * y2)
134 #define CLESSEQ( x1, y1, x2, y2 ) (x1 * x1 + y1 * y1 <= x2 * x2 + y2 * y2)
135 #define CMORE( x1, y1, x2, y2 ) (x1 * x1 + y1 * y1 > x2 * x2 + y2 * y2)
136 #define CMOREEQ( x1, y1, x2, y2 ) (x1 * x1 + y1 * y1 >= x2 * x2 + y2 * y2)
137 
138 static void
vips_relational_buffer(VipsArithmetic * arithmetic,VipsPel * out,VipsPel ** in,int width)139 vips_relational_buffer( VipsArithmetic *arithmetic,
140 	VipsPel *out, VipsPel **in, int width )
141 {
142 	VipsRelational *relational = (VipsRelational *) arithmetic;
143 	VipsImage *im = arithmetic->ready[0];
144 	const int sz = width * vips_image_get_bands( im );
145 
146 	VipsOperationRelational op;
147 	VipsPel *in0;
148 	VipsPel *in1;
149 	int x;
150 
151 	in0 = in[0];
152 	in1 = in[1];
153 	op = relational->relational;
154 
155 	if( op == VIPS_OPERATION_RELATIONAL_MORE ) {
156 		op = VIPS_OPERATION_RELATIONAL_LESS;
157 		VIPS_SWAP( VipsPel *, in0, in1 );
158 	}
159 
160 	if( op == VIPS_OPERATION_RELATIONAL_MOREEQ ) {
161 		op = VIPS_OPERATION_RELATIONAL_LESSEQ;
162 		VIPS_SWAP( VipsPel *, in0, in1 );
163 	}
164 
165 	switch( op ) {
166 	case VIPS_OPERATION_RELATIONAL_EQUAL:
167 		SWITCH( RLOOP, CLOOP, ==, CEQUAL );
168 		break;
169 
170 	case VIPS_OPERATION_RELATIONAL_NOTEQ:
171 		SWITCH( RLOOP, CLOOP, !=, CNOTEQ );
172 		break;
173 
174 	case VIPS_OPERATION_RELATIONAL_LESS:
175 		SWITCH( RLOOP, CLOOP, <, CLESS );
176 		break;
177 
178 	case VIPS_OPERATION_RELATIONAL_LESSEQ:
179 		SWITCH( RLOOP, CLOOP, <=, CLESSEQ );
180 		break;
181 
182 	default:
183 		g_assert_not_reached();
184 	}
185 }
186 
187 /* Save a bit of typing.
188  */
189 #define UC VIPS_FORMAT_UCHAR
190 #define C VIPS_FORMAT_CHAR
191 #define US VIPS_FORMAT_USHORT
192 #define S VIPS_FORMAT_SHORT
193 #define UI VIPS_FORMAT_UINT
194 #define I VIPS_FORMAT_INT
195 #define F VIPS_FORMAT_FLOAT
196 #define X VIPS_FORMAT_COMPLEX
197 #define D VIPS_FORMAT_DOUBLE
198 #define DX VIPS_FORMAT_DPCOMPLEX
199 
200 static const VipsBandFormat vips_relational_format_table[10] = {
201 /* UC  C   US  S   UI  I   F   X   D   DX */
202    UC, UC, UC, UC, UC, UC, UC, UC, UC, UC
203 };
204 
205 static void
vips_relational_class_init(VipsRelationalClass * class)206 vips_relational_class_init( VipsRelationalClass *class )
207 {
208 	GObjectClass *gobject_class = G_OBJECT_CLASS( class );
209 	VipsObjectClass *object_class = (VipsObjectClass *) class;
210 	VipsArithmeticClass *aclass = VIPS_ARITHMETIC_CLASS( class );
211 
212 	gobject_class->set_property = vips_object_set_property;
213 	gobject_class->get_property = vips_object_get_property;
214 
215 	object_class->nickname = "relational";
216 	object_class->description = _( "relational operation on two images" );
217 
218 	aclass->process_line = vips_relational_buffer;
219 
220 	vips_arithmetic_set_format_table( aclass,
221 		vips_relational_format_table );
222 
223 	VIPS_ARG_ENUM( class, "relational", 200,
224 		_( "Operation" ),
225 		_( "relational to perform" ),
226 		VIPS_ARGUMENT_REQUIRED_INPUT,
227 		G_STRUCT_OFFSET( VipsRelational, relational ),
228 		VIPS_TYPE_OPERATION_RELATIONAL,
229 			VIPS_OPERATION_RELATIONAL_EQUAL );
230 }
231 
232 static void
vips_relational_init(VipsRelational * relational)233 vips_relational_init( VipsRelational *relational )
234 {
235 }
236 
237 static int
vips_relationalv(VipsImage * left,VipsImage * right,VipsImage ** out,VipsOperationRelational relational,va_list ap)238 vips_relationalv( VipsImage *left, VipsImage *right, VipsImage **out,
239 	VipsOperationRelational relational, va_list ap )
240 {
241 	return(  vips_call_split( "relational", ap, left, right, out,
242 		relational ) );
243 }
244 
245 /**
246  * vips_relational:
247  * @left: left-hand input #VipsImage
248  * @right: right-hand input #VipsImage
249  * @out: (out): output #VipsImage
250  * @relational: relational operation to perform
251  * @...: %NULL-terminated list of optional named arguments
252  *
253  * Perform various relational operations on pairs of images.
254  *
255  * The output type is always uchar, with 0 for FALSE and 255 for TRUE.
256  *
257  * Less-than and greater-than for complex images compare the modulus.
258  *
259  * If the images differ in size, the smaller image is enlarged to match the
260  * larger by adding zero pixels along the bottom and right.
261  *
262  * If the number of bands differs, one of the images
263  * must have one band. In this case, an n-band image is formed from the
264  * one-band image by joining n copies of the one-band image together, and then
265  * the two n-band images are operated upon.
266  *
267  * The two input images are cast up to the smallest common format (see table
268  * Smallest common format in
269  * <link linkend="libvips-arithmetic">arithmetic</link>).
270  *
271  * To decide if pixels match exactly, that is have the same value in every
272  * band, use vips_bandbool() after this operation to AND or OR image bands
273  * together.
274  *
275  * See also: vips_boolean(), vips_bandbool(), vips_relational_const().
276  *
277  * Returns: 0 on success, -1 on error
278  */
279 int
vips_relational(VipsImage * left,VipsImage * right,VipsImage ** out,VipsOperationRelational relational,...)280 vips_relational( VipsImage *left, VipsImage *right, VipsImage **out,
281 	VipsOperationRelational relational, ... )
282 {
283 	va_list ap;
284 	int result;
285 
286 	va_start( ap, relational );
287 	result = vips_relationalv( left, right, out, relational, ap );
288 	va_end( ap );
289 
290 	return( result );
291 }
292 
293 /**
294  * vips_equal:
295  * @left: left-hand input #VipsImage
296  * @right: right-hand input #VipsImage
297  * @out: (out): output #VipsImage
298  * @...: %NULL-terminated list of optional named arguments
299  *
300  * Perform #VIPS_OPERATION_RELATIONAL_EQUAL on a pair of images. See
301  * vips_relational().
302  *
303  * Returns: 0 on success, -1 on error
304  */
305 int
vips_equal(VipsImage * left,VipsImage * right,VipsImage ** out,...)306 vips_equal( VipsImage *left, VipsImage *right, VipsImage **out, ... )
307 {
308 	va_list ap;
309 	int result;
310 
311 	va_start( ap, out );
312 	result = vips_relationalv( left, right, out,
313 		VIPS_OPERATION_RELATIONAL_EQUAL, ap );
314 	va_end( ap );
315 
316 	return( result );
317 }
318 
319 /**
320  * vips_notequal:
321  * @left: left-hand input #VipsImage
322  * @right: right-hand input #VipsImage
323  * @out: (out): output #VipsImage
324  * @...: %NULL-terminated list of optional named arguments
325  *
326  * Perform #VIPS_OPERATION_RELATIONAL_NOTEQ on a pair of images. See
327  * vips_relational().
328  *
329  * Returns: 0 on success, -1 on error
330  */
331 int
vips_notequal(VipsImage * left,VipsImage * right,VipsImage ** out,...)332 vips_notequal( VipsImage *left, VipsImage *right, VipsImage **out, ... )
333 {
334 	va_list ap;
335 	int result;
336 
337 	va_start( ap, out );
338 	result = vips_relationalv( left, right, out,
339 		VIPS_OPERATION_RELATIONAL_NOTEQ, ap );
340 	va_end( ap );
341 
342 	return( result );
343 }
344 
345 /**
346  * vips_more:
347  * @left: left-hand input #VipsImage
348  * @right: right-hand input #VipsImage
349  * @out: (out): output #VipsImage
350  * @...: %NULL-terminated list of optional named arguments
351  *
352  * Perform #VIPS_OPERATION_RELATIONAL_MORE on a pair of images. See
353  * vips_relational().
354  *
355  * Returns: 0 on success, -1 on error
356  */
357 int
vips_more(VipsImage * left,VipsImage * right,VipsImage ** out,...)358 vips_more( VipsImage *left, VipsImage *right, VipsImage **out, ... )
359 {
360 	va_list ap;
361 	int result;
362 
363 	va_start( ap, out );
364 	result = vips_relationalv( left, right, out,
365 		VIPS_OPERATION_RELATIONAL_MORE, ap );
366 	va_end( ap );
367 
368 	return( result );
369 }
370 
371 /**
372  * vips_moreeq:
373  * @left: left-hand input #VipsImage
374  * @right: right-hand input #VipsImage
375  * @out: (out): output #VipsImage
376  * @...: %NULL-terminated list of optional named arguments
377  *
378  * Perform #VIPS_OPERATION_RELATIONAL_MOREEQ on a pair of images. See
379  * vips_relational().
380  *
381  * Returns: 0 on success, -1 on error
382  */
383 int
vips_moreeq(VipsImage * left,VipsImage * right,VipsImage ** out,...)384 vips_moreeq( VipsImage *left, VipsImage *right, VipsImage **out, ... )
385 {
386 	va_list ap;
387 	int result;
388 
389 	va_start( ap, out );
390 	result = vips_relationalv( left, right, out,
391 		VIPS_OPERATION_RELATIONAL_MOREEQ, ap );
392 	va_end( ap );
393 
394 	return( result );
395 }
396 
397 /**
398  * vips_less:
399  * @left: left-hand input #VipsImage
400  * @right: right-hand input #VipsImage
401  * @out: (out): output #VipsImage
402  * @...: %NULL-terminated list of optional named arguments
403  *
404  * Perform #VIPS_OPERATION_RELATIONAL_LESS on a pair of images. See
405  * vips_relational().
406  *
407  * Returns: 0 on success, -1 on error
408  */
409 int
vips_less(VipsImage * left,VipsImage * right,VipsImage ** out,...)410 vips_less( VipsImage *left, VipsImage *right, VipsImage **out, ... )
411 {
412 	va_list ap;
413 	int result;
414 
415 	va_start( ap, out );
416 	result = vips_relationalv( left, right, out,
417 		VIPS_OPERATION_RELATIONAL_LESS, ap );
418 	va_end( ap );
419 
420 	return( result );
421 }
422 
423 /**
424  * vips_lesseq:
425  * @left: left-hand input #VipsImage
426  * @right: right-hand input #VipsImage
427  * @out: (out): output #VipsImage
428  * @...: %NULL-terminated list of optional named arguments
429  *
430  * Perform #VIPS_OPERATION_RELATIONAL_LESSEQ on a pair of images. See
431  * vips_relational().
432  *
433  * Returns: 0 on success, -1 on error
434  */
435 int
vips_lesseq(VipsImage * left,VipsImage * right,VipsImage ** out,...)436 vips_lesseq( VipsImage *left, VipsImage *right, VipsImage **out, ... )
437 {
438 	va_list ap;
439 	int result;
440 
441 	va_start( ap, out );
442 	result = vips_relationalv( left, right, out,
443 		VIPS_OPERATION_RELATIONAL_LESSEQ, ap );
444 	va_end( ap );
445 
446 	return( result );
447 }
448 
449 typedef struct _VipsRelationalConst {
450 	VipsUnaryConst parent_instance;
451 
452 	VipsOperationRelational relational;
453 } VipsRelationalConst;
454 
455 typedef VipsUnaryConstClass VipsRelationalConstClass;
456 
457 G_DEFINE_TYPE( VipsRelationalConst,
458 	vips_relational_const, VIPS_TYPE_UNARY_CONST );
459 
460 #define RLOOPCI( TYPE, OP ) { \
461 	TYPE * restrict p = (TYPE *) in[0]; \
462 	int * restrict c = uconst->c_int; \
463  	\
464 	for( i = 0, x = 0; x < width; x++ ) \
465 		for( b = 0; b < bands; b++, i++ ) \
466 			out[i] = (p[i] OP c[b]) ? 255 : 0; \
467 }
468 
469 #define RLOOPCF( TYPE, OP ) { \
470 	TYPE * restrict p = (TYPE *) in[0]; \
471 	double * restrict c = uconst->c_double; \
472  	\
473 	for( i = 0, x = 0; x < width; x++ ) \
474 		for( b = 0; b < bands; b++, i++ ) \
475 			out[i] = (p[i] OP c[b]) ? 255 : 0; \
476 }
477 
478 #define CLOOPC( TYPE, OP ) { \
479 	TYPE * restrict p = (TYPE *) in[0]; \
480  	\
481 	for( i = 0, x = 0; x < width; x++ ) { \
482 		double * restrict c = uconst->c_double; \
483 		\
484 		for( b = 0; b < bands; b++, i++ ) { \
485 			out[i] = OP( p[0], p[1], c[0], c[1]) ? 255 : 0; \
486 			\
487 			p += 2; \
488 			c += 2; \
489 		} \
490 	} \
491 }
492 
493 static void
vips_relational_const_buffer(VipsArithmetic * arithmetic,VipsPel * out,VipsPel ** in,int width)494 vips_relational_const_buffer( VipsArithmetic *arithmetic,
495 	VipsPel *out, VipsPel **in, int width )
496 {
497 	VipsUnaryConst *uconst = (VipsUnaryConst *) arithmetic;
498 	VipsRelationalConst *rconst = (VipsRelationalConst *) arithmetic;
499 	VipsImage *im = arithmetic->ready[0];
500 	int bands = im->Bands;
501 	gboolean is_int = uconst->is_int &&
502 		vips_band_format_isint( im->BandFmt );
503 
504 	int i, x, b;
505 
506 	switch( rconst->relational ) {
507 	case VIPS_OPERATION_RELATIONAL_EQUAL:
508 		if( is_int ) {
509 			SWITCH( RLOOPCI, CLOOPC, ==, CEQUAL );
510 		}
511 		else {
512 			SWITCH( RLOOPCF, CLOOPC, ==, CEQUAL );
513 		}
514 		break;
515 
516 	case VIPS_OPERATION_RELATIONAL_NOTEQ:
517 		if( is_int ) {
518 			SWITCH( RLOOPCI, CLOOPC, !=, CNOTEQ );
519 		}
520 		else {
521 			SWITCH( RLOOPCF, CLOOPC, !=, CNOTEQ );
522 		}
523 		break;
524 
525 	case VIPS_OPERATION_RELATIONAL_LESS:
526 		if( is_int ) {
527 			SWITCH( RLOOPCI, CLOOPC, <, CLESS );
528 		}
529 		else {
530 			SWITCH( RLOOPCF, CLOOPC, <, CLESS );
531 		}
532 		break;
533 
534 	case VIPS_OPERATION_RELATIONAL_LESSEQ:
535 		if( is_int ) {
536 			SWITCH( RLOOPCI, CLOOPC, <=, CLESSEQ );
537 		}
538 		else {
539 			SWITCH( RLOOPCF, CLOOPC, <=, CLESSEQ );
540 		}
541 		break;
542 
543 	case VIPS_OPERATION_RELATIONAL_MORE:
544 		if( is_int ) {
545 			SWITCH( RLOOPCI, CLOOPC, >, CMORE );
546 		}
547 		else {
548 			SWITCH( RLOOPCF, CLOOPC, >, CMORE );
549 		}
550 		break;
551 
552 	case VIPS_OPERATION_RELATIONAL_MOREEQ:
553 		if( is_int ) {
554 			SWITCH( RLOOPCI, CLOOPC, >=, CMOREEQ );
555 		}
556 		else {
557 			SWITCH( RLOOPCF, CLOOPC, >=, CMOREEQ );
558 		}
559 		break;
560 
561 	default:
562 		g_assert_not_reached();
563 	}
564 }
565 
566 static void
vips_relational_const_class_init(VipsRelationalConstClass * class)567 vips_relational_const_class_init( VipsRelationalConstClass *class )
568 {
569 	GObjectClass *gobject_class = G_OBJECT_CLASS( class );
570 	VipsObjectClass *object_class = (VipsObjectClass *) class;
571 	VipsArithmeticClass *aclass = VIPS_ARITHMETIC_CLASS( class );
572 
573 	gobject_class->set_property = vips_object_set_property;
574 	gobject_class->get_property = vips_object_get_property;
575 
576 	object_class->nickname = "relational_const";
577 	object_class->description =
578 		_( "relational operations against a constant" );
579 
580 	aclass->process_line = vips_relational_const_buffer;
581 
582 	vips_arithmetic_set_format_table( aclass,
583 		vips_relational_format_table );
584 
585 	VIPS_ARG_ENUM( class, "relational", 200,
586 		_( "Operation" ),
587 		_( "relational to perform" ),
588 		VIPS_ARGUMENT_REQUIRED_INPUT,
589 		G_STRUCT_OFFSET( VipsRelationalConst, relational ),
590 		VIPS_TYPE_OPERATION_RELATIONAL,
591 			VIPS_OPERATION_RELATIONAL_EQUAL );
592 }
593 
594 static void
vips_relational_const_init(VipsRelationalConst * relational_const)595 vips_relational_const_init( VipsRelationalConst *relational_const )
596 {
597 }
598 
599 static int
vips_relational_constv(VipsImage * in,VipsImage ** out,VipsOperationRelational relational,const double * c,int n,va_list ap)600 vips_relational_constv( VipsImage *in, VipsImage **out,
601 	VipsOperationRelational relational, const double *c, int n, va_list ap )
602 {
603 	VipsArea *area_c;
604 	double *array;
605 	int result;
606 	int i;
607 
608 	area_c = vips_area_new_array( G_TYPE_DOUBLE, sizeof( double ), n );
609 	array = (double *) area_c->data;
610 	for( i = 0; i < n; i++ )
611 		array[i] = c[i];
612 
613 	result = vips_call_split( "relational_const", ap,
614 		in, out, relational, area_c );
615 
616 	vips_area_unref( area_c );
617 
618 	return( result );
619 }
620 
621 /**
622  * vips_relational_const: (method)
623  * @in: input image
624  * @out: (out): output image
625  * @relational: relational operation to perform
626  * @c: (array length=n): array of constants
627  * @n: number of constants in @c
628  * @...: %NULL-terminated list of optional named arguments
629  *
630  * Perform various relational operations on an image and an array of
631  * constants.
632  *
633  * The output type is always uchar, with 0 for FALSE and 255 for TRUE.
634  *
635  * If the array of constants has just one element, that constant is used for
636  * all image bands. If the array has more than one element and they have
637  * the same number of elements as there are bands in the image, then
638  * one array element is used for each band. If the arrays have more than one
639  * element and the image only has a single band, the result is a many-band
640  * image where each band corresponds to one array element.
641  *
642  * See also: vips_boolean(), vips_relational().
643  *
644  * Returns: 0 on success, -1 on error
645  */
646 int
vips_relational_const(VipsImage * in,VipsImage ** out,VipsOperationRelational relational,const double * c,int n,...)647 vips_relational_const( VipsImage *in, VipsImage **out,
648 	VipsOperationRelational relational, const double *c, int n, ... )
649 {
650 	va_list ap;
651 	int result;
652 
653 	va_start( ap, n );
654 	result = vips_relational_constv( in, out, relational, c, n, ap );
655 	va_end( ap );
656 
657 	return( result );
658 }
659 
660 /**
661  * vips_equal_const: (method)
662  * @in: input #VipsImage
663  * @out: (out): output #VipsImage
664  * @c: (array length=n): array of constants
665  * @n: number of constants in @c
666  * @...: %NULL-terminated list of optional named arguments
667  *
668  * Perform #VIPS_OPERATION_RELATIONAL_EQUAL on an image and a constant. See
669  * vips_relational_const().
670  *
671  * Returns: 0 on success, -1 on error
672  */
673 int
vips_equal_const(VipsImage * in,VipsImage ** out,const double * c,int n,...)674 vips_equal_const( VipsImage *in, VipsImage **out, const double *c, int n, ... )
675 {
676 	va_list ap;
677 	int result;
678 
679 	va_start( ap, n );
680 	result = vips_relational_constv( in, out,
681 		VIPS_OPERATION_RELATIONAL_EQUAL, c, n, ap );
682 	va_end( ap );
683 
684 	return( result );
685 }
686 
687 /**
688  * vips_notequal_const: (method)
689  * @in: input #VipsImage
690  * @out: (out): output #VipsImage
691  * @c: (array length=n): array of constants
692  * @n: number of constants in @c
693  * @...: %NULL-terminated list of optional named arguments
694  *
695  * Perform #VIPS_OPERATION_RELATIONAL_NOTEQ on an image and a constant. See
696  * vips_relational_const().
697  *
698  * Returns: 0 on success, -1 on error
699  */
700 int
vips_notequal_const(VipsImage * in,VipsImage ** out,const double * c,int n,...)701 vips_notequal_const( VipsImage *in, VipsImage **out,
702 	const double *c, int n, ... )
703 {
704 	va_list ap;
705 	int result;
706 
707 	va_start( ap, n );
708 	result = vips_relational_constv( in, out,
709 		VIPS_OPERATION_RELATIONAL_NOTEQ, c, n, ap );
710 	va_end( ap );
711 
712 	return( result );
713 }
714 
715 /**
716  * vips_less_const: (method)
717  * @in: input #VipsImage
718  * @out: (out): output #VipsImage
719  * @c: (array length=n): array of constants
720  * @n: number of constants in @c
721  * @...: %NULL-terminated list of optional named arguments
722  *
723  * Perform #VIPS_OPERATION_RELATIONAL_LESS on an image and a constant. See
724  * vips_relational_const().
725  *
726  * Returns: 0 on success, -1 on error
727  */
728 int
vips_less_const(VipsImage * in,VipsImage ** out,const double * c,int n,...)729 vips_less_const( VipsImage *in, VipsImage **out, const double *c, int n, ... )
730 {
731 	va_list ap;
732 	int result;
733 
734 	va_start( ap, n );
735 	result = vips_relational_constv( in, out,
736 		VIPS_OPERATION_RELATIONAL_LESS, c, n, ap );
737 	va_end( ap );
738 
739 	return( result );
740 }
741 
742 /**
743  * vips_lesseq_const: (method)
744  * @in: input #VipsImage
745  * @out: (out): output #VipsImage
746  * @c: (array length=n): array of constants
747  * @n: number of constants in @c
748  * @...: %NULL-terminated list of optional named arguments
749  *
750  * Perform #VIPS_OPERATION_RELATIONAL_LESSEQ on an image and a constant. See
751  * vips_relational_const().
752  *
753  * Returns: 0 on success, -1 on error
754  */
755 int
vips_lesseq_const(VipsImage * in,VipsImage ** out,const double * c,int n,...)756 vips_lesseq_const( VipsImage *in, VipsImage **out, const double *c, int n, ... )
757 {
758 	va_list ap;
759 	int result;
760 
761 	va_start( ap, n );
762 	result = vips_relational_constv( in, out,
763 		VIPS_OPERATION_RELATIONAL_LESSEQ, c, n, ap );
764 	va_end( ap );
765 
766 	return( result );
767 }
768 
769 /**
770  * vips_more_const: (method)
771  * @in: input #VipsImage
772  * @out: (out): output #VipsImage
773  * @c: (array length=n): array of constants
774  * @n: number of constants in @c
775  * @...: %NULL-terminated list of optional named arguments
776  *
777  * Perform #VIPS_OPERATION_RELATIONAL_MORE on an image and a constant. See
778  * vips_relational_const().
779  *
780  * Returns: 0 on success, -1 on error
781  */
782 int
vips_more_const(VipsImage * in,VipsImage ** out,const double * c,int n,...)783 vips_more_const( VipsImage *in, VipsImage **out, const double *c, int n, ... )
784 {
785 	va_list ap;
786 	int result;
787 
788 	va_start( ap, n );
789 	result = vips_relational_constv( in, out,
790 		VIPS_OPERATION_RELATIONAL_MORE, c, n, ap );
791 	va_end( ap );
792 
793 	return( result );
794 }
795 
796 /**
797  * vips_moreeq_const: (method)
798  * @in: input #VipsImage
799  * @out: (out): output #VipsImage
800  * @c: (array length=n): array of constants
801  * @n: number of constants in @c
802  * @...: %NULL-terminated list of optional named arguments
803  *
804  * Perform #VIPS_OPERATION_RELATIONAL_MOREEQ on an image and a constant. See
805  * vips_relational_const().
806  *
807  * Returns: 0 on success, -1 on error
808  */
809 int
vips_moreeq_const(VipsImage * in,VipsImage ** out,const double * c,int n,...)810 vips_moreeq_const( VipsImage *in, VipsImage **out, const double *c, int n, ... )
811 {
812 	va_list ap;
813 	int result;
814 
815 	va_start( ap, n );
816 	result = vips_relational_constv( in, out,
817 		VIPS_OPERATION_RELATIONAL_MOREEQ, c, n, ap );
818 	va_end( ap );
819 
820 	return( result );
821 }
822 
823 /**
824  * vips_relational_const1: (method)
825  * @in: input image
826  * @out: (out): output image
827  * @relational: relational operation to perform
828  * @c: constant
829  * @...: %NULL-terminated list of optional named arguments
830  *
831  * Perform various relational operations on an image and a constant. See
832  * vips_relational_const().
833  *
834  * See also: vips_boolean(), vips_relational().
835  *
836  * Returns: 0 on success, -1 on error
837  */
838 int
vips_relational_const1(VipsImage * in,VipsImage ** out,VipsOperationRelational relational,double c,...)839 vips_relational_const1( VipsImage *in, VipsImage **out,
840 	VipsOperationRelational relational, double c, ... )
841 {
842 	va_list ap;
843 	int result;
844 
845 	va_start( ap, c );
846 	result = vips_relational_constv( in, out, relational, &c, 1, ap );
847 	va_end( ap );
848 
849 	return( result );
850 }
851 
852 /**
853  * vips_equal_const1: (method)
854  * @in: input image
855  * @out: (out): output image
856  * @c: constant
857  * @...: %NULL-terminated list of optional named arguments
858  *
859  * Perform #VIPS_OPERATION_RELATIONAL_EQUAL on an image and a constant. See
860  * vips_relational_const().
861  *
862  * Returns: 0 on success, -1 on error
863  */
864 int
vips_equal_const1(VipsImage * in,VipsImage ** out,double c,...)865 vips_equal_const1( VipsImage *in, VipsImage **out, double c, ... )
866 {
867 	va_list ap;
868 	int result;
869 
870 	va_start( ap, c );
871 	result = vips_relational_constv( in, out,
872 		VIPS_OPERATION_RELATIONAL_EQUAL, &c, 1, ap );
873 	va_end( ap );
874 
875 	return( result );
876 }
877 
878 /**
879  * vips_notequal_const1: (method)
880  * @in: input image
881  * @out: (out): output image
882  * @c: constant
883  * @...: %NULL-terminated list of optional named arguments
884  *
885  * Perform #VIPS_OPERATION_RELATIONAL_NOTEQ on an image and a constant. See
886  * vips_relational_const().
887  *
888  * Returns: 0 on success, -1 on error
889  */
890 int
vips_notequal_const1(VipsImage * in,VipsImage ** out,double c,...)891 vips_notequal_const1( VipsImage *in, VipsImage **out, double c, ... )
892 {
893 	va_list ap;
894 	int result;
895 
896 	va_start( ap, c );
897 	result = vips_relational_constv( in, out,
898 		VIPS_OPERATION_RELATIONAL_NOTEQ, &c, 1, ap );
899 	va_end( ap );
900 
901 	return( result );
902 }
903 
904 /**
905  * vips_less_const1: (method)
906  * @in: input image
907  * @out: (out): output image
908  * @c: constant
909  * @...: %NULL-terminated list of optional named arguments
910  *
911  * Perform #VIPS_OPERATION_RELATIONAL_LESS on an image and a constant. See
912  * vips_relational_const().
913  *
914  * Returns: 0 on success, -1 on error
915  */
916 int
vips_less_const1(VipsImage * in,VipsImage ** out,double c,...)917 vips_less_const1( VipsImage *in, VipsImage **out, double c, ... )
918 {
919 	va_list ap;
920 	int result;
921 
922 	va_start( ap, c );
923 	result = vips_relational_constv( in, out,
924 		VIPS_OPERATION_RELATIONAL_LESS, &c, 1, ap );
925 	va_end( ap );
926 
927 	return( result );
928 }
929 
930 /**
931  * vips_lesseq_const1: (method)
932  * @in: input image
933  * @out: (out): output image
934  * @c: constant
935  * @...: %NULL-terminated list of optional named arguments
936  *
937  * Perform #VIPS_OPERATION_RELATIONAL_LESSEQ on an image and a constant. See
938  * vips_relational_const().
939  *
940  * Returns: 0 on success, -1 on error
941  */
942 int
vips_lesseq_const1(VipsImage * in,VipsImage ** out,double c,...)943 vips_lesseq_const1( VipsImage *in, VipsImage **out, double c, ... )
944 {
945 	va_list ap;
946 	int result;
947 
948 	va_start( ap, c );
949 	result = vips_relational_constv( in, out,
950 		VIPS_OPERATION_RELATIONAL_LESSEQ, &c, 1, ap );
951 	va_end( ap );
952 
953 	return( result );
954 }
955 
956 /**
957  * vips_more_const1: (method)
958  * @in: input image
959  * @out: (out): output image
960  * @c: constant
961  * @...: %NULL-terminated list of optional named arguments
962  *
963  * Perform #VIPS_OPERATION_RELATIONAL_MORE on an image and a constant. See
964  * vips_relational_const().
965  *
966  * Returns: 0 on success, -1 on error
967  */
968 int
vips_more_const1(VipsImage * in,VipsImage ** out,double c,...)969 vips_more_const1( VipsImage *in, VipsImage **out, double c, ... )
970 {
971 	va_list ap;
972 	int result;
973 
974 	va_start( ap, c );
975 	result = vips_relational_constv( in, out,
976 		VIPS_OPERATION_RELATIONAL_MORE, &c, 1, ap );
977 	va_end( ap );
978 
979 	return( result );
980 }
981 
982 /**
983  * vips_moreeq_const1: (method)
984  * @in: input image
985  * @out: (out): output image
986  * @c: constant
987  * @...: %NULL-terminated list of optional named arguments
988  *
989  * Perform #VIPS_OPERATION_RELATIONAL_MOREEQ on an image and a constant. See
990  * vips_relational_const().
991  *
992  * Returns: 0 on success, -1 on error
993  */
994 int
vips_moreeq_const1(VipsImage * in,VipsImage ** out,double c,...)995 vips_moreeq_const1( VipsImage *in, VipsImage **out, double c, ... )
996 {
997 	va_list ap;
998 	int result;
999 
1000 	va_start( ap, c );
1001 	result = vips_relational_constv( in, out,
1002 		VIPS_OPERATION_RELATIONAL_MOREEQ, &c, 1, ap );
1003 	va_end( ap );
1004 
1005 	return( result );
1006 }
1007 
1008