diff --git a/Makefile.am b/Makefile.am index a870fe50..bfa09060 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,9 +1,9 @@ -# turn off libvipsCC if C++ is disabled +# turn off C++ APIs if C++ is disabled if ENABLE_CXX -C_COMPILE_DIR = libvipsCC +C_COMPILE_DIR = libvipsCC cplusplus C_DIST_DIR = -C_PKGCONFIG = vipsCC.pc +C_PKGCONFIG = vipsCC.pc vips-cc.pc # turn on Python if we can (requires C++) if HAVE_PYTHON @@ -13,7 +13,7 @@ endif else C_COMPILE_DIR = -C_DIST_DIR = libvipsCC +C_DIST_DIR = libvipsCC cplusplus C_PKGCONFIG = P_COMPILE_DIR = P_DIST_DIR = swig @@ -53,6 +53,7 @@ EXTRA_DIST = \ bootstrap.sh \ vips.pc.in \ vipsCC.pc.in \ + vips-cc.pc.in \ libvips.supp \ acinclude.m4 \ depcomp \ diff --git a/configure.ac b/configure.ac index 63483c80..b6eb15a5 100644 --- a/configure.ac +++ b/configure.ac @@ -794,6 +794,7 @@ AC_SUBST(PACKAGES_USED) AC_OUTPUT([ vips.pc vipsCC.pc + vips-cc.pc Makefile libvips/include/vips/version.h libvips/include/Makefile @@ -817,6 +818,9 @@ AC_OUTPUT([ libvipsCC/include/Makefile libvipsCC/include/vips/Makefile libvipsCC/Makefile + cplusplus/include/Makefile + cplusplus/include/vips/Makefile + cplusplus/Makefile tools/Makefile tools/batch_crop tools/batch_image_convert diff --git a/cplusplus/Makefile.am b/cplusplus/Makefile.am index 9ab3717a..08fa22dd 100644 --- a/cplusplus/Makefile.am +++ b/cplusplus/Makefile.am @@ -8,28 +8,28 @@ AM_CPPFLAGS = \ lib_LTLIBRARIES = libvips-cc.la -libvipsCC_la_SOURCES = \ +libvips_cc_la_SOURCES = \ VImage.cc \ VError.cc -libvipsCC_la_LDFLAGS = \ +libvips_cc_la_LDFLAGS = \ -no-undefined \ -version-info @LIBRARY_CURRENT@:@LIBRARY_REVISION@:@LIBRARY_AGE@ -libvipsCC_la_LIBADD = \ +libvips_cc_la_LIBADD = \ $(top_builddir)/libvips/libvips.la @VIPS_LIBS@ # swap the 'awk' line for this: # awk '{if($$1!="deprecated") print $$1}'` ; \ # to not generate the wrappers for deprecated functions -vipsc++.cc: +vips-operators.cc: packages=`vips list packages | \ awk '{print $$1}'` ; \ - echo > vipsc++.cc ; \ + echo > vips-operators.cc ; \ for name in $$packages; do \ - echo "// bodies for package $$name" >> vipsc++.cc ; \ - vips cppc $$name >> vipsc++.cc ; \ - echo >> vipsc++.cc ; \ + echo "// bodies for package $$name" >> vips-operators.cc ; \ + vips cppc $$name >> vips-operators.cc ; \ + echo >> vips-operators.cc ; \ done EXTRA_DIST = vips-operators.cc diff --git a/cplusplus/VError.cc b/cplusplus/VError.cc index 999d51e4..67e67348 100644 --- a/cplusplus/VError.cc +++ b/cplusplus/VError.cc @@ -32,69 +32,21 @@ #endif /*HAVE_CONFIG_H*/ #include -#include -#include - #include -#include - -#include - -#ifdef WITH_DMALLOC -#include -#endif /*WITH_DMALLOC*/ +#include VIPS_NAMESPACE_START -void VError::perror() -{ - std::cerr << _what; - exit( 1 ); +std::ostream &operator<<( std::ostream &file, const VError &err ) +{ + err.ostream_print( file ); + return( file ); } -void VError::perror( const char *name ) -{ - std::cerr << name << ": " << _what; - exit( 1 ); -} - -// Add a new bit to the end of the error buffer -VError &VError::app( const int i ) -{ - char buf[ 256 ]; - - sprintf( buf, "%d", i ); - _what += buf; - - return( *this ); -} - -VError &VError::app( std::string txt ) -{ - _what += txt; - - return( *this ); -}; - void VError::ostream_print( std::ostream &file ) const { file << _what; } -void verror( std::string str ) throw( VError ) -{ - VError err; - - err.app( "VIPS error: " ); - if( str == "" ) { - err.app( im_error_buffer() ); - im_error_clear(); - } - else - err.app( str ).app( "\n" ); - - throw( err ); -} - VIPS_NAMESPACE_END diff --git a/cplusplus/VImage.cc b/cplusplus/VImage.cc index 5893adce..a09971c9 100644 --- a/cplusplus/VImage.cc +++ b/cplusplus/VImage.cc @@ -32,303 +32,221 @@ #endif /*HAVE_CONFIG_H*/ #include -#include -#include -#include +#include -#include #include -#include - -#include "include/vips/vips8" - -#ifdef WITH_DMALLOC -#include -#endif /*WITH_DMALLOC*/ - /* #define DEBUG */ VIPS_NAMESPACE_START -/* Useful to have these as namespaced C++ functions. - */ -void -init( const char *argv0 ) - throw( VError ) +VOption::~VOption() { - if( vips_init( argv0 ) ) - throw VError(); + std::list::iterator i; + + for( i = options.begin(); i != options.end(); i++ ) + delete *i; } -void shutdown() +VOption *VOption::set( const char *name, const char *value ) { - vips_shutdown(); + Pair *pair = new Pair( name ); + + pair->input = true; + g_value_init( &pair->value, G_TYPE_STRING ); + g_value_set_string( &pair->value, value ); + options.push_back( pair ); + + return( this ); } -void thread_shutdown() +VOption *VOption::set( const char *name, int value ) { - vips_thread_shutdown(); + Pair *pair = new Pair( name ); + + pair->input = true; + g_value_init( &pair->value, G_TYPE_INT ); + g_value_set_int( &pair->value, value ); + options.push_back( pair ); + + return( this ); } -static void -call_get( GParamSpec *pspec, void *arg ) +VOption *VOption::set( const char *name, VImage value ) { - /* We've read out of the VipsObject to the pointer. If it's a - * VipsImage, we need to box it. - */ - if( G_IS_PARAM_SPEC_OBJECT( pspec ) ) { - VImage *image = new VImage( *((VipsImage **) arg) ); + Pair *pair = new Pair( name ); - *((VImage *) arg) = *image; - } + pair->input = true; + g_value_init( &pair->value, VIPS_TYPE_IMAGE ); + // we need to unbox + g_value_set_object( &pair->value, value.get_image() ); + options.push_back( pair ); + + return( this ); } -static void -call_set( GParamSpec *pspec, GValue *value ) +VOption *VOption::set( const char *name, VImage *value ) { - if( G_VALUE_HOLDS( value, VIPS_TYPE_IMAGE ) ) { - /* A VImage has been written to the GValue, extract the VImage - * and swap it for the underlying VipsImage* pointer. - */ - VImage *image = static_cast( - g_value_peek_pointer( value ) ); + Pair *pair = new Pair( name ); - g_value_set_object( value, (gpointer) (image->image()) ); - } + // note where we will write the VImage on success + pair->input = false; + pair->vimage = value; + g_value_init( &pair->value, VIPS_TYPE_IMAGE ); + + options.push_back( pair ); + + return( this ); } -/* Some systems do not have va_copy() ... this might work (it does on MSVC, - * apparently). - * - * FIXME ... this should be in configure.in - */ -#ifndef va_copy -#define va_copy(d,s) ((d) = (s)) -#endif - -void -call( const char *operation_name, ... ) - throw( VError ) +// walk the options and set props on the operation +void VOption::set_operation( VipsOperation *operation ) { - VipsCollect collect; - VipsOperation *operation; - int result; - va_list required; - va_list optional; + std::list::iterator i; - if( !(operation = vips_operation_new( operation_name )) ) - throw VError(); + for( i = options.begin(); i != options.end(); i++ ) + if( (*i)->input ) { + 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 ); - /* We have to break the va_list into separate required and optional - * components. - * - * Note the start, grab the required, then copy and reuse. - */ - va_start( required, operation_name ); - - va_copy( optional, required ); - - VIPS_ARGUMENT_FOR_ALL( operation, - pspec, argument_class, argument_instance ) { - - g_assert( argument_instance ); - - if( (argument_class->flags & VIPS_ARGUMENT_REQUIRED) ) { - VIPS_ARGUMENT_COLLECT_SET( pspec, argument_class, - optional ); - - VIPS_ARGUMENT_COLLECT_GET( pspec, argument_class, - optional ); - - VIPS_ARGUMENT_COLLECT_END + g_object_set_property( G_OBJECT( operation ), + (*i)->name, &(*i)->value ); } - } VIPS_ARGUMENT_FOR_ALL_END - - collect.get = call_get; - collect.set = call_set; - result = vips_call_required_optional( &operation, - &collect, required, optional ); - - va_end( required ); - va_end( optional ); - - /* Build failed: junk args. - */ - if( result ) - vips_object_unref_outputs( VIPS_OBJECT( operation ) ); - - /* The operation we have built should now have been reffed by one of - * its arguments or have finished its work. Either way, we can unref. - */ - g_object_unref( operation ); - - if( result ) - throw VError(); } -int -call_split( const char *operation_name, va_list optional, ... ) +// walk the options and do any processing needed for output objects +void VOption::get_operation( VipsOperation *operation ) +{ + std::list::iterator i; + + for( i = options.begin(); i != options.end(); i++ ) + if( not (*i)->input ) { + g_object_get_property( G_OBJECT( operation ), + (*i)->name, &(*i)->value ); + + printf( "get_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 ); + + // rebox object + VipsImage *image = VIPS_IMAGE( + g_value_get_object( &(*i)->value ) ); + if( (*i)->vimage ) + *((*i)->vimage) = VImage( image ); + } +} + +void VImage::call_option_string( const char *operation_name, + const char *option_string, VOption *options ) + throw( VError ) { VipsOperation *operation; - va_list required; - VipsCollect collect; - int result; - if( !(operation = vips_operation_new( operation_name )) ) - throw VError(); + VIPS_DEBUG_MSG( "vips_call_by_name: starting for %s ...\n", + operation_name ); - va_start( required, optional ); + if( !(operation = vips_operation_new( operation_name )) ) { + if( options ) + delete options; + throw( VError() ); + } - collect.get = call_get; - collect.set = call_set; - result = vips_call_required_optional( &operation, - &collect, required, optional ); - - va_end( required ); - - /* Build failed: junk args. + /* Set str options before vargs options, so the user can't + * override things we set deliberately. */ - if( result ) + if( option_string && + vips_object_set_from_string( VIPS_OBJECT( operation ), + option_string ) ) { vips_object_unref_outputs( VIPS_OBJECT( operation ) ); + g_object_unref( operation ); + delete options; + throw( VError() ); + } - /* The operation we have built should now have been reffed by one of - * its arguments or have finished its work. Either way, we can unref. + if( options ) + options->set_operation( operation ); + + /* Build from cache. + */ + if( vips_cache_operation_buildp( &operation ) ) { + vips_object_unref_outputs( VIPS_OBJECT( operation ) ); + delete options; + throw( VError() ); + } + + /* Walk args again, writing output. + */ + if( options ) + options->get_operation( operation ); + + /* We're done with options! + */ + delete options; + + /* The operation we have built should now have been reffed by + * one of its arguments or have finished its work. Either + * way, we can unref. */ g_object_unref( operation ); - - if( result ) - throw VError(); } -// see vips_image_new_from_file() -VImage::VImage( const char *name, ... ) - throw( VError ) +void VImage::call( const char *operation_name, VOption *options ) + throw( VError ) +{ + call_option_string( operation_name, NULL, options ); +} + +VImage VImage::new_from_file( const char *name, VOption *options ) + throw( VError ) { char filename[VIPS_PATH_MAX]; char option_string[VIPS_PATH_MAX]; const char *operation_name; - va_list ap; - int result; + + VImage out; vips__filename_split8( name, filename, option_string ); - if( !(operation_name = vips_foreign_find_load( filename )) ) + if( !(operation_name = vips_foreign_find_load( filename )) ) { + delete options; throw VError(); + } - va_start( ap, name ); - result = vips_call_split_option_string( operation_name, - option_string, ap, filename, &im ); - va_end( ap ); + call_option_string( operation_name, option_string, + (options ? options : VImage::option())-> + set( "filename", filename )-> + set( "out", &out ) ); - if( result ) - throw VError(); + return( out ); } -// see vips_image_new_from_buffer() -VImage::VImage( void *buffer, size_t length, const char *option_string, ... ) - throw( VError ) -{ - const char *operation_name; - VipsBlob *blob; - va_list ap; - int result; - - if( !(operation_name = - vips_foreign_find_load_buffer( buffer, length )) ) - throw VError(); - - /* We don't take a copy of the data or free it. - */ - blob = vips_blob_new( NULL, buffer, length ); - - va_start( ap, option_string ); - result = vips_call_split_option_string( operation_name, - option_string, ap, blob, &im ); - va_end( ap ); - - vips_area_unref( VIPS_AREA( blob ) ); - - if( result ) - throw VError(); -} - -// see vips_image_write_to_file() -void VImage::write_to_file( const char *name, ... ) +void VImage::write_to_file( const char *name, VOption *options ) throw( VError ) { char filename[VIPS_PATH_MAX]; char option_string[VIPS_PATH_MAX]; const char *operation_name; - va_list ap; - int result; vips__filename_split8( name, filename, option_string ); - if( !(operation_name = vips_foreign_find_save( filename )) ) + if( !(operation_name = vips_foreign_find_save( filename )) ) { + delete options; throw VError(); + } - va_start( ap, name ); - result = vips_call_split_option_string( operation_name, option_string, - ap, this->im, filename ); - va_end( ap ); - - if( result ) - throw VError(); + call_option_string( operation_name, option_string, + (options ? options : VImage::option())-> + set( "in", *this )-> + set( "filename", filename ) ); } -// see vips_image_write_to_buffer() -void *VImage::write_to_buffer( const char *suffix, size_t *size, ... ) - throw( VError ) -{ - char filename[VIPS_PATH_MAX]; - char option_string[VIPS_PATH_MAX]; - const char *operation_name; - va_list ap; - VipsBlob *blob; - int result; - void *buf; - - vips__filename_split8( suffix, filename, option_string ); - if( !(operation_name = vips_foreign_find_save_buffer( filename )) ) - throw VError(); - - va_start( ap, size ); - result = vips_call_split_option_string( operation_name, option_string, - ap, this->im, &blob ); - va_end( ap ); - - if( result ) - throw VError(); - - g_assert( blob ); - - buf = VIPS_AREA( blob )->data; - VIPS_AREA( blob )->free_fn = NULL; - if( size ) - *size = VIPS_AREA( blob )->length; - - vips_area_unref( VIPS_AREA( blob ) ); - - return( buf ); -} - - -/* Insert automatically generated wrappers for vips operators. - */ #include "vips-operators.cc" VIPS_NAMESPACE_END - - -int -main( int argc, char **argv ) -{ - vips8::init( argv[0] ); - - vips8::VImage x( "/home/john/pics/k2.jpg", NULL ); - - printf( "width = %d\n", x.width() ); - - return( 0 ); -} diff --git a/cplusplus/examples/a.out b/cplusplus/examples/a.out new file mode 100755 index 00000000..3d0c6cb2 Binary files /dev/null and b/cplusplus/examples/a.out differ diff --git a/cplusplus/examples/invert.cc b/cplusplus/examples/invert.cc new file mode 100644 index 00000000..5eb27b00 --- /dev/null +++ b/cplusplus/examples/invert.cc @@ -0,0 +1,54 @@ +/* + * compile with: + * + * g++ -g -Wall invert.cc `pkg-config vips-cc --cflags --libs` + * + */ + +#include + +using namespace vips8; + +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 ); + } + + + printf( "these should match if VImage is compile-time-only\n" ); + printf( "sizeof( VipsImage *) = %zd\n", sizeof( VipsImage *) ); + printf( "sizeof( VImage ) = %zd\n", sizeof( VImage ) ); + +{ + VImage in = VImage::new_from_file( argv[1] ); + VImage out; + + out = in.invert(); + + out.write_to_file( argv[2] ); +} + + vips_shutdown(); + + return( 0 ); +} diff --git a/cplusplus/include/vips/Makefile.am b/cplusplus/include/vips/Makefile.am index 94eceef4..c14ef992 100644 --- a/cplusplus/include/vips/Makefile.am +++ b/cplusplus/include/vips/Makefile.am @@ -1,6 +1,6 @@ pkginclude_HEADERS = \ - VError.h \ - VImage.h \ + VError8.h \ + VImage8.h \ vips8 \ vips-operators.h diff --git a/cplusplus/include/vips/VError.h b/cplusplus/include/vips/VError8.h similarity index 60% rename from cplusplus/include/vips/VError.h rename to cplusplus/include/vips/VError8.h index 9cfdb41f..0cb7478d 100644 --- a/cplusplus/include/vips/VError.h +++ b/cplusplus/include/vips/VError8.h @@ -27,57 +27,31 @@ */ -#ifndef IM_VERROR_H -#define IM_VERROR_H -/* SWIG includes this file directly rather than going through vipscpp.h ... so - * we have to define these macros here as well. - */ -#ifdef SWIG -#define VIPS_NAMESPACE_START namespace vips { -#define VIPS_NAMESPACE_END } -#endif /*SWIG*/ +#ifndef VIPS_VERROR_H +#define VIPS_VERROR_H -/* Don't include these when parsing for SWIG. - */ -#ifndef SWIG -# include -# include -# include -#endif /*!SWIG*/ +#include +#include +#include + +#include VIPS_NAMESPACE_START -// Error type class VError : public std::exception { std::string _what; public: VError( std::string what ) : _what( what ) {} - VError() {} + VError() : _what( vips_error_buffer() ) {} virtual ~VError() throw() {} - // Print message and exit - void perror( const char * ); - void perror(); - - // Append some more text to the message - VError &app( std::string txt ); - VError &app( const int i ); - // Extract string virtual const char *what() const throw() { return _what.c_str(); } void ostream_print( std::ostream & ) const; }; -inline std::ostream &operator<<( std::ostream &file, const VError &err ) -{ - err.ostream_print( file ); - return( file ); -} - -void verror( std::string str = "" ) throw( VError ); - VIPS_NAMESPACE_END -#endif /*IM_VERROR_H*/ +#endif /*VIPS_VERROR_H*/ diff --git a/cplusplus/include/vips/VImage.h b/cplusplus/include/vips/VImage.h deleted file mode 100644 index f102f454..00000000 --- a/cplusplus/include/vips/VImage.h +++ /dev/null @@ -1,334 +0,0 @@ -// VIPS image wrapper - -/* - - This file is part of VIPS. - - VIPS is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - - */ - -/* - - These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk - - */ - -#ifndef VIPS_VIMAGE_H -#define VIPS_VIMAGE_H - -#include -#include -#include - -#include - -VIPS_NAMESPACE_START - -/* vips_init() and vips_shutdown as namespaced C++ functions. - */ -void init( const char *argv0 = "nothing" ) throw( VError ); -void thread_shutdown( void ); -void shutdown( void ); - -/* VIPS image class. - */ -class VImage { -protected: - VipsImage *im = NULL; // Underlying vips pointer - -public: - VImage() - { - im = NULL; - } - - // ref the VipsImage ... see new_steal() for one that steals the - // caller's ref - VImage( VipsImage *vips_image ) - { - g_assert( !im ); - - im = vips_image; - g_object_ref( im ); - } - - // make a VImage, stealing the caller's ref - VImage new_steal( VipsImage *vips_image ) - { - VImage image; - - g_assert( !image.im ); - - image.im = vips_image; - } - - VImage( const char *filename, const char *mode = "r" ) - throw( VError ) - { - if( !(im = vips_image_new_mode( filename, mode )) ) - throw VError(); - } - - // see vips_image_new_from_file() - VImage( const char *name, ... ) - throw( VError ) __attribute__((sentinel)); - - // see vips_image_new_from_buffer() - VImage( void *buffer, size_t length, const char *option_string, ... ) - throw( VError ) __attribute__((sentinel)); - - // see vips_image_new_from_memory() - VImage( void *data, size_t size, int width, int height, - int bands, VipsBandFormat format ) throw( VError ) - { - if( !(im = vips_image_new_from_memory( data, size, - width, height, bands, format )) ) - throw VError(); - } - - // also do - // vips_image_new_matrix() - // vips_image_new_matrixv() - // vips_image_new_matrix_from_array() - // vips_image_new_from_file_raw:() - // vips_image_new_from_file_RW() - // vips_image_new_memory() - - // Copy constructor - VImage( const VImage &a ) - { - g_assert( !im ); - - im = a.im; - g_object_ref( im ); - } - - // Assignment - delete old ref - VImage &operator=( const VImage &a ) - { - VIPS_UNREF( im ); - im = a.im; - g_object_ref( im ); - } - - // Destructor - ~VImage() throw( VError ) { VIPS_UNREF( im ); } - - // Peek at the underlying VipsImage pointer - VipsImage *image() const { return( im ); } - - // get a pointer to the pixels ... can be very slow! this may render - // the whole image to a memory buffer - void *data() - throw( VError ) - { - if( vips_image_wio_input( im ) ) - throw VError(); - - return( VIPS_IMAGE_ADDR( im, 0, 0 ) ); - } - - // Write this to another VImage, to a file, or to a mem buffer - void write( VImage out ) - throw( VError ) - { - if( vips_image_write( im, out.im ) ) - throw VError(); - } - - void write_to_file( const char *name, ... ) - throw( VError ) - { - if( vips_image_write_to_file( im, name, NULL ) ) - throw VError(); - } - - // see vips_image_write_to_buffer() - void *write_to_buffer( const char *suffix, size_t *size, ... ) - throw( VError ); - - // also need - // vips_image_write_to_memory() - - // Projection functions to get header fields - int width() { return( im->Xsize ); } - int height() { return( im->Ysize ); } - int bands() { return( im->Bands ); } - VipsBandFormat format() { return( im->BandFmt ); } - VipsCoding coding() { return( im->Coding ); } - VipsInterpretation interpretation() { return( im->Type ); } - float xres() { return( im->Xres ); } - float yres() { return( im->Yres ); } - int xoffset() { return( im->Xoffset ); } - int yoffset() { return( im->Yoffset ); } - - // Derived fields - const char *filename() { return( im->filename ); } - const char *hist() { return( vips_image_get_history( im ) ); } - - // metadata - - /* - - // base functionality - void meta_set( const char *field, GValue *value ) throw( VError ); - void meta_get( const char *field, GValue *value_copy ) throw( VError ); - gboolean meta_remove( const char *field ); - GType meta_get_typeof( const char *field ); - - // convenience functions - int meta_get_int( const char *field ) throw( VError ); - double meta_get_double( const char *field ) throw( VError ); - const char *meta_get_string( const char *field ) throw( VError ); - void *meta_get_area( const char *field ) throw( VError ); - void *meta_get_blob( const char *field, size_t *length ) - throw( VError ); - - void meta_set( const char *field, int value ) throw( VError ); - void meta_set( const char *field, double value ) throw( VError ); - void meta_set( const char *field, const char *value ) throw( VError ); - - void meta_set( const char *field, - VCallback free_fn, void *value ) - throw( VError ); - void meta_set( const char *field, - VCallback free_fn, void *value, size_t length ) - throw( VError ); - - // Set header fields - void initdesc( int, int, int, - VipsBandFormat, VipsCoding, VipsInterpretation, - float = 1.0, float = 1.0, int = 0, int = 0 ) throw( VError ); - */ - - /* Insert automatically generated headers. - */ -#include "vips-operators.h" - - /* - - // And some in-line operator equivalences done by hand - friend VImage operator+( VImage a, VImage b ) throw( VError ) - { return( a.add( b ) ); } - friend VImage operator+( double a, VImage b ) throw( VError ) - { return( b.lin( 1.0, a ) ); } - friend VImage operator+( VImage a, double b ) throw( VError ) - { return( a.lin( 1.0, b ) ); } - - friend VImage operator-( VImage a, VImage b ) throw( VError ) - { return( a.subtract( b ) ); } - friend VImage operator-( double a, VImage b ) throw( VError ) - { return( b.lin( -1.0, a ) ); } - friend VImage operator-( VImage a, double b ) throw( VError ) - { return( a.lin( 1.0, -b ) ); } - - friend VImage operator*( VImage a, VImage b ) throw( VError ) - { return( a.multiply( b ) ); } - friend VImage operator*( double a, VImage b ) throw( VError ) - { return( b.lin( a, 0.0 ) ); } - friend VImage operator*( VImage a, double b ) throw( VError ) - { return( a.lin( b, 0.0 ) ); } - - friend VImage operator/( VImage a, VImage b ) throw( VError ) - { return( a.divide( b ) ); } - friend VImage operator/( double a, VImage b ) throw( VError ) - { return( b.pow( -1.0 ).lin( a, 0.0 ) ); } - friend VImage operator/( VImage a, double b ) throw( VError ) - { return( a.lin( 1.0/b, 0.0 ) ); } - - friend VImage operator%( VImage a, VImage b ) throw( VError ) - { return( a.remainder( b ) ); } - friend VImage operator%( VImage a, double b ) throw( VError ) - { return( a.remainder( b ) ); } - - friend VImage operator<( VImage a, VImage b ) throw( VError ) - { return( a.less( b ) ); } - friend VImage operator<( double a, VImage b ) throw( VError ) - { return( b.more( a ) ); } - friend VImage operator<( VImage a, double b ) throw( VError ) - { return( a.less( b ) ); } - - friend VImage operator<=( VImage a, VImage b ) throw( VError ) - { return( a.lesseq( b ) ); } - friend VImage operator<=( double a, VImage b ) throw( VError ) - { return( b.moreeq( a ) ); } - friend VImage operator<=( VImage a, double b ) throw( VError ) - { return( a.lesseq( b ) ); } - - friend VImage operator>( VImage a, VImage b ) throw( VError ) - { return( a.more( b ) ); } - friend VImage operator>( double a, VImage b ) throw( VError ) - { return( b.less( a ) ); } - friend VImage operator>( VImage a, double b ) throw( VError ) - { return( a.more( b ) ); } - - friend VImage operator>=( VImage a, VImage b ) throw( VError ) - { return( a.moreeq( b ) ); } - friend VImage operator>=( double a, VImage b ) throw( VError ) - { return( b.lesseq( a ) ); } - friend VImage operator>=( VImage a, double b ) throw( VError ) - { return( a.moreeq( b ) ); } - - friend VImage operator==( VImage a, VImage b ) throw( VError ) - { return( a.equal( b ) ); } - friend VImage operator==( double a, VImage b ) throw( VError ) - { return( b.equal( a ) ); } - friend VImage operator==( VImage a, double b ) throw( VError ) - { return( a.equal( b ) ); } - - friend VImage operator!=( VImage a, VImage b ) throw( VError ) - { return( a.notequal( b ) ); } - friend VImage operator!=( double a, VImage b ) throw( VError ) - { return( b.notequal( a ) ); } - friend VImage operator!=( VImage a, double b ) throw( VError ) - { return( a.notequal( b ) ); } - - friend VImage operator&( VImage a, VImage b ) throw( VError ) - { return( a.andimage( b ) ); } - friend VImage operator&( int a, VImage b ) throw( VError ) - { return( b.andimage( a ) ); } - friend VImage operator&( VImage a, int b ) throw( VError ) - { return( a.andimage( b ) ); } - - friend VImage operator|( VImage a, VImage b ) throw( VError ) - { return( a.orimage( b ) ); } - friend VImage operator|( int a, VImage b ) throw( VError ) - { return( b.orimage( a ) ); } - friend VImage operator|( VImage a, int b ) throw( VError ) - { return( a.orimage( b ) ); } - - friend VImage operator^( VImage a, VImage b ) throw( VError ) - { return( a.eorimage( b ) ); } - friend VImage operator^( int a, VImage b ) throw( VError ) - { return( b.eorimage( a ) ); } - friend VImage operator^( VImage a, int b ) throw( VError ) - { return( a.eorimage( b ) ); } - - friend VImage operator<<( VImage a, int b ) throw( VError ) - { return( a.shiftleft( b ) ); } - friend VImage operator>>( VImage a, int b ) throw( VError ) - { return( a.shiftright( b ) ); } - - friend VImage operator-( VImage a ) throw( VError ) - { return( a * -1 ); } - */ - -}; - -VIPS_NAMESPACE_END - -#endif /*VIPS_VIMAGE_H*/ diff --git a/cplusplus/include/vips/VImage8.h b/cplusplus/include/vips/VImage8.h new file mode 100644 index 00000000..b839acf8 --- /dev/null +++ b/cplusplus/include/vips/VImage8.h @@ -0,0 +1,236 @@ +// VIPS image wrapper + +/* + + This file is part of VIPS. + + VIPS is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + + */ + +/* + + These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk + + */ + +#ifndef VIPS_VIMAGE_H +#define VIPS_VIMAGE_H + +#include +#include +#include + +#include + +VIPS_NAMESPACE_START + +enum VSteal { + NOSTEAL = 0, + STEAL = 1 +}; + +/* A smart VipsObject pointer class ... use g_object_ref()/_unref() for + * lifetime management. + */ +class VObject +{ +private: + // can be NULL, see eg. VObject() + VipsObject *vobject; + +public: + VObject( VipsObject *new_vobject, VSteal steal = STEAL ) : + vobject( new_vobject ) + { + // we allow NULL init, eg. "VImage a;" + g_assert( !new_vobject || + VIPS_IS_OBJECT( new_vobject ) ); + + printf( "VObject constructor, obj = %p, steal = %d\n", + new_vobject, steal ); + if( new_vobject ) { + printf( " obj " ); + vips_object_print_name( VIPS_OBJECT( new_vobject ) ); + printf( "\n" ); + } + if( !steal ) { + printf( " reffing object\n" ); + g_object_ref( vobject ); + } + } + + VObject() : + vobject( 0 ) + { + } + + // copy constructor + VObject( const VObject &a ) : + vobject( a.vobject ) + { + g_assert( VIPS_IS_OBJECT( a.vobject ) ); + + printf( "VObject copy constructor, obj = %p\n", + vobject ); + g_object_ref( vobject ); + printf( " reffing object\n" ); + } + + // assignment ... we must delete the old ref + // old can be NULL, new must not be NULL + VObject &operator=( const VObject &a ) + { + VipsObject *old_vobject; + + printf( "VObject assignment\n" ); + printf( " reffing %p\n", a.vobject ); + printf( " unreffing %p\n", vobject ); + + g_assert( !vobject || + VIPS_IS_OBJECT( vobject ) ); + g_assert( a.vobject && + VIPS_IS_OBJECT( a.vobject ) ); + + // delete the old ref at the end ... otherwise "a = a;" could + // unref before reffing again + old_vobject = vobject; + vobject = a.vobject; + g_object_ref( vobject ); + if( old_vobject ) + g_object_unref( old_vobject ); + + return( *this ); + } + + // this mustn't be virtual: we want this class to only be a pointer, + // no vtable allowed + ~VObject() + { + printf( "VObject destructor\n" ); + printf( " unreffing %p\n", vobject ); + + g_assert( !vobject || + VIPS_IS_OBJECT( vobject ) ); + + if( vobject ) + g_object_unref( vobject ); + } + + VipsObject *get_object() + { + g_assert( !vobject || + VIPS_IS_OBJECT( vobject ) ); + + return( vobject ); + } + +}; + +class VImage; +class VOption; + +class VOption +{ +private: + struct Pair { + const char *name; + + // the thing we pass to VipsOperation + GValue value; + + // an input or output parameter ... we guess the direction + // from the arg to set() + bool input; + + // we need to box and unbox VImage ... keep a pointer to the + // VImage from C++ here + VImage *vimage; + + Pair( const char *name ) : + name( name ), input( false ), vimage( 0 ) + { + G_VALUE_TYPE( &value ) = 0; + } + + ~Pair() + { + g_value_unset( &value ); + } + }; + + std::list options; + +public: + VOption() + { + } + + virtual ~VOption(); + + VOption *set( const char *name, const char *value ); + VOption *set( const char *name, int value ); + VOption *set( const char *name, VImage value ); + VOption *set( const char *name, VImage *value ); + + void set_operation( VipsOperation *operation ); + void get_operation( VipsOperation *operation ); + +}; + +class VImage : VObject +{ +public: + VImage( VipsImage *image, VSteal steal = STEAL ) : + VObject( (VipsObject *) image, steal ) + { + } + + // an empty (NULL) VImage, eg. "VImage a;" + VImage() : + VObject( 0 ) + { + } + + VipsImage *get_image() + { + return( (VipsImage *) VObject::get_object() ); + } + + static VOption *option() + { + return( new VOption() ); + } + + static void call_option_string( const char *operation_name, + const char *option_string, VOption *options = 0 ) + throw( VError ); + static void call( const char *operation_name, VOption *options = 0 ) + throw( VError ); + + static VImage new_from_file( const char *name, VOption *options = 0 ) + throw( VError ); + + void write_to_file( const char *name, VOption *options = 0 ) + throw( VError ); + +#include "vips-operators.h" + +}; + +VIPS_NAMESPACE_END + +#endif /*VIPS_VIMAGE_H*/ diff --git a/cplusplus/include/vips/vips-operators.h b/cplusplus/include/vips/vips-operators.h index 4cf76864..6f75c822 100644 --- a/cplusplus/include/vips/vips-operators.h +++ b/cplusplus/include/vips/vips-operators.h @@ -1,3 +1 @@ - -VImage add( VImage add_in2, ... ) - throw( VError ) __attribute__((sentinel)); +VImage invert( VOption *options = 0 ) throw( VError ); diff --git a/cplusplus/include/vips/vips8 b/cplusplus/include/vips/vips8 index fa08fd7e..19f5b8f2 100644 --- a/cplusplus/include/vips/vips8 +++ b/cplusplus/include/vips/vips8 @@ -37,7 +37,7 @@ #define VIPS_NAMESPACE_START namespace vips8 { #define VIPS_NAMESPACE_END } -#include "VError.h" -#include "VImage.h" +#include "VError8.h" +#include "VImage8.h" #endif /*VIPS_CPLUSPLUS*/ diff --git a/cplusplus/try92.cc b/cplusplus/old/try92.cc similarity index 100% rename from cplusplus/try92.cc rename to cplusplus/old/try92.cc diff --git a/cplusplus/try93.cc b/cplusplus/old/try93.cc similarity index 100% rename from cplusplus/try93.cc rename to cplusplus/old/try93.cc diff --git a/cplusplus/vips-operators.cc b/cplusplus/vips-operators.cc index 27e360f8..0a644743 100644 --- a/cplusplus/vips-operators.cc +++ b/cplusplus/vips-operators.cc @@ -1,16 +1,14 @@ -VImage VImage::add( VImage in2, ... ) + +VImage VImage::invert( VOption *options ) throw( VError ) { - va_list ap; - VImage out; - int result; + VImage out; - va_start( ap, in2 ); - result = call_split( "add", ap, this, in2, &out ); - va_end( ap ); - - if( result ) - VError(); + call( "invert", + (options ? options : VImage::option())-> + set( "in", *this )-> + set( "out", &out ) ); return( out ); } + diff --git a/vips-cc.pc.in b/vips-cc.pc.in new file mode 100644 index 00000000..b5f7b14b --- /dev/null +++ b/vips-cc.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: vips-cc +Description: C++ API for vips8 image processing library +Version: @VERSION@ +Requires: vips = @VERSION@ +Libs: -L${libdir} -lvips-cc diff --git a/vipsCC.pc.in b/vipsCC.pc.in index 7175c53b..4484778a 100644 --- a/vipsCC.pc.in +++ b/vipsCC.pc.in @@ -4,7 +4,7 @@ libdir=@libdir@ includedir=@includedir@ Name: vipsCC -Description: C++ API for vips image processing library +Description: C++ API for vips7 image processing library Version: @VERSION@ Requires: vips = @VERSION@ Libs: -L${libdir} -lvipsCC