From 8267dd262156d0c5b11612cd7a0534de6688f531 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 5 Nov 2014 14:04:46 +0000 Subject: [PATCH] naming improvements and test_overloads.cpp has started working --- Makefile.am | 4 +- configure.ac | 2 +- cplusplus/Makefile.am | 28 +- cplusplus/{VError.cc => VError.cpp} | 0 cplusplus/{VImage.cc => VImage.cpp} | 14 +- cplusplus/examples/{avg.cc => avg.cpp} | 2 +- cplusplus/examples/{embed.cc => embed.cpp} | 2 +- cplusplus/examples/{invert.cc => invert.cpp} | 2 +- cplusplus/examples/test_overloads.cc | 76 ----- cplusplus/examples/test_overloads.cpp | 266 ++++++++++++++++++ cplusplus/examples/{try.cc => try.cpp} | 2 +- cplusplus/include/vips/VImage8.h | 20 +- .../{vips-operators.cc => vips-operators.cpp} | 0 vips-cc.pc.in => vips-cpp.pc.in | 4 +- 14 files changed, 306 insertions(+), 116 deletions(-) rename cplusplus/{VError.cc => VError.cpp} (100%) rename cplusplus/{VImage.cc => VImage.cpp} (98%) rename cplusplus/examples/{avg.cc => avg.cpp} (93%) rename cplusplus/examples/{embed.cc => embed.cpp} (93%) rename cplusplus/examples/{invert.cc => invert.cpp} (94%) delete mode 100644 cplusplus/examples/test_overloads.cc create mode 100644 cplusplus/examples/test_overloads.cpp rename cplusplus/examples/{try.cc => try.cpp} (96%) rename cplusplus/{vips-operators.cc => vips-operators.cpp} (100%) rename vips-cc.pc.in => vips-cpp.pc.in (80%) diff --git a/Makefile.am b/Makefile.am index bfa09060..a173ba1e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,7 +3,7 @@ if ENABLE_CXX C_COMPILE_DIR = libvipsCC cplusplus C_DIST_DIR = -C_PKGCONFIG = vipsCC.pc vips-cc.pc +C_PKGCONFIG = vipsCC.pc vips-cpp.pc # turn on Python if we can (requires C++) if HAVE_PYTHON @@ -53,7 +53,7 @@ EXTRA_DIST = \ bootstrap.sh \ vips.pc.in \ vipsCC.pc.in \ - vips-cc.pc.in \ + vips-cpp.pc.in \ libvips.supp \ acinclude.m4 \ depcomp \ diff --git a/configure.ac b/configure.ac index 994795f2..049ad5bd 100644 --- a/configure.ac +++ b/configure.ac @@ -794,7 +794,7 @@ AC_SUBST(PACKAGES_USED) AC_OUTPUT([ vips.pc vipsCC.pc - vips-cc.pc + vips-cpp.pc Makefile libvips/include/vips/version.h libvips/include/Makefile diff --git a/cplusplus/Makefile.am b/cplusplus/Makefile.am index ce8a30d1..d6697e10 100644 --- a/cplusplus/Makefile.am +++ b/cplusplus/Makefile.am @@ -6,28 +6,28 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/cplusplus/include \ @VIPS_CFLAGS@ -lib_LTLIBRARIES = libvips-cc.la +lib_LTLIBRARIES = libvips-cpp.la -libvips_cc_la_SOURCES = \ - VImage.cc \ - VError.cc +libvips_cpp_la_SOURCES = \ + VImage.cpp \ + VError.cpp -libvips_cc_la_LDFLAGS = \ +libvips_cpp_la_LDFLAGS = \ -no-undefined \ -version-info @LIBRARY_CURRENT@:@LIBRARY_REVISION@:@LIBRARY_AGE@ -libvips_cc_la_LIBADD = \ +libvips_cpp_la_LIBADD = \ $(top_builddir)/libvips/libvips.la @VIPS_LIBS@ -vips-operators.cc: - echo "// bodies for vips operations" > vips-operators.cc; \ - echo -n "// " >> vips-operators.cc; \ - date >> vips-operators.cc; \ - echo "// this file is generated automatically, do not edit!" >> vips-operators.cc; \ - echo "" >> vips-operators.cc; \ - ./gen-operators.py >> vips-operators.cc +vips-operators.cpp: + echo "// bodies for vips operations" > vips-operators.cpp; \ + echo -n "// " >> vips-operators.cpp; \ + date >> vips-operators.cpp; \ + echo "// this file is generated automatically, do not edit!" >> vips-operators.cpp; \ + echo "" >> vips-operators.cpp; \ + ./gen-operators.py >> vips-operators.cpp EXTRA_DIST = \ README.txt \ - vips-operators.cc \ + vips-operators.cpp \ gen-operators.py diff --git a/cplusplus/VError.cc b/cplusplus/VError.cpp similarity index 100% rename from cplusplus/VError.cc rename to cplusplus/VError.cpp diff --git a/cplusplus/VImage.cc b/cplusplus/VImage.cpp similarity index 98% rename from cplusplus/VImage.cc rename to cplusplus/VImage.cpp index 0479060f..8e70f1bc 100644 --- a/cplusplus/VImage.cc +++ b/cplusplus/VImage.cpp @@ -37,9 +37,9 @@ #include /* - */ #define VIPS_DEBUG -#define DEBUG +#define VIPS_DEBUG_VERBOSE + */ VIPS_NAMESPACE_START @@ -335,13 +335,13 @@ VOption::set_operation( VipsOperation *operation ) for( i = options.begin(); i != options.end(); i++ ) if( (*i)->input ) { -#ifdef DEBUG +#ifdef VIPS_DEBUG_VERBOSE printf( "set_operation: " ); vips_object_print_name( VIPS_OBJECT( operation ) ); char *str_value = g_strdup_value_contents( &(*i)->value ); printf( ".%s = %s\n", (*i)->name, str_value ); g_free( str_value ); -#endif /*DEBUG*/ +#endif /*VIPS_DEBUG_VERBOSE*/ g_object_set_property( G_OBJECT( operation ), (*i)->name, &(*i)->value ); @@ -361,14 +361,14 @@ VOption::get_operation( VipsOperation *operation ) g_object_get_property( G_OBJECT( operation ), name, &(*i)->value ); -#ifdef DEBUG +#ifdef VIPS_DEBUG_VERBOSE printf( "get_operation: " ); vips_object_print_name( VIPS_OBJECT( operation ) ); char *str_value = g_strdup_value_contents( &(*i)->value ); printf( ".%s = %s\n", name, str_value ); g_free( str_value ); -#endif /*DEBUG*/ +#endif /*VIPS_DEBUG_VERBOSE*/ GValue *value = &(*i)->value; GType type = G_VALUE_TYPE( value ); @@ -623,7 +623,7 @@ VImage::write_to_buffer( const char *suffix, void **buf, size_t *size, } } -#include "vips-operators.cc" +#include "vips-operators.cpp" std::vector VImage::bandsplit( VOption *options ) diff --git a/cplusplus/examples/avg.cc b/cplusplus/examples/avg.cpp similarity index 93% rename from cplusplus/examples/avg.cc rename to cplusplus/examples/avg.cpp index 152c1268..3cd7cae7 100644 --- a/cplusplus/examples/avg.cc +++ b/cplusplus/examples/avg.cpp @@ -1,7 +1,7 @@ /* * compile with: * - * g++ -g -Wall avg.cc `pkg-config vips-cc --cflags --libs` + * g++ -g -Wall avg.cc `pkg-config vips-cpp --cflags --libs` * */ diff --git a/cplusplus/examples/embed.cc b/cplusplus/examples/embed.cpp similarity index 93% rename from cplusplus/examples/embed.cc rename to cplusplus/examples/embed.cpp index 4d93f0d2..7ca724ab 100644 --- a/cplusplus/examples/embed.cc +++ b/cplusplus/examples/embed.cpp @@ -1,7 +1,7 @@ /* * compile with: * - * g++ -g -Wall embed.cc `pkg-config vips-cc --cflags --libs` + * g++ -g -Wall embed.cc `pkg-config vips-cpp --cflags --libs` * */ diff --git a/cplusplus/examples/invert.cc b/cplusplus/examples/invert.cpp similarity index 94% rename from cplusplus/examples/invert.cc rename to cplusplus/examples/invert.cpp index 2ccb984d..361abf1b 100644 --- a/cplusplus/examples/invert.cc +++ b/cplusplus/examples/invert.cpp @@ -1,7 +1,7 @@ /* * compile with: * - * g++ -g -Wall invert.cc `pkg-config vips-cc --cflags --libs` + * g++ -g -Wall invert.cc `pkg-config vips-cpp --cflags --libs` * */ diff --git a/cplusplus/examples/test_overloads.cc b/cplusplus/examples/test_overloads.cc deleted file mode 100644 index 357a53c2..00000000 --- a/cplusplus/examples/test_overloads.cc +++ /dev/null @@ -1,76 +0,0 @@ -/* - * compile with: - * - * g++ -g -Wall try.cc `pkg-config vips-cc --cflags --libs` - * - */ - -#define DEBUG - -#include - -using namespace vips8; - -template -C test_add( T left, T right ) -{ - return( left + right ); -} - -std::vector -get_pixel( VImage x, int x, int y ) -{ - VImage pixel = x.extract_area( x, y, 1, 1 ); - std::vector split = pixel.bandsplit() - std::vector values( split.bands() ); - - for( int i = 0; i < split.bands(); i++ ) - values[i] = split.avg(); - - return( values ); -} - -void -test_binary -{ - -} - -int -main( int argc, char **argv ) -{ - GOptionContext *context; - GOptionGroup *main_group; - GError *error = NULL; - - if( vips_init( argv[0] ) ) - vips_error_exit( NULL ); - - context = g_option_context_new( "" ); - - main_group = g_option_group_new( NULL, NULL, NULL, NULL, NULL ); - g_option_context_set_main_group( context, main_group ); - g_option_context_add_group( context, vips_get_option_group() ); - - if( !g_option_context_parse( context, &argc, &argv, &error ) ) { - if( error ) { - fprintf( stderr, "%s\n", error->message ); - g_error_free( error ); - } - - vips_error_exit( NULL ); - } - - -{ - VImage in = VImage::new_from_file( argv[1], - VImage::option()->set( "access", VIPS_ACCESS_SEQUENTIAL_UNBUFFERED ) ); - double avg; - - avg = in.avg(); - - printf( "avg = %g\n", avg ); -} - - return( 0 ); -} diff --git a/cplusplus/examples/test_overloads.cpp b/cplusplus/examples/test_overloads.cpp new file mode 100644 index 00000000..4d067a3e --- /dev/null +++ b/cplusplus/examples/test_overloads.cpp @@ -0,0 +1,266 @@ +/* + * compile with: + * + * g++ -g -Wall test_overloads.cpp `pkg-config vips-cpp --cflags --libs` + * + */ + +/* +#define VIPS_DEBUG +#define VIPS_DEBUG_VERBOSE + */ + +#include + +#include + +using namespace vips; + +bool +equal_vector( std::vector a, std::vector b ) +{ + for( unsigned int i = 0; i < a.size(); i++ ) + if( fabs( a[i] - b[i] ) > 0.001 ) { + printf( "vectors differ at %d: should be [", i ); + for( unsigned int i = 0; i < a.size(); i++ ) { + if( i > 0 ) + printf( ", " ); + printf( "%g", a[i] ); + } + printf( "], is [" ); + for( unsigned int i = 0; i < a.size(); i++ ) { + if( i > 0 ) + printf( ", " ); + printf( "%g", a[i] ); + } + printf( "]\n" ); + + return( false ); + } + + return( true ); +} + +bool +equal_double( double a, double b ) +{ + if( fabs( a - b ) > 0.001 ) { + printf( "doubles differ: should be %g, is %g\n", a, b ); + return( false ); + } + + return( true ); +} + +/* We can't do this with a template, I think we'd need partially-parameterised + * template, which is C++11 only. + */ + +/* Only test a few points and only test uchar: we are just testing the C++ + * overloads, we rely on the python test suite for testing the underlying + * vips operators. + */ +#define TEST_BINARY( OPERATOR ) \ +void \ +test_binary_##OPERATOR( VImage left, VImage right ) \ +{ \ + for( int x = 10; x < 30; x += 10 ) { \ + std::vector p_left = left.getpoint( x, x ); \ + std::vector p_right = right.getpoint( x, x ); \ + std::vector p_result = \ + OPERATOR, \ + std::vector, \ + std::vector >(p_left, p_right ); \ + \ + VImage im_result; \ + std::vector p_im_result; \ + \ + /* test: image = image OP image \ + */ \ + im_result = OPERATOR( left, right ); \ + p_im_result = im_result.getpoint( x, x ); \ + \ + if( !equal_vector( p_result, p_im_result ) ) { \ + printf( #OPERATOR \ + "(VImage, VImage) failed at (%d, %d)\n", \ + x, x ); \ + abort(); \ + } \ + \ + /* test: image = image OP vec \ + */ \ + im_result = \ + OPERATOR >( left, p_right );\ + p_im_result = im_result.getpoint( x, x ); \ + \ + if( !equal_vector( p_result, p_im_result ) ) { \ + printf( #OPERATOR \ + "(VImage, vector) failed at (%d, %d)\n", \ + x, x ); \ + abort(); \ + } \ + \ + /* test: image = vec OP image \ + */ \ + im_result = \ + OPERATOR, \ + VImage>( p_left, right ); \ + p_im_result = im_result.getpoint( x, x ); \ + \ + if( !equal_vector( p_result, p_im_result ) ) { \ + printf( #OPERATOR \ + "(vector, VImage) failed at (%d, %d)\n", \ + x, x ); \ + abort(); \ + } \ + \ + /* test: image = image OP double \ + */ \ + for( unsigned int i = 0; i < p_right.size(); i++ ) { \ + im_result = \ + OPERATOR( left, p_right[i] ); \ + p_im_result = im_result.getpoint( x, x ); \ + \ + if( !equal_double( p_result[i], p_im_result[i] ) ) { \ + printf( #OPERATOR \ + "(VImage, double) failed at " \ + "(%d, %d)\n", \ + x, x ); \ + abort(); \ + } \ + } \ + \ + /* test: image = double OP image \ + */ \ + for( unsigned int i = 0; i < p_left.size(); i++ ) { \ + im_result = \ + OPERATOR( p_left[i], right ); \ + p_im_result = im_result.getpoint( x, x ); \ + \ + if( !equal_double( p_result[i], p_im_result[i] ) ) { \ + printf( #OPERATOR \ + "(double, VImage) failed at " \ + "(%d, %d)\n", \ + x, x ); \ + abort(); \ + } \ + } \ + } \ +} + +// eg. double = double + double +// or image = double + image +template +A test_add( B left, C right ) +{ + return( left + right ); +} + +template +std::vector operator+(std::vector &v1, const std::vector &v2) +{ + std::vector result( v1.size() ); + + for( unsigned int i = 0; i < v1.size(); i++ ) + result[i] = v1[i] + v2[i]; + + return( result ); +} + +TEST_BINARY( test_add ); + +template +A test_subtract( B left, C right ) +{ + return( left - right ); +} + +template +std::vector operator-(std::vector &v1, const std::vector &v2) +{ + std::vector result( v1.size() ); + + for( unsigned int i = 0; i < v1.size(); i++ ) + result[i] = v1[i] - v2[i]; + + return( result ); +} + +TEST_BINARY( test_subtract ); + +template +A test_multiply( B left, C right ) +{ + return( left * right ); +} + +template +std::vector operator*(std::vector &v1, const std::vector &v2) +{ + std::vector result( v1.size() ); + + for( unsigned int i = 0; i < v1.size(); i++ ) + result[i] = v1[i] * v2[i]; + + return( result ); +} + +TEST_BINARY( test_multiply ); + +template +A test_divide( B left, C right ) +{ + return( left / right ); +} + +template +std::vector operator/(std::vector &v1, const std::vector &v2) +{ + std::vector result( v1.size() ); + + for( unsigned int i = 0; i < v1.size(); i++ ) + result[i] = v1[i] / v2[i]; + + return( result ); +} + +TEST_BINARY( test_divide ); + +int +main( int argc, char **argv ) +{ + GOptionContext *context; + GOptionGroup *main_group; + GError *error = NULL; + + if( vips_init( argv[0] ) ) + vips_error_exit( NULL ); + + context = g_option_context_new( "" ); + + main_group = g_option_group_new( NULL, NULL, NULL, NULL, NULL ); + g_option_context_set_main_group( context, main_group ); + g_option_context_add_group( context, vips_get_option_group() ); + + if( !g_option_context_parse( context, &argc, &argv, &error ) ) { + if( error ) { + fprintf( stderr, "%s\n", error->message ); + g_error_free( error ); + } + + vips_error_exit( NULL ); + } + + VImage left = VImage::new_from_file( argv[1] ); + VImage right = VImage::new_from_file( argv[2] ); + + test_binary_test_add( left, right ); + test_binary_test_subtract( left, right ); + test_binary_test_multiply( left, right ); + test_binary_test_divide( left, right ); + + return( 0 ); +} diff --git a/cplusplus/examples/try.cc b/cplusplus/examples/try.cpp similarity index 96% rename from cplusplus/examples/try.cc rename to cplusplus/examples/try.cpp index 78ee40cb..c7c77049 100644 --- a/cplusplus/examples/try.cc +++ b/cplusplus/examples/try.cpp @@ -1,7 +1,7 @@ /* * compile with: * - * g++ -g -Wall try.cc `pkg-config vips-cc --cflags --libs` + * g++ -g -Wall try.cc `pkg-config vips-cpp --cflags --libs` * */ diff --git a/cplusplus/include/vips/VImage8.h b/cplusplus/include/vips/VImage8.h index 31e2e7de..2bf870de 100644 --- a/cplusplus/include/vips/VImage8.h +++ b/cplusplus/include/vips/VImage8.h @@ -71,7 +71,7 @@ public: g_assert( !new_vobject || VIPS_IS_OBJECT( new_vobject ) ); -#ifdef DEBUG +#ifdef VIPS_DEBUG_VERBOSE printf( "VObject constructor, obj = %p, steal = %d\n", new_vobject, steal ); if( new_vobject ) { @@ -79,12 +79,12 @@ public: vips_object_print_name( VIPS_OBJECT( new_vobject ) ); printf( "\n" ); } -#endif /*DEBUG*/ +#endif /*VIPS_DEBUG_VERBOSE*/ if( !steal ) { -#ifdef DEBUG +#ifdef VIPS_DEBUG_VERBOSE printf( " reffing object\n" ); -#endif /*DEBUG*/ +#endif /*VIPS_DEBUG_VERBOSE*/ g_object_ref( vobject ); } } @@ -100,11 +100,11 @@ public: { g_assert( VIPS_IS_OBJECT( a.vobject ) ); -#ifdef DEBUG +#ifdef VIPS_DEBUG_VERBOSE printf( "VObject copy constructor, obj = %p\n", vobject ); printf( " reffing object\n" ); -#endif /*DEBUG*/ +#endif /*VIPS_DEBUG_VERBOSE*/ g_object_ref( vobject ); } @@ -114,11 +114,11 @@ public: { VipsObject *old_vobject; -#ifdef DEBUG +#ifdef VIPS_DEBUG_VERBOSE printf( "VObject assignment\n" ); printf( " reffing %p\n", a.vobject ); printf( " unreffing %p\n", vobject ); -#endif /*DEBUG*/ +#endif /*VIPS_DEBUG_VERBOSE*/ g_assert( !vobject || VIPS_IS_OBJECT( vobject ) ); @@ -140,10 +140,10 @@ public: // no vtable allowed ~VObject() { -#ifdef DEBUG +#ifdef VIPS_DEBUG_VERBOSE printf( "VObject destructor\n" ); printf( " unreffing %p\n", vobject ); -#endif /*DEBUG*/ +#endif /*VIPS_DEBUG_VERBOSE*/ g_assert( !vobject || VIPS_IS_OBJECT( vobject ) ); diff --git a/cplusplus/vips-operators.cc b/cplusplus/vips-operators.cpp similarity index 100% rename from cplusplus/vips-operators.cc rename to cplusplus/vips-operators.cpp diff --git a/vips-cc.pc.in b/vips-cpp.pc.in similarity index 80% rename from vips-cc.pc.in rename to vips-cpp.pc.in index b5f7b14b..5df9baf2 100644 --- a/vips-cc.pc.in +++ b/vips-cpp.pc.in @@ -3,8 +3,8 @@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ -Name: vips-cc +Name: vips-cpp Description: C++ API for vips8 image processing library Version: @VERSION@ Requires: vips = @VERSION@ -Libs: -L${libdir} -lvips-cc +Libs: -L${libdir} -lvips-cpp