diff --git a/cplusplus/include/vips/VImage8.h b/cplusplus/include/vips/VImage8.h index d048c66b..d0d8705c 100644 --- a/cplusplus/include/vips/VImage8.h +++ b/cplusplus/include/vips/VImage8.h @@ -1468,6 +1468,35 @@ public: return( math2_const( VIPS_OPERATION_MATH2_WOP, other, options ) ); } + + /** + * Calculate atan2 of each pixel. + */ + VImage + atan2( VImage other, VOption *options = 0 ) const + { + return( math2( other, VIPS_OPERATION_MATH2_ATAN2, options ) ); + } + + /** + * Calculate atan2 of each pixel. + */ + VImage + atan2( double other, VOption *options = 0 ) const + { + return( math2_const( VIPS_OPERATION_MATH2_ATAN2, + to_vector( other ), options ) ); + } + + /** + * Calculate atan2 of each pixel. + */ + VImage + atan2( std::vector other, VOption *options = 0 ) const + { + return( math2_const( VIPS_OPERATION_MATH2_ATAN2, + other, options ) ); + } /** * Use self as a conditional image (not zero meaning TRUE) to pick diff --git a/doc/function-list.xml b/doc/function-list.xml index 47474b4f..c5eace85 100644 --- a/doc/function-list.xml +++ b/doc/function-list.xml @@ -949,7 +949,7 @@ math2 Binary math operations - vips_math2(), vips_pow(), vips_wop() + vips_math2(), vips_pow(), vips_wop(), vips_atan2() math2_const diff --git a/doc/gen-function-list.py b/doc/gen-function-list.py index 5ad30e33..ecfb366a 100644 --- a/doc/gen-function-list.py +++ b/doc/gen-function-list.py @@ -83,7 +83,7 @@ def gen_function_list(): 'extract_area': ['crop'], 'linear': ['linear1'], 'math': ['sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'exp', 'exp10', 'log', 'log10'], - 'math2': ['pow', 'wop'], + 'math2': ['pow', 'wop', 'atan2'], 'rank': ['median'], 'relational': ['equal', 'notequal', 'less', 'lesseq', 'more', 'moreeq'], 'remainder_const': ['remainder_const1'], diff --git a/libvips/arithmetic/math2.c b/libvips/arithmetic/math2.c index dd3e5323..c1022c00 100644 --- a/libvips/arithmetic/math2.c +++ b/libvips/arithmetic/math2.c @@ -146,6 +146,25 @@ vips_math2_build( VipsObject *object ) #define WOP( Y, X, E ) POW( Y, E, X ) + +#ifdef HAVE_ATAN2 +#define ATAN2( Y, L, R ) { \ + double left = (double) (L); \ + double right = (double) (R); \ + \ + (Y) = VIPS_DEG( atan2( left, right ) ); \ + if( (Y) < 0.0 ) \ + (Y) += 360; \ +} +#else +#define ATAN2( Y, L, R ) { \ + double left = (double) (L); \ + double right = (double) (R); \ + \ + (Y) = vips_col_ab2h( left, right ); \ +} +#endif + static void vips_math2_buffer( VipsArithmetic *arithmetic, VipsPel *out, VipsPel **in, int width ) @@ -159,6 +178,7 @@ vips_math2_buffer( VipsArithmetic *arithmetic, switch( math2->math2 ) { case VIPS_OPERATION_MATH2_POW: SWITCH( LOOP, POW ); break; case VIPS_OPERATION_MATH2_WOP: SWITCH( LOOP, WOP ); break; + case VIPS_OPERATION_MATH2_ATAN2: SWITCH( LOOP, ATAN2 ); break; default: g_assert_not_reached(); @@ -320,6 +340,31 @@ vips_wop( VipsImage *left, VipsImage *right, VipsImage **out, ... ) return( result ); } +/** + * vips_atan2: + * @left: left-hand input #VipsImage + * @right: right-hand input #VipsImage + * @out: (out): output #VipsImage + * @...: %NULL-terminated list of optional named arguments + * + * Perform #VIPS_OPERATION_MATH2_ATAN2 on a pair of images. See + * vips_math2(). + * + * Returns: 0 on success, -1 on error + */ +int +vips_atan2( VipsImage *left, VipsImage *right, VipsImage **out, ... ) +{ + va_list ap; + int result; + + va_start( ap, out ); + result = vips_math2v( left, right, out, VIPS_OPERATION_MATH2_ATAN2, ap ); + va_end( ap ); + + return( result ); +} + typedef struct _VipsMath2Const { VipsUnaryConst parent_instance; @@ -380,6 +425,10 @@ vips_math2_const_buffer( VipsArithmetic *arithmetic, SWITCH( LOOPC, WOP ); break; + case VIPS_OPERATION_MATH2_ATAN2: + SWITCH( LOOPC, ATAN2 ); + break; + default: g_assert_not_reached(); break; @@ -536,6 +585,33 @@ vips_wop_const( VipsImage *in, VipsImage **out, const double *c, int n, ... ) return( result ); } +/** + * vips_atan2_const: (method) + * @in: left-hand input #VipsImage + * @out: (out): output #VipsImage + * @c: (array length=n): array of constants + * @n: number of constants in @c + * @...: %NULL-terminated list of optional named arguments + * + * Perform #VIPS_OPERATION_MATH2_ATAN2 on an image and a constant. See + * vips_math2_const(). + * + * Returns: 0 on success, -1 on error + */ +int +vips_atan2_const( VipsImage *in, VipsImage **out, const double *c, int n, ... ) +{ + va_list ap; + int result; + + va_start( ap, n ); + result = vips_math2_constv( in, out, + VIPS_OPERATION_MATH2_ATAN2, c, n, ap ); + va_end( ap ); + + return( result ); +} + /** * vips_math2_const1: (method) * @in: input image @@ -614,3 +690,29 @@ vips_wop_const1( VipsImage *in, VipsImage **out, double c, ... ) return( result ); } + +/** + * vips_atan2_const1: (method) + * @in: left-hand input #VipsImage + * @out: (out): output #VipsImage + * @c: constant + * @...: %NULL-terminated list of optional named arguments + * + * Perform #VIPS_OPERATION_MATH2_ATAN2 on an image and a constant. See + * vips_math2_const(). + * + * Returns: 0 on success, -1 on error + */ +int +vips_atan2_const1( VipsImage *in, VipsImage **out, double c, ... ) +{ + va_list ap; + int result; + + va_start( ap, c ); + result = vips_math2_constv( in, out, + VIPS_OPERATION_MATH2_ATAN2, &c, 1, ap ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/include/vips/arithmetic.h b/libvips/include/vips/arithmetic.h index 3c9c7aa9..41581df9 100644 --- a/libvips/include/vips/arithmetic.h +++ b/libvips/include/vips/arithmetic.h @@ -71,12 +71,14 @@ typedef enum { * VipsOperationMath2: * @VIPS_OPERATION_MATH2_POW: pow( left, right ) * @VIPS_OPERATION_MATH2_WOP: pow( right, left ) + * @VIPS_OPERATION_MATH2_ATAN2: pow( left, right ) * * See also: vips_math(). */ typedef enum { VIPS_OPERATION_MATH2_POW, VIPS_OPERATION_MATH2_WOP, + VIPS_OPERATION_MATH2_ATAN2, VIPS_OPERATION_MATH2_LAST } VipsOperationMath2; @@ -368,6 +370,8 @@ int vips_pow( VipsImage *left, VipsImage *right, VipsImage **out, ... ) __attribute__((sentinel)); int vips_wop( VipsImage *left, VipsImage *right, VipsImage **out, ... ) __attribute__((sentinel)); +int vips_atan2( VipsImage *left, VipsImage *right, VipsImage **out, ... ) + __attribute__((sentinel)); int vips_math2_const( VipsImage *in, VipsImage **out, VipsOperationMath2 math2, const double *c, int n, ... ) __attribute__((sentinel)); @@ -377,6 +381,9 @@ int vips_pow_const( VipsImage *in, VipsImage **out, int vips_wop_const( VipsImage *in, VipsImage **out, const double *c, int n, ... ) __attribute__((sentinel)); +int vips_atan2_const( VipsImage *in, VipsImage **out, + const double *c, int n, ... ) + __attribute__((sentinel)); int vips_math2_const1( VipsImage *in, VipsImage **out, VipsOperationMath2 math2, double c, ... ) __attribute__((sentinel)); @@ -384,6 +391,8 @@ int vips_pow_const1( VipsImage *in, VipsImage **out, double c, ... ) __attribute__((sentinel)); int vips_wop_const1( VipsImage *in, VipsImage **out, double c, ... ) __attribute__((sentinel)); +int vips_atan2_const1( VipsImage *in, VipsImage **out, double c, ... ) + __attribute__((sentinel)); int vips_avg( VipsImage *in, double *out, ... ) __attribute__((sentinel)); diff --git a/libvips/iofuncs/enumtypes.c b/libvips/iofuncs/enumtypes.c index d7fa839d..8852f902 100644 --- a/libvips/iofuncs/enumtypes.c +++ b/libvips/iofuncs/enumtypes.c @@ -40,6 +40,7 @@ vips_operation_math2_get_type( void ) static const GEnumValue values[] = { {VIPS_OPERATION_MATH2_POW, "VIPS_OPERATION_MATH2_POW", "pow"}, {VIPS_OPERATION_MATH2_WOP, "VIPS_OPERATION_MATH2_WOP", "wop"}, + {VIPS_OPERATION_MATH2_ATAN2, "VIPS_OPERATION_MATH2_ATAN2", "atan2"}, {VIPS_OPERATION_MATH2_LAST, "VIPS_OPERATION_MATH2_LAST", "last"}, {0, NULL, NULL} };