Coverage Report

Created: 2025-01-28 06:33

/src/libvips/libvips/arithmetic/math2.c
Line
Count
Source (jump to first uncovered line)
1
/* math2.c --- 2ary math funcs
2
 *
3
 * Copyright: 1990, N. Dessipris
4
 *
5
 * Author: Nicos Dessipris
6
 * Written on: 02/05/1990
7
 * Modified on:
8
 * 10/12/93 JC
9
 *  - now reports total number of x/0, rather than each one.
10
 * 1/2/95 JC
11
 *  - rewritten for PIO with im_wrapone()
12
 *  - incorrect complex code removed
13
 *  - /0 reporting removed for ease of programming
14
 * 15/4/97 JC
15
 *  - return( 0 ) missing, oops!
16
 * 6/7/98 JC
17
 *  - _vec form added
18
 * 30/8/09
19
 *  - gtkdoc
20
 *  - tiny cleanups
21
 * 20/9/09
22
 *  - im_powtra() adapted to make math2.c
23
 * 12/11/11
24
 *  - redone as a class
25
 * 17/7/12
26
 *  - wopconst was broken
27
 * 20/10/21 indus
28
 *  - add atan2
29
 */
30
31
/*
32
33
  Copyright (C) 1991-2005 The National Gallery
34
35
  This library is free software; you can redistribute it and/or
36
  modify it under the terms of the GNU Lesser General Public
37
  License as published by the Free Software Foundation; either
38
  version 2.1 of the License, or (at your option) any later version.
39
40
  This library is distributed in the hope that it will be useful,
41
  but WITHOUT ANY WARRANTY; without even the implied warranty of
42
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
43
  Lesser General Public License for more details.
44
45
  You should have received a copy of the GNU Lesser General Public
46
  License along with this library; if not, write to the Free Software
47
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
48
  02110-1301  USA
49
50
 */
51
52
/*
53
54
  These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
55
56
 */
57
58
/*
59
#define DEBUG
60
 */
61
62
#ifdef HAVE_CONFIG_H
63
#include <config.h>
64
#endif /*HAVE_CONFIG_H*/
65
#include <glib/gi18n-lib.h>
66
67
#include <stdio.h>
68
#include <stdlib.h>
69
#include <math.h>
70
71
#include <vips/vips.h>
72
73
#include "binary.h"
74
#include "unaryconst.h"
75
76
typedef struct _VipsMath2 {
77
  VipsBinary parent_instance;
78
79
  VipsOperationMath2 math2;
80
81
} VipsMath2;
82
83
typedef VipsBinaryClass VipsMath2Class;
84
85
G_DEFINE_TYPE(VipsMath2, vips_math2, VIPS_TYPE_BINARY);
86
87
static int
88
vips_math2_build(VipsObject *object)
89
0
{
90
0
  VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(object);
91
0
  VipsBinary *binary = (VipsBinary *) object;
92
93
0
  if (binary->left &&
94
0
    vips_check_noncomplex(class->nickname, binary->left))
95
0
    return -1;
96
0
  if (binary->right &&
97
0
    vips_check_noncomplex(class->nickname, binary->right))
98
0
    return -1;
99
100
0
  if (VIPS_OBJECT_CLASS(vips_math2_parent_class)->build(object))
101
0
    return -1;
102
103
0
  return 0;
104
0
}
105
106
#define LOOP(IN, OUT, OP) \
107
0
  { \
108
0
    IN *restrict p1 = (IN *) in[0]; \
109
0
    IN *restrict p2 = (IN *) in[1]; \
110
0
    OUT *restrict q = (OUT *) out; \
111
0
\
112
0
    for (x = 0; x < sz; x++) \
113
0
      OP(q[x], p1[x], p2[x]); \
114
0
  }
115
116
#define SWITCH(L, OP) \
117
0
  switch (vips_image_get_format(im)) { \
118
0
  case VIPS_FORMAT_UCHAR: \
119
0
    L(unsigned char, float, OP); \
120
0
    break; \
121
0
  case VIPS_FORMAT_CHAR: \
122
0
    L(signed char, float, OP); \
123
0
    break; \
124
0
  case VIPS_FORMAT_USHORT: \
125
0
    L(unsigned short, float, OP); \
126
0
    break; \
127
0
  case VIPS_FORMAT_SHORT: \
128
0
    L(signed short, float, OP); \
129
0
    break; \
130
0
  case VIPS_FORMAT_UINT: \
131
0
    L(unsigned int, float, OP); \
132
0
    break; \
133
0
  case VIPS_FORMAT_INT: \
134
0
    L(signed int, float, OP); \
135
0
    break; \
136
0
  case VIPS_FORMAT_FLOAT: \
137
0
    L(float, float, OP); \
138
0
    break; \
139
0
  case VIPS_FORMAT_DOUBLE: \
140
0
    L(double, double, OP); \
141
0
    break; \
142
0
\
143
0
  default: \
144
0
    g_assert_not_reached(); \
145
0
  }
