Coverage Report

Created: 2025-11-16 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvips/libvips/arithmetic/relational.c
Line
Count
Source
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 <glib/gi18n-lib.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
34
G_DEFINE_TYPE(VipsRelational, vips_relational, VIPS_TYPE_BINARY);
91
34
92
34
#define RLOOP(TYPE, ROP) \
93
34
  { \
94
0
    TYPE *restrict left = (TYPE *) in0; \
95
0
    TYPE *restrict right = (TYPE *) in1; \
96
0
    VipsPel *restrict q = (VipsPel *) out; \
97
0
\
98
0
    for (x = 0; x < sz; x++) \
99
0
      q[x] = (left[x] ROP right[x]) ? 255 : 0; \
100
0
  }
101
102
#define CLOOP(TYPE, COP) \
103
0
  { \
104
0
    TYPE *restrict left = (TYPE *) in0; \
105
0
    TYPE *restrict right = (TYPE *) in1; \
106
0
    VipsPel *restrict q = (VipsPel *) out; \
107
0
\
108
0
    for (x = 0; x < sz; x++) { \
109
0
      q[x] = COP(left[0], left[1], right[0], right[1]) ? 255 : 0; \
110
0
\
111
0
      left += 2; \
112
0
      right += 2; \
113
0
    } \
114
0
  }
115
116
#define SWITCH(R, C, ROP, COP) \
117
187k
  switch (vips_image_get_format(im)) { \
118
0
  case VIPS_FORMAT_UCHAR: \
119
0
    R(unsigned char, ROP); \
120
0
    break; \
121
0
  case VIPS_FORMAT_CHAR: \
122
0
    R(signed char, ROP); \
123
0
    break; \
124
0
  case VIPS_FORMAT_USHORT: \
125
0
    R(unsigned short, ROP); \
126
0
    break; \
127
0
  case VIPS_FORMAT_SHORT: \
128
0
    R(signed short, ROP); \
129
0
    break; \
130
0
  case VIPS_FORMAT_UINT: \
131
0
    R(unsigned int, ROP); \
132
0
    break; \
133
0
  case VIPS_FORMAT_INT: \
134
0
    R(signed int, ROP); \
135
0
    break; \
136
187k
  case VIPS_FORMAT_FLOAT: \
137
187k
    R(float, ROP); \
138
187k
    break; \
139
0
  case VIPS_FORMAT_DOUBLE: \
140
0
    R(double, ROP); \
141
0
    break; \
142
0
  case VIPS_FORMAT_COMPLEX: \
143
0
    C(float, COP); \
144
0
    break; \
145
0
  case VIPS_FORMAT_DPCOMPLEX: \
146
0
    C(double, COP); \
147
0
    break; \
148
0
\
149
0
  default: \
150
0
    g_assert_not_reached(); \
151
187k
  }
152
153
0
#define CEQUAL(x1, y1, x2, y2) (x1 == x2 && y1 == y2)
154
0
#define CNOTEQ(x1, y1, x2, y2) (x1 != x2 || y1 != y2)
155
0
#define CLESS(x1, y1, x2, y2) (x1 * x1 + y1 * y1 < x2 * x2 + y2 * y2)
156
0
#define CLESSEQ(x1, y1, x2, y2) (x1 * x1 + y1 * y1 <= x2 * x2 + y2 * y2)
157
0
#define CMORE(x1, y1, x2, y2) (x1 * x1 + y1 * y1 > x2 * x2 + y2 * y2)
158
0
#define CMOREEQ(x1, y1, x2, y2) (x1 * x1 + y1 * y1 >= x2 * x2 + y2 * y2)
159
160
static void
161
vips_relational_buffer(VipsArithmetic *arithmetic,
162
  VipsPel *out, VipsPel **in, int width)