146
147
#define POW(Y, X, E) \
148
0
  { \
149
0
    double left = (double) (X); \
150
0
    double right = (double) (E); \
151
0
\
152
0
    /* Special case for **-1 and **0.5, since they are so common. Also \
153
0
     * watch for /0. \
154
0
     */ \
155
0
    (Y) = (left == 0.0) \
156
0
      ? 0.0 \
157
0
      : (right == -1) \
158
0
      ? 1.0 / left \
159
0
      : (right == 0.5) \
160
0
      ? sqrt(left) \
161
0
      : pow(left, right); \
162
0
  }
163
164
0
#define WOP(Y, X, E) POW(Y, E, X)
165
166
#define ATAN2(Y, L, R) \
167
0
  { \
168
0
    double left = (double) (L); \
169
0
    double right = (double) (R); \
170
0
\
171
0
    (Y) = VIPS_DEG(atan2(left, right)); \
172
0
    if ((Y) < 0.0) \
173
0
      (Y) += 360; \
174
0
  }
175
176
static void
177
vips_math2_buffer(VipsArithmetic *arithmetic,
178
  VipsPel *out, VipsPel **in, int width)
179
0
{
180
0
  VipsMath2 *math2 = (VipsMath2 *) arithmetic;
181
0
  VipsImage *im = arithmetic->ready[0];
182
0
  const int sz = width * vips_image_get_bands(im);
183
184
0
  int x;
185
186
0
  switch (math2->math2) {
187
0
  case VIPS_OPERATION_MATH2_POW:
188
0
    SWITCH(LOOP, POW);
189
0
    break;
190
0
  case VIPS_OPERATION_MATH2_WOP:
191
0
    SWITCH(LOOP, WOP);
192
0
    break;
193
0
  case VIPS_OPERATION_MATH2_ATAN2:
194
0
    SWITCH(LOOP, ATAN2);
195
0
    break;
196
197
0
  default:
198
0
    g_assert_not_reached();
199
0
  }
200
0
}
201
202
/* Save a bit of typing.
203
 */
204
#define UC VIPS_FORMAT_UCHAR
205
#define C VIPS_FORMAT_CHAR
206
#define US VIPS_FORMAT_USHORT
207
#define S VIPS_FORMAT_SHORT
208
#define UI VIPS_FORMAT_UINT
209
#define I VIPS_FORMAT_INT
210
#define F VIPS_FORMAT_FLOAT
211
#define X VIPS_FORMAT_COMPLEX
212
#define D VIPS_FORMAT_DOUBLE
213
#define DX VIPS_FORMAT_DPCOMPLEX
214
215
/* Type promotion for math2. Keep in sync with math2_buffer() above.
216
 */
217
static const VipsBandFormat vips_math2_format_table[10] = {
218
  /* Band format:  UC C  US S  UI I  F  X  D  DX */
219
  /* Promotion: */ F, F, F, F, F, F, F, X, D, DX
220
};
221
222
static void
223
vips_math2_class_init(VipsMath2Class *class)
224
1
{
225
1
  GObjectClass *gobject_class = G_OBJECT_CLASS(class);
226
1
  VipsObjectClass *object_class = (VipsObjectClass *) class;
227
1
  VipsArithmeticClass *aclass = VIPS_ARITHMETIC_CLASS(class);
228
229
1
  gobject_class->set_property = vips_object_set_property;
230
1
  gobject_class->get_property = vips_object_get_property;
231
232
1
  object_class->nickname = "math2";
233
1
  object_class->description = _("binary math operations");
234
1
  object_class->build = vips_math2_build;
235
236
1
  aclass->process_line = vips_math2_buffer;
237
238
1
  vips_arithmetic_set_format_table(aclass, vips_math2_format_table);
239
240
1
  VIPS_ARG_ENUM(class, "math2", 200,
241
1
    _("Operation"),
242
1
    _("Math to perform"),
243
1
    VIPS_ARGUMENT_REQUIRED_INPUT,
244
1
    G_STRUCT_OFFSET(VipsMath2, math2),
245
1
    VIPS_TYPE_OPERATION_MATH2, VIPS_OPERATION_MATH2_POW);
246
1
}
247
248
static void
249
vips_math2_init(VipsMath2 *math2)
250
0
{
251
0
}
252
253
static int
254
vips_math2v(VipsImage *left, VipsImage *right, VipsImage **out,
255
  VipsOperationMath2 math2, va_list ap)
256
0
{
257
0
  return vips_call_split("math2", ap, left, right, out, math2);
258
0
}
259
260
/**
261
 * vips_math2:
262
 * @left: left-hand input #VipsImage
263
 * @right: right-hand input #VipsImage
264
 * @out: (out): output #VipsImage
265
 * @math2: math operation to perform
266
 * @...: %NULL-terminated list of optional named arguments
267
 *
268
 * This operation calculates a 2-ary maths operation on a pair of images
269
 * and writes the result to @out. The images may have any
270
 * non-complex format. @out is float except in the case that either of @left
271
 * or @right are double, in which case @out is also double.
272
 *
273
 * It detects division by zero, setting those pixels to zero in the output.
274
 * Beware: it does this silently!
275
 *
276
 * If the images differ in size, the smaller image is enlarged to match the
277
 * larger by adding zero pixels along the bottom and right.
278
 *
279
 * If the number of bands differs, one of the images
280
 * must have one band. In this case, an n-band image is formed from the
281
 * one-band image by joining n copies of the one-band image together, and then
282
 * the two n-band images are operated upon.
283
 *
284
 * The two input images are cast up to the smallest common format (see table
285
 * Smallest common format in
286
 * <link linkend="libvips-arithmetic">arithmetic</link>), and that format is the
287
 * result type.
288
 *
289
 * See also: vips_math2_const().
290
 *
291
 * Returns: 0 on success, -1 on error
292
 */
293
int
294
vips_math2(VipsImage *left, VipsImage *right, VipsImage **out,
295
  VipsOperationMath2 math2, ...)
296
0
{
297
0
  va_list ap;
298
0
  int result;
299
300
0
  va_start(ap, math2);
301
0
  result = vips_math2v(left, right, out, math2, ap);
302
0
  va_end(ap);
303
304
0
  return result;
305
0
}
306
307
/**
308
 * vips_pow:
309
 * @left: left-hand input #VipsImage
310
 * @right: right-hand input #VipsImage
311
 * @out: (out): output #VipsImage
312
 * @...: %NULL-terminated list of optional named arguments
313
 *
314
 * Perform #VIPS_OPERATION_MATH2_POW on a pair of images. See
315
 * vips_math2().
316
 *
317
 * Returns: 0 on success, -1 on error
318
 */
319
int
320
vips_pow(VipsImage *left, VipsImage *right, VipsImage **out, ...)
321
0
{
322
0
  va_list ap;
323
0
  int result;
324
325
0
  va_start(ap, out);
326
0
  result = vips_math2v(left, right, out, VIPS_OPERATION_MATH2_POW, ap);
327
0
  va_end(ap);
328
329
0
  return result;
330
0
}
331
332
/**
333
 * vips_wop:
334
 * @left: left-hand input #VipsImage
335
 * @right: right-hand input #VipsImage
336
 * @out: (out): output #VipsImage
337
 * @...: %NULL-terminated list of optional named arguments
338
 *
339
 * Perform #VIPS_OPERATION_MATH2_WOP on a pair of images. See
340
 * vips_math2().
341
 *
342
 * Returns: 0 on success, -1 on error
343
 */
344
int
345
vips_wop(VipsImage *left, VipsImage *right, VipsImage **out, ...)
346
0
{
347
0
  va_list ap;
348
0
  int result;
349
350
0
  va_start(ap, out);
351
0
  result = vips_math2v(left, right, out, VIPS_OPERATION_MATH2_WOP, ap);
352
0
  va_end(ap);
353
354
0
  return result;
355
0
}
356
357
/**
358
 * vips_atan2:
359
 * @left: left-hand input #VipsImage
360
 * @right: right-hand input #VipsImage
361
 * @out: (out): output #VipsImage
362
 * @...: %NULL-terminated list of optional named arguments
363
 *
364
 * Perform #VIPS_OPERATION_MATH2_ATAN2 on a pair of images. See
365
 * vips_math2().
366
 *
367
 * Returns: 0 on success, -1 on error
368
 */