163
0
{
164
0
  VipsRelational *relational = (VipsRelational *) arithmetic;
165
0
  VipsImage *im = arithmetic->ready[0];
166
0
  const int sz = width * vips_image_get_bands(im);
167
168
0
  VipsOperationRelational op;
169
0
  VipsPel *in0;
170
0
  VipsPel *in1;
171
0
  int x;
172
173
0
  in0 = in[0];
174
0
  in1 = in[1];
175
0
  op = relational->relational;
176
177
0
  if (op == VIPS_OPERATION_RELATIONAL_MORE) {
178
0
    op = VIPS_OPERATION_RELATIONAL_LESS;
179
0
    VIPS_SWAP(VipsPel *, in0, in1);
180
0
  }
181
182
0
  if (op == VIPS_OPERATION_RELATIONAL_MOREEQ) {
183
0
    op = VIPS_OPERATION_RELATIONAL_LESSEQ;
184
0
    VIPS_SWAP(VipsPel *, in0, in1);
185
0
  }
186
187
0
  switch (op) {
188
0
  case VIPS_OPERATION_RELATIONAL_EQUAL:
189
0
    SWITCH(RLOOP, CLOOP, ==, CEQUAL);
190
0
    break;
191
192
0
  case VIPS_OPERATION_RELATIONAL_NOTEQ:
193
0
    SWITCH(RLOOP, CLOOP, !=, CNOTEQ);
194
0
    break;
195
196
0
  case VIPS_OPERATION_RELATIONAL_LESS:
197
0
    SWITCH(RLOOP, CLOOP, <, CLESS);
198
0
    break;
199
200
0
  case VIPS_OPERATION_RELATIONAL_LESSEQ:
201
0
    SWITCH(RLOOP, CLOOP, <=, CLESSEQ);
202
0
    break;
203
204
0
  default:
205
0
    g_assert_not_reached();
206
0
  }
207
0
}
208
209
/* Save a bit of typing.
210
 */
211
#define UC VIPS_FORMAT_UCHAR
212
#define C VIPS_FORMAT_CHAR
213
#define US VIPS_FORMAT_USHORT
214
#define S VIPS_FORMAT_SHORT
215
#define UI VIPS_FORMAT_UINT
216
#define I VIPS_FORMAT_INT
217
#define F VIPS_FORMAT_FLOAT
218
#define X VIPS_FORMAT_COMPLEX
219
#define D VIPS_FORMAT_DOUBLE
220
#define DX VIPS_FORMAT_DPCOMPLEX
221
222
static const VipsBandFormat vips_relational_format_table[10] = {
223
  /* Band format:  UC  C   US  S   UI  I   F   X   D   DX */
224
  /* Promotion: */ UC, UC, UC, UC, UC, UC, UC, UC, UC, UC
225
};
226
227
static void
228
vips_relational_class_init(VipsRelationalClass *class)
229
17
{
230
17
  GObjectClass *gobject_class = G_OBJECT_CLASS(class);
231
17
  VipsObjectClass *object_class = (VipsObjectClass *) class;
232
17
  VipsArithmeticClass *aclass = VIPS_ARITHMETIC_CLASS(class);
233
234
17
  gobject_class->set_property = vips_object_set_property;
235
17
  gobject_class->get_property = vips_object_get_property;
236
237
17
  object_class->nickname = "relational";
238
17
  object_class->description = _("relational operation on two images");
239
240
17
  aclass->process_line = vips_relational_buffer;
241
242
17
  vips_arithmetic_set_format_table(aclass,
243
17
    vips_relational_format_table);
244
245
17
  VIPS_ARG_ENUM(class, "relational", 200,
246
17
    _("Operation"),
247
17
    _("Relational to perform"),
248
17
    VIPS_ARGUMENT_REQUIRED_INPUT,
249
17
    G_STRUCT_OFFSET(VipsRelational, relational),
250
17
    VIPS_TYPE_OPERATION_RELATIONAL,
251
17
    VIPS_OPERATION_RELATIONAL_EQUAL);
252
17
}
253
254
static void
255
vips_relational_init(VipsRelational *relational)
256
0
{
257
0
}
258
259
static int
260
vips_relationalv(VipsImage *left, VipsImage *right, VipsImage **out,
261
  VipsOperationRelational relational, va_list ap)
262
0
{
263
0
  return vips_call_split("relational", ap, left, right, out,
264
0
    relational);
265
0
}
266
267
/**
268
 * vips_relational: (method)
269
 * @left: left-hand input [class@Image]
270
 * @right: right-hand input [class@Image]
271
 * @out: (out): output [class@Image]
272
 * @relational: relational operation to perform
273
 * @...: `NULL`-terminated list of optional named arguments
274
 *
275
 * Perform various relational operations on pairs of images.
276
 *
277
 * The output type is always uchar, with 0 for `FALSE` and 255 for `TRUE`.
278
 *
279
 * Less-than and greater-than for complex images compare the modulus.
280
 *
281
 * If the images differ in size, the smaller image is enlarged to match the
282
 * larger by adding zero pixels along the bottom and right.
283
 *
284
 * If the number of bands differs, one of the images
285
 * must have one band. In this case, an n-band image is formed from the
286
 * one-band image by joining n copies of the one-band image together, and then
287
 * the two n-band images are operated upon.
288
 *
289
 * The two input images are cast up to the smallest common format (see table
290
 * Smallest common format in
291
 * [arithmetic](libvips-arithmetic.html)).
292
 *
293
 * To decide if pixels match exactly, that is have the same value in every
294
 * band, use [method@Image.bandbool] after this operation to AND or OR image
295
 * bands together.
296
 *
297
 * ::: seealso
298
 *     [method@Image.boolean], [method@Image.bandbool],
299
 *     [method@Image.relational_const].
300
 *
301
 * Returns: 0 on success, -1 on error
302
 */
303
int
304
vips_relational(VipsImage *left, VipsImage *right, VipsImage **out,
305
  VipsOperationRelational relational, ...)
306
0
{
307
0
  va_list ap;
308
0
  int result;
309
310
0
  va_start(ap, relational);
311
0
  result = vips_relationalv(left, right, out, relational, ap);
312
0
  va_end(ap);
313
314
0
  return result;
315
0
}
316
317
/**
318
 * vips_equal: (method)
319
 * @left: left-hand input [class@Image]
320
 * @right: right-hand input [class@Image]
321
 * @out: (out): output [class@Image]
322
 * @...: `NULL`-terminated list of optional named arguments
323
 *
324
 * Perform [enum@Vips.OperationRelational.EQUAL] on a pair of images. See
325
 * [method@Image.relational].
326
 *
327
 * Returns: 0 on success, -1 on error
328
 */
329
int
330
vips_equal(VipsImage *left, VipsImage *right, VipsImage **out, ...)
331
0
{
332
0
  va_list ap;
333
0
  int result;
334
335
0
  va_start(ap, out);
336
0
  result = vips_relationalv(left, right, out,
337
0
    VIPS_OPERATION_RELATIONAL_EQUAL, ap);
338
0
  va_end(ap);
339
340
0
  return result;
341
0
}
342
343
/**
344
 * vips_notequal: (method)
345
 * @left: left-hand input [class@Image]
346
 * @right: right-hand input [class@Image]
347
 * @out: (out): output [class@Image]
348
 * @...: `NULL`-terminated list of optional named arguments
349
 *
350
 * Perform [enum@Vips.OperationRelational.NOTEQ] on a pair of images. See
351
 * [method@Image.relational].
352
 *
353
 * Returns: 0 on success, -1 on error
354
 */
355
int
356
vips_notequal(VipsImage *left, VipsImage *right, VipsImage **out, ...)
357
0
{
358
0
  va_list ap;
359
0
  int result;
360
361
0
  va_start(ap, out);
362
0
  result = vips_relationalv(left, right, out,
363
0
    VIPS_OPERATION_RELATIONAL_NOTEQ, ap);
364
0
  va_end(ap);
365
366
0
  return result;
367
0
}
368
369
/**
370
 * vips_more: (method)
371
 * @left: left-hand input [class@Image]
372
 * @right: right-hand input [class@Image]
373
 * @out: (out): output [class@Image]
374
 * @...: `NULL`-terminated list of optional named arguments
375
 *
376
 * Perform [enum@Vips.OperationRelational.MORE] on a pair of images. See
377
 * [method@Image.relational].
378
 *
379
 * Returns: 0 on success, -1 on error
380
 */
381
int
382
vips_more(VipsImage *left, VipsImage *right, VipsImage **out, ...)
383
0
{
384
0
  va_list ap;
385
0
  int result;
386
387
0
  va_start(ap, out);
388
0
  result = vips_relationalv(left, right, out,
389
0
    VIPS_OPERATION_RELATIONAL_MORE, ap);
390
0
  va_end(ap);
391
392
0
  return result;
393
0
}
394
395
/**
396
 * vips_moreeq: (method)
397
 * @left: left-hand input [class@Image]
398
 * @right: right-hand input [class@Image]
399
 * @out: (out): output [class@Image]
400
 * @...: `NULL`-terminated list of optional named arguments
401
 *
402
 * Perform [enum@Vips.OperationRelational.MOREEQ] on a pair of images. See
403
 * [method@Image.relational].
404
 *
405
 * Returns: 0 on success, -1 on error
406
 */