369
int
370
vips_atan2(VipsImage *left, VipsImage *right, VipsImage **out, ...)
371
0
{
372
0
  va_list ap;
373
0
  int result;
374
375
0
  va_start(ap, out);
376
0
  result = vips_math2v(left, right, out, VIPS_OPERATION_MATH2_ATAN2, ap);
377
0
  va_end(ap);
378
379
0
  return result;
380
0
}
381
382
typedef struct _VipsMath2Const {
383
  VipsUnaryConst parent_instance;
384
385
  VipsOperationMath2 math2;
386
387
} VipsMath2Const;
388
389
typedef VipsUnaryConstClass VipsMath2ConstClass;
390
391
G_DEFINE_TYPE(VipsMath2Const,
392
  vips_math2_const, VIPS_TYPE_UNARY_CONST);
393
394
static int
395
vips_math2_const_build(VipsObject *object)
396
0
{
397
0
  VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(object);
398
0
  VipsUnary *unary = (VipsUnary *) object;
399
400
0
  if (unary->in &&
401
0
    vips_check_noncomplex(class->nickname, unary->in))
402
0
    return -1;
403
404
0
  if (VIPS_OBJECT_CLASS(vips_math2_const_parent_class)->build(object))
405
0
    return -1;
406
407
0
  return 0;
408
0
}
409
410
#define LOOPC(IN, OUT, OP) \
411
0
  { \
412
0
    IN *restrict p = (IN *) in[0]; \
413
0
    OUT *restrict q = (OUT *) out; \
414
0
    double *restrict c = uconst->c_double; \
415
0
\
416
0
    for (i = 0, x = 0; x < width; x++) \
417
0
      for (b = 0; b < bands; b++, i++) \
418
0
        OP(q[i], p[i], c[b]); \
419
0
  }
420
421
static void
422
vips_math2_const_buffer(VipsArithmetic *arithmetic,
423
  VipsPel *out, VipsPel **in, int width)
424
0
{
425
0
  VipsUnaryConst *uconst = (VipsUnaryConst *) arithmetic;
426
0
  VipsMath2Const *math2 = (VipsMath2Const *) arithmetic;
427
0
  VipsImage *im = arithmetic->ready[0];
428
0
  int bands = im->Bands;
429
430
0
  int i, x, b;
431
432
0
  switch (math2->math2) {
433
0
  case VIPS_OPERATION_MATH2_POW:
434
0
    SWITCH(LOOPC, POW);
435
0
    break;
436
437
0
  case VIPS_OPERATION_MATH2_WOP:
438
0
    SWITCH(LOOPC, WOP);
439
0
    break;
440
441
0
  case VIPS_OPERATION_MATH2_ATAN2:
442
0
    SWITCH(LOOPC, ATAN2);
443
0
    break;
444
445
0
  default:
446
0
    g_assert_not_reached();
447
0
    break;
448
0
  }
449
0
}
450
451
static void
452
vips_math2_const_class_init(VipsMath2ConstClass *class)
453
1
{
454
1
  GObjectClass *gobject_class = G_OBJECT_CLASS(class);
455
1
  VipsObjectClass *object_class = (VipsObjectClass *) class;
456
1
  VipsArithmeticClass *aclass = VIPS_ARITHMETIC_CLASS(class);
457
458
1
  gobject_class->set_property = vips_object_set_property;
459
1
  gobject_class->get_property = vips_object_get_property;
460
461
1
  object_class->nickname = "math2_const";
462
1
  object_class->description =
463
1
    _("binary math operations with a constant");
464
1
  object_class->build = vips_math2_const_build;
465
466
1
  aclass->process_line = vips_math2_const_buffer;
467
468
1
  vips_arithmetic_set_format_table(aclass, vips_math2_format_table);
469
470
1
  VIPS_ARG_ENUM(class, "math2", 200,
471
1
    _("Operation"),
472
1
    _("Math to perform"),
473
1
    VIPS_ARGUMENT_REQUIRED_INPUT,
474
1
    G_STRUCT_OFFSET(VipsMath2Const, math2),
475
1
    VIPS_TYPE_OPERATION_MATH2, VIPS_OPERATION_MATH2_POW);
476
1
}
477
478
static void
479
vips_math2_const_init(VipsMath2Const *math2_const)
480
0
{
481
0
}
482
483
static int
484
vips_math2_constv(VipsImage *in, VipsImage **out,
485
  VipsOperationMath2 math2, const double *c, int n, va_list ap)