407
int
408
vips_moreeq(VipsImage *left, VipsImage *right, VipsImage **out, ...)
409
0
{
410
0
  va_list ap;
411
0
  int result;
412
413
0
  va_start(ap, out);
414
0
  result = vips_relationalv(left, right, out,
415
0
    VIPS_OPERATION_RELATIONAL_MOREEQ, ap);
416
0
  va_end(ap);
417
418
0
  return result;
419
0
}
420
421
/**
422
 * vips_less: (method)
423
 * @left: left-hand input [class@Image]
424
 * @right: right-hand input [class@Image]
425
 * @out: (out): output [class@Image]
426
 * @...: `NULL`-terminated list of optional named arguments
427
 *
428
 * Perform [enum@Vips.OperationRelational.LESS] on a pair of images. See
429
 * [method@Image.relational].
430
 *
431
 * Returns: 0 on success, -1 on error
432
 */
433
int
434
vips_less(VipsImage *left, VipsImage *right, VipsImage **out, ...)
435
0
{
436
0
  va_list ap;
437
0
  int result;
438
439
0
  va_start(ap, out);
440
0
  result = vips_relationalv(left, right, out,
441
0
    VIPS_OPERATION_RELATIONAL_LESS, ap);
442
0
  va_end(ap);
443
444
0
  return result;
445
0
}
446
447
/**
448
 * vips_lesseq: (method)
449
 * @left: left-hand input [class@Image]
450
 * @right: right-hand input [class@Image]
451
 * @out: (out): output [class@Image]
452
 * @...: `NULL`-terminated list of optional named arguments
453
 *
454
 * Perform [enum@Vips.OperationRelational.LESSEQ] on a pair of images. See
455
 * [method@Image.relational].
456
 *
457
 * Returns: 0 on success, -1 on error
458
 */
459
int
460
vips_lesseq(VipsImage *left, VipsImage *right, VipsImage **out, ...)
461
0
{
462
0
  va_list ap;
463
0
  int result;
464
465
0
  va_start(ap, out);
466
0
  result = vips_relationalv(left, right, out,
467
0
    VIPS_OPERATION_RELATIONAL_LESSEQ, ap);
468
0
  va_end(ap);
469
470
0
  return result;
471
0
}
472
473
typedef struct _VipsRelationalConst {
474
  VipsUnaryConst parent_instance;
475
476
  VipsOperationRelational relational;
477
} VipsRelationalConst;
478
479
typedef VipsUnaryConstClass VipsRelationalConstClass;
480
481
34
G_DEFINE_TYPE(VipsRelationalConst,
482
34
  vips_relational_const, VIPS_TYPE_UNARY_CONST);
483
34
484
34
#define RLOOPCI(TYPE, OP) \
485
34
  { \
486
0
    TYPE *restrict p = (TYPE *) in[0]; \
487
0
    int *restrict c = uconst->c_int; \
488
0
\
489
0
    for (i = 0, x = 0; x < width; x++) \
490
0
      for (b = 0; b < bands; b++, i++) \
491
0
        out[i] = (p[i] OP c[b]) ? 255 : 0; \
492
0
  }
493
494
#define RLOOPCF(TYPE, OP) \
495
187k
  { \
496
187k
    TYPE *restrict p = (TYPE *) in[0]; \
497
187k
    double *restrict c = uconst->c_double; \
498
187k
\
499
6.18M
    for (i = 0, x = 0; x < width; x++) \
500
11.9M
      for (b = 0; b < bands; b++, i++) \
501
5.99M
        out[i] = (p[i] OP c[b]) ? 255 : 0; \
502
187k
  }
503
504
#define CLOOPC(TYPE, OP) \
505
0
  { \
506
0
    TYPE *restrict p = (TYPE *) in[0]; \
507
0
\
508
0
    for (i = 0, x = 0; x < width; x++) { \
509
0
      double *restrict c = uconst->c_double; \
510
0
\
511
0
      for (b = 0; b < bands; b++, i++) { \
512
0
        out[i] = OP(p[0], p[1], c[0], c[1]) ? 255 : 0; \
513
0
\
514
0
        p += 2; \
515
0
        c += 2; \
516
0
      } \
517
0
    } \
518
0
  }
519
520
static void
521
vips_relational_const_buffer(VipsArithmetic *arithmetic,
522
  VipsPel *out, VipsPel **in, int width)
523
187k
{
524
187k
  VipsUnaryConst *uconst = (VipsUnaryConst *) arithmetic;
525
187k
  VipsRelationalConst *rconst = (VipsRelationalConst *) arithmetic;
526
187k
  VipsImage *im = arithmetic->ready[0];
527
187k
  int bands = im->Bands;
528
187k
  gboolean is_int = uconst->is_int &&
529
187k
    vips_band_format_isint(im->BandFmt);
530
531
187k
  int i, x, b;
532
533
187k
  switch (rconst->relational) {
534
0
  case VIPS_OPERATION_RELATIONAL_EQUAL:
535
0
    if (is_int) {
536
0
      SWITCH(RLOOPCI, CLOOPC, ==, CEQUAL);
537
0
    }
538
0
    else {
539
0
      SWITCH(RLOOPCF, CLOOPC, ==, CEQUAL);
540
0
    }
541
0
    break;
542
543
0
  case VIPS_OPERATION_RELATIONAL_NOTEQ:
544
0
    if (is_int) {
545
0
      SWITCH(RLOOPCI, CLOOPC, !=, CNOTEQ);
546
0
    }
547
0
    else {
548
0
      SWITCH(RLOOPCF, CLOOPC, !=, CNOTEQ);
549
0
    }
550
0
    break;
551
552
0
  case VIPS_OPERATION_RELATIONAL_LESS:
553
0
    if (is_int) {
554
0
      SWITCH(RLOOPCI, CLOOPC, <, CLESS);
555
0
    }
556
0
    else {
557
0
      SWITCH(RLOOPCF, CLOOPC, <, CLESS);
558
0
    }
559
0
    break;
560
561
0
  case VIPS_OPERATION_RELATIONAL_LESSEQ:
562
0
    if (is_int) {
563
0
      SWITCH(RLOOPCI, CLOOPC, <=, CLESSEQ);
564
0
    }
565
0
    else {
566
0
      SWITCH(RLOOPCF, CLOOPC, <=, CLESSEQ);
567
0
    }
568
0
    break;
569
570
187k
  case VIPS_OPERATION_RELATIONAL_MORE:
571
187k
    if (is_int) {
572
0
      SWITCH(RLOOPCI, CLOOPC, >, CMORE);
573
0
    }
574
187k
    else {
575
187k
      SWITCH(RLOOPCF, CLOOPC, >, CMORE);
576
187k
    }
577
187k
    break;
578
579
187k
  case VIPS_OPERATION_RELATIONAL_MOREEQ:
580
0
    if (is_int) {
581
0
      SWITCH(RLOOPCI, CLOOPC, >=, CMOREEQ);
582
0
    }
583
0
    else {
584
0
      SWITCH(RLOOPCF, CLOOPC, >=, CMOREEQ);
585
0
    }
586
0
    break;
587
588
0
  default:
589
0
    g_assert_not_reached();
590
187k
  }
591
187k
}
592
593
static void
594
vips_relational_const_class_init(VipsRelationalConstClass *class)
595
17
{
596
17
  GObjectClass *gobject_class = G_OBJECT_CLASS(class);
597
17
  VipsObjectClass *object_class = (VipsObjectClass *) class;
598
17
  VipsArithmeticClass *aclass = VIPS_ARITHMETIC_CLASS(class);
599
600
17
  gobject_class->set_property = vips_object_set_property;
601
17
  gobject_class->get_property = vips_object_get_property;
602
603
17
  object_class->nickname = "relational_const";
604
17
  object_class->description =
605
17
    _("relational operations against a constant");
606
607
17
  aclass->process_line = vips_relational_const_buffer;
608
609
17
  vips_arithmetic_set_format_table(aclass,
610
17
    vips_relational_format_table);
611
612
17
  VIPS_ARG_ENUM(class, "relational", 200,
613
17
    _("Operation"),
614
17
    _("Relational to perform"),
615
17
    VIPS_ARGUMENT_REQUIRED_INPUT,
616
17
    G_STRUCT_OFFSET(VipsRelationalConst, relational),
617
17
    VIPS_TYPE_OPERATION_RELATIONAL,
618
17
    VIPS_OPERATION_RELATIONAL_EQUAL);
619
17
}
620
621
static void
622
vips_relational_const_init(VipsRelationalConst *relational_const)
623
15.1k
{
624
15.1k
}
625
626
static int
627
vips_relational_constv(VipsImage *in, VipsImage **out,
628
  VipsOperationRelational relational, const double *c, int n, va_list ap)
629
15.1k
{
630
15.1k
  VipsArea *area_c;
631
15.1k
  double *array;
632
15.1k
  int result;
633
15.1k
  int i;
634
635
15.1k
  area_c = vips_area_new_array(G_TYPE_DOUBLE, sizeof(double), n);
636
15.1k
  array = (double *) area_c->data;
637
30.2k
  for (i = 0; i < n; i++)
638
15.1k
    array[i] = c[i];
639
640
15.1k
  result = vips_call_split("relational_const", ap,
641
15.1k
    in, out, relational, area_c);
642
643
15.1k
  vips_area_unref(area_c);
644
645
15.1k
  return result;
646
15.1k
}
647
648
/**
649
 * vips_relational_const: (method)
650
 * @in: input image
651
 * @out: (out): output image
652
 * @relational: relational operation to perform
653
 * @c: (array length=n): array of constants
654
 * @n: number of constants in @c
655
 * @...: `NULL`-terminated list of optional named arguments
656
 *
657
 * Perform various relational operations on an image and an array of
658
 * constants.
659
 *
660
 * The output type is always uchar, with 0 for `FALSE` and 255 for `TRUE`.
661
 *
662
 * If the array of constants has just one element, that constant is used for
663
 * all image bands. If the array has more than one element and they have
664
 * the same number of elements as there are bands in the image, then
665
 * one array element is used for each band. If the arrays have more than one
666
 * element and the image only has a single band, the result is a many-band
667
 * image where each band corresponds to one array element.
668
 *
669
 * ::: seealso
670
 *     [method@Image.boolean], [method@Image.relational].
671
 *
672
 * Returns: 0 on success, -1 on error
673
 */
674
int
675
vips_relational_const(VipsImage *in, VipsImage **out,
676
  VipsOperationRelational relational, const double *c, int n, ...)
677
0
{
678
0
  va_list ap;
679
0
  int result;
680
681
0
  va_start(ap, n);
682
0
  result = vips_relational_constv(in, out, relational, c, n, ap);
683
0
  va_end(ap);
684
685
0
  return result;
686
0
}
687
688
/**
689
 * vips_equal_const: (method)
690
 * @in: input [class@Image]
691
 * @out: (out): output [class@Image]
692
 * @c: (array length=n): array of constants
693
 * @n: number of constants in @c
694
 * @...: `NULL`-terminated list of optional named arguments
695
 *
696
 * Perform [enum@Vips.OperationRelational.EQUAL] on an image and a constant. See
697
 * [method@Image.relational_const].
698
 *
699
 * Returns: 0 on success, -1 on error
700
 */
701
int
702
vips_equal_const(VipsImage *in, VipsImage **out, const double *c, int n, ...)
703
0
{
704
0
  va_list ap;
705
0
  int result;
706
707
0
  va_start(ap, n);
708
0
  result = vips_relational_constv(in, out,
709
0
    VIPS_OPERATION_RELATIONAL_EQUAL, c, n, ap);
710
0
  va_end(ap);
711
712
0
  return result;
713
0
}
714
715
/**
716
 * vips_notequal_const: (method)
717
 * @in: input [class@Image]
718
 * @out: (out): output [class@Image]
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 [enum@Vips.OperationRelational.NOTEQ] on an image and a constant. See
724
 * [method@Image.relational_const].
725
 *
726
 * Returns: 0 on success, -1 on error
727
 */
728
int
729
vips_notequal_const(VipsImage *in, VipsImage **out,
730
  const double *c, int n, ...)
731
0
{
732
0
  va_list ap;
733
0
  int result;
734
735
0
  va_start(ap, n);
736
0
  result = vips_relational_constv(in, out,
737
0
    VIPS_OPERATION_RELATIONAL_NOTEQ, c, n, ap);
738
0
  va_end(ap);
739
740
0
  return result;
741
0
}
742
743
/**
744
 * vips_less_const: (method)
745
 * @in: input [class@Image]
746
 * @out: (out): output [class@Image]
747
 * @c: (array length=n): array of constants
748
 * @n: number of constants in @c
749
 * @...: `NULL`-terminated list of optional named arguments
750
 *
751
 * Perform [enum@Vips.OperationRelational.LESS] on an image and a constant. See
752
 * [method@Image.relational_const].
753
 *
754
 * Returns: 0 on success, -1 on error
755
 */
756
int
757
vips_less_const(VipsImage *in, VipsImage **out, const double *c, int n, ...)
758
0
{
759
0
  va_list ap;
760
0
  int result;
761
762
0
  va_start(ap, n);
763
0
  result = vips_relational_constv(in, out,
764
0
    VIPS_OPERATION_RELATIONAL_LESS, c, n, ap);
765
0
  va_end(ap);
766
767
0
  return result;
768
0
}
769
770
/**
771
 * vips_lesseq_const: (method)
772
 * @in: input [class@Image]
773
 * @out: (out): output [class@Image]
774
 * @c: (array length=n): array of constants
775
 * @n: number of constants in @c
776
 * @...: `NULL`-terminated list of optional named arguments
777
 *
778
 * Perform [enum@Vips.OperationRelational.LESSEQ] on an image and a constant. See
779
 * [method@Image.relational_const].
780
 *
781
 * Returns: 0 on success, -1 on error
782
 */