486
0
{
487
0
  VipsArea *area_c;
488
0
  double *array;
489
0
  int result;
490
0
  int i;
491
492
0
  area_c = vips_area_new_array(G_TYPE_DOUBLE, sizeof(double), n);
493
0
  array = (double *) area_c->data;
494
0
  for (i = 0; i < n; i++)
495
0
    array[i] = c[i];
496
497
0
  result = vips_call_split("math2_const", ap, in, out, math2, area_c);
498
499
0
  vips_area_unref(area_c);
500
501
0
  return result;
502
0
}
503
504
/**
505
 * vips_math2_const: (method)
506
 * @in: input image
507
 * @out: (out): output image
508
 * @math2: math operation to perform
509
 * @c: (array length=n): array of constants
510
 * @n: number of constants in @c
511
 * @...: %NULL-terminated list of optional named arguments
512
 *
513
 * This operation calculates various 2-ary maths operations on an image and
514
 * an array of constants and writes the result to @out.
515
 * The image may have any
516
 * non-complex format. @out is float except in the case that @in
517
 * is double, in which case @out is also double.
518
 *
519
 * It detects division by zero, setting those pixels to zero in the output.
520
 * Beware: it does this silently!
521
 *
522
 * If the array of constants has just one element, that constant is used for
523
 * all image bands. If the array has more than one element and they have
524
 * the same number of elements as there are bands in the image, then
525
 * one array element is used for each band. If the arrays have more than one
526
 * element and the image only has a single band, the result is a many-band
527
 * image where each band corresponds to one array element.
528
 *
529
 * See also: vips_math2(), vips_math().
530
 *
531
 * Returns: 0 on success, -1 on error
532
 */
533
int
534
vips_math2_const(VipsImage *in, VipsImage **out,
535
  VipsOperationMath2 math2, const double *c, int n, ...)
536
0
{
537
0
  va_list ap;
538
0
  int result;
539
540
0
  va_start(ap, n);
541
0
  result = vips_math2_constv(in, out, math2, c, n, ap);
542
0
  va_end(ap);
543
544
0
  return result;
545
0
}
546
547
/**
548
 * vips_pow_const: (method)
549
 * @in: left-hand input #VipsImage
550
 * @out: (out): output #VipsImage
551
 * @c: (array length=n): array of constants
552
 * @n: number of constants in @c
553
 * @...: %NULL-terminated list of optional named arguments
554
 *
555
 * Perform #VIPS_OPERATION_MATH2_POW on an image and a constant. See
556
 * vips_math2_const().
557
 *
558
 * Returns: 0 on success, -1 on error
559
 */
560
int
561
vips_pow_const(VipsImage *in, VipsImage **out, const double *c, int n, ...)
562
0
{
563
0
  va_list ap;
564
0
  int result;
565
566
0
  va_start(ap, n);
567
0
  result = vips_math2_constv(in, out,
568
0
    VIPS_OPERATION_MATH2_POW, c, n, ap);
569
0
  va_end(ap);
570
571
0
  return result;
572
0
}
573
574
/**
575
 * vips_wop_const: (method)
576
 * @in: left-hand input #VipsImage
577
 * @out: (out): output #VipsImage
578
 * @c: (array length=n): array of constants
579
 * @n: number of constants in @c
580
 * @...: %NULL-terminated list of optional named arguments
581
 *
582
 * Perform #VIPS_OPERATION_MATH2_WOP on an image and a constant. See
583
 * vips_math2_const().
584
 *
585
 * Returns: 0 on success, -1 on error
586
 */
587
int
588
vips_wop_const(VipsImage *in, VipsImage **out, const double *c, int n, ...)
589
0
{
590
0
  va_list ap;
591
0
  int result;
592
593
0
  va_start(ap, n);
594
0
  result = vips_math2_constv(in, out,
595
0
    VIPS_OPERATION_MATH2_WOP, c, n, ap);
596
0
  va_end(ap);
597
598
0
  return result;
599
0
}
600
601
/**
602
 * vips_atan2_const: (method)
603
 * @in: left-hand input #VipsImage
604
 * @out: (out): output #VipsImage
605
 * @c: (array length=n): array of constants
606
 * @n: number of constants in @c
607
 * @...: %NULL-terminated list of optional named arguments
608
 *
609
 * Perform #VIPS_OPERATION_MATH2_ATAN2 on an image and a constant. See
610
 * vips_math2_const().
611
 *
612
 * Returns: 0 on success, -1 on error
613
 */
614
int
615
vips_atan2_const(VipsImage *in, VipsImage **out, const double *c, int n, ...)
616
0
{
617
0
  va_list ap;
618
0
  int result;
619
620
0
  va_start(ap, n);
621
0
  result = vips_math2_constv(in, out,
622
0
    VIPS_OPERATION_MATH2_ATAN2, c, n, ap);
623
0
  va_end(ap);
624
625
0
  return result;
626
0
}
627
628
/**
629
 * vips_math2_const1: (method)
630
 * @in: input image
631
 * @out: (out): output image
632
 * @math2: math operation to perform
633
 * @c: constant
634
 * @...: %NULL-terminated list of optional named arguments
635
 *
636
 * This operation calculates various 2-ary maths operations on an image and
637
 * a constant. See vips_math2_const().
638
 *
639
 * Returns: 0 on success, -1 on error
640
 */
641
int
642
vips_math2_const1(VipsImage *in, VipsImage **out,
643
  VipsOperationMath2 math2, double c, ...)
644
0
{
645
0
  va_list ap;
646
0
  int result;
647
648
0
  va_start(ap, c);
649
0
  result = vips_math2_constv(in, out, math2, &c, 1, ap);
650
0
  va_end(ap);
651
652
0
  return result;
653
0
}
654
655
/**
656
 * vips_pow_const1: (method)
657
 * @in: left-hand input #VipsImage
658
 * @out: (out): output #VipsImage
659
 * @c: constant
660
 * @...: %NULL-terminated list of optional named arguments
661
 *
662
 * Perform #VIPS_OPERATION_MATH2_POW on an image and a constant. See
663
 * vips_math2_const().
664
 *
665
 * Returns: 0 on success, -1 on error
666
 */
667
int
668
vips_pow_const1(VipsImage *in, VipsImage **out, double c, ...)
669
0
{
670
0
  va_list ap;
671
0
  int result;
672
673
0
  va_start(ap, c);
674
0
  result = vips_math2_constv(in, out,
675
0
    VIPS_OPERATION_MATH2_POW, &c, 1, ap);
676
0
  va_end(ap);
677
678
0
  return result;
679
0
}
680
681
/**
682
 * vips_wop_const1: (method)
683
 * @in: left-hand input #VipsImage
684
 * @out: (out): output #VipsImage
685
 * @c: constant
686
 * @...: %NULL-terminated list of optional named arguments
687
 *
688
 * Perform #VIPS_OPERATION_MATH2_WOP on an image and a constant. See
689
 * vips_math2_const().
690
 *
691
 * Returns: 0 on success, -1 on error
692
 */
693
int
694
vips_wop_const1(VipsImage *in, VipsImage **out, double c, ...)
695
0
{
696
0
  va_list ap;
697
0
  int result;
698
699
0
  va_start(ap, c);
700
0
  result = vips_math2_constv(in, out,
701
0
    VIPS_OPERATION_MATH2_WOP, &c, 1, ap);
702
0
  va_end(ap);
703
704
0
  return result;
705
0
}
706
707
/**
708
 * vips_atan2_const1: (method)
709
 * @in: left-hand input #VipsImage
710
 * @out: (out): output #VipsImage
711
 * @c: constant
712
 * @...: %NULL-terminated list of optional named arguments
713
 *
714
 * Perform #VIPS_OPERATION_MATH2_ATAN2 on an image and a constant. See
715
 * vips_math2_const().
716
 *
717
 * Returns: 0 on success, -1 on error
718
 */
719
int
720
vips_atan2_const1(VipsImage *in, VipsImage **out, double c, ...)
721
0
{
722
0
  va_list ap;
723
0
  int result;
724
725
0
  va_start(ap, c);
726
0
  result = vips_math2_constv(in, out,
727
0
    VIPS_OPERATION_MATH2_ATAN2, &c, 1, ap);
728
0
  va_end(ap);
729
730
0
  return result;
731
0
}