783
int
784
vips_lesseq_const(VipsImage *in, VipsImage **out, const double *c, int n, ...)
785
0
{
786
0
  va_list ap;
787
0
  int result;
788
789
0
  va_start(ap, n);
790
0
  result = vips_relational_constv(in, out,
791
0
    VIPS_OPERATION_RELATIONAL_LESSEQ, c, n, ap);
792
0
  va_end(ap);
793
794
0
  return result;
795
0
}
796
797
/**
798
 * vips_more_const: (method)
799
 * @in: input [class@Image]
800
 * @out: (out): output [class@Image]
801
 * @c: (array length=n): array of constants
802
 * @n: number of constants in @c
803
 * @...: `NULL`-terminated list of optional named arguments
804
 *
805
 * Perform [enum@Vips.OperationRelational.MORE] on an image and a constant. See
806
 * [method@Image.relational_const].
807
 *
808
 * Returns: 0 on success, -1 on error
809
 */
810
int
811
vips_more_const(VipsImage *in, VipsImage **out, const double *c, int n, ...)
812
0
{
813
0
  va_list ap;
814
0
  int result;
815
816
0
  va_start(ap, n);
817
0
  result = vips_relational_constv(in, out,
818
0
    VIPS_OPERATION_RELATIONAL_MORE, c, n, ap);
819
0
  va_end(ap);
820
821
0
  return result;
822
0
}
823
824
/**
825
 * vips_moreeq_const: (method)
826
 * @in: input [class@Image]
827
 * @out: (out): output [class@Image]
828
 * @c: (array length=n): array of constants
829
 * @n: number of constants in @c
830
 * @...: `NULL`-terminated list of optional named arguments
831
 *
832
 * Perform [enum@Vips.OperationRelational.MOREEQ] on an image and a constant. See
833
 * [method@Image.relational_const].
834
 *
835
 * Returns: 0 on success, -1 on error
836
 */
837
int
838
vips_moreeq_const(VipsImage *in, VipsImage **out, const double *c, int n, ...)
839
0
{
840
0
  va_list ap;
841
0
  int result;
842
843
0
  va_start(ap, n);
844
0
  result = vips_relational_constv(in, out,
845
0
    VIPS_OPERATION_RELATIONAL_MOREEQ, c, n, ap);
846
0
  va_end(ap);
847
848
0
  return result;
849
0
}
850
851
/**
852
 * vips_relational_const1: (method)
853
 * @in: input image
854
 * @out: (out): output image
855
 * @relational: relational operation to perform
856
 * @c: constant
857
 * @...: `NULL`-terminated list of optional named arguments
858
 *
859
 * Perform various relational operations on an image and a constant. See
860
 * [method@Image.relational_const].
861
 *
862
 * ::: seealso
863
 *     [method@Image.boolean], [method@Image.relational].
864
 *
865
 * Returns: 0 on success, -1 on error
866
 */
867
int
868
vips_relational_const1(VipsImage *in, VipsImage **out,
869
  VipsOperationRelational relational, double c, ...)
870
0
{
871
0
  va_list ap;
872
0
  int result;
873
874
0
  va_start(ap, c);
875
0
  result = vips_relational_constv(in, out, relational, &c, 1, ap);
876
0
  va_end(ap);
877
878
0
  return result;
879
0
}
880
881
/**
882
 * vips_equal_const1: (method)
883
 * @in: input image
884
 * @out: (out): output image
885
 * @c: constant
886
 * @...: `NULL`-terminated list of optional named arguments
887
 *
888
 * Perform [enum@Vips.OperationRelational.EQUAL] on an image and a constant. See
889
 * [method@Image.relational_const].
890
 *
891
 * Returns: 0 on success, -1 on error
892
 */
893
int
894
vips_equal_const1(VipsImage *in, VipsImage **out, double c, ...)
895
0
{
896
0
  va_list ap;
897
0
  int result;
898
899
0
  va_start(ap, c);
900
0
  result = vips_relational_constv(in, out,
901
0
    VIPS_OPERATION_RELATIONAL_EQUAL, &c, 1, ap);
902
0
  va_end(ap);
903
904
0
  return result;
905
0
}
906
907
/**
908
 * vips_notequal_const1: (method)
909
 * @in: input image
910
 * @out: (out): output image
911
 * @c: constant
912
 * @...: `NULL`-terminated list of optional named arguments
913
 *
914
 * Perform [enum@Vips.OperationRelational.NOTEQ] on an image and a constant. See
915
 * [method@Image.relational_const].
916
 *
917
 * Returns: 0 on success, -1 on error
918
 */
919
int
920
vips_notequal_const1(VipsImage *in, VipsImage **out, double c, ...)
921
0
{
922
0
  va_list ap;
923
0
  int result;
924
925
0
  va_start(ap, c);
926
0
  result = vips_relational_constv(in, out,
927
0
    VIPS_OPERATION_RELATIONAL_NOTEQ, &c, 1, ap);
928
0
  va_end(ap);
929
930
0
  return result;
931
0
}
932
933
/**
934
 * vips_less_const1: (method)
935
 * @in: input image
936
 * @out: (out): output image
937
 * @c: constant
938
 * @...: `NULL`-terminated list of optional named arguments
939
 *
940
 * Perform [enum@Vips.OperationRelational.LESS] on an image and a constant. See
941
 * [method@Image.relational_const].
942
 *
943
 * Returns: 0 on success, -1 on error
944
 */
945
int
946
vips_less_const1(VipsImage *in, VipsImage **out, double c, ...)
947
0
{
948
0
  va_list ap;
949
0
  int result;
950
951
0
  va_start(ap, c);
952
0
  result = vips_relational_constv(in, out,
953
0
    VIPS_OPERATION_RELATIONAL_LESS, &c, 1, ap);
954
0
  va_end(ap);
955
956
0
  return result;
957
0
}
958
959
/**
960
 * vips_lesseq_const1: (method)
961
 * @in: input image
962
 * @out: (out): output image
963
 * @c: constant
964
 * @...: `NULL`-terminated list of optional named arguments
965
 *
966
 * Perform [enum@Vips.OperationRelational.LESSEQ] on an image and a constant. See
967
 * [method@Image.relational_const].
968
 *
969
 * Returns: 0 on success, -1 on error
970
 */
971
int
972
vips_lesseq_const1(VipsImage *in, VipsImage **out, double c, ...)
973
0
{
974
0
  va_list ap;
975
0
  int result;
976
977
0
  va_start(ap, c);
978
0
  result = vips_relational_constv(in, out,
979
0
    VIPS_OPERATION_RELATIONAL_LESSEQ, &c, 1, ap);
980
0
  va_end(ap);
981
982
0
  return result;
983
0
}
984
985
/**
986
 * vips_more_const1: (method)
987
 * @in: input image
988
 * @out: (out): output image
989
 * @c: constant
990
 * @...: `NULL`-terminated list of optional named arguments
991
 *
992
 * Perform [enum@Vips.OperationRelational.MORE] on an image and a constant. See
993
 * [method@Image.relational_const].
994
 *
995
 * Returns: 0 on success, -1 on error
996
 */
997
int
998
vips_more_const1(VipsImage *in, VipsImage **out, double c, ...)
999
15.1k
{
1000
15.1k
  va_list ap;
1001
15.1k
  int result;
1002
1003
15.1k
  va_start(ap, c);
1004
15.1k
  result = vips_relational_constv(in, out,
1005
15.1k
    VIPS_OPERATION_RELATIONAL_MORE, &c, 1, ap);
1006
15.1k
  va_end(ap);
1007
1008
15.1k
  return result;
1009
15.1k
}
1010
1011
/**
1012
 * vips_moreeq_const1: (method)
1013
 * @in: input image
1014
 * @out: (out): output image
1015
 * @c: constant
1016
 * @...: `NULL`-terminated list of optional named arguments
1017
 *
1018
 * Perform [enum@Vips.OperationRelational.MOREEQ] on an image and a constant. See
1019
 * [method@Image.relational_const].
1020
 *
1021
 * Returns: 0 on success, -1 on error
1022
 */
1023
int
1024
vips_moreeq_const1(VipsImage *in, VipsImage **out, double c, ...)
1025
0
{
1026
0
  va_list ap;
1027
0
  int result;
1028
1029
0
  va_start(ap, c);
1030
0
  result = vips_relational_constv(in, out,
1031
0
    VIPS_OPERATION_RELATIONAL_MOREEQ, &c, 1, ap);
1032
0
  va_end(ap);
1033
1034
0
  return result;
1035
0
}