// 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 /* Small utility things. */ std::vector to_vectorv( int n, ... ); std::vector to_vector( double value ); std::vector to_vector( int n, double array[] ); std::vector negate( std::vector value ); std::vector invert( std::vector value ); 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 ) ); #ifdef DEBUG 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" ); } #endif /*DEBUG*/ if( !steal ) { #ifdef DEBUG printf( " reffing object\n" ); #endif /*DEBUG*/ g_object_ref( vobject ); } } VObject() : vobject( 0 ) { } // copy constructor VObject( const VObject &a ) : vobject( a.vobject ) { g_assert( VIPS_IS_OBJECT( a.vobject ) ); #ifdef DEBUG printf( "VObject copy constructor, obj = %p\n", vobject ); printf( " reffing object\n" ); #endif /*DEBUG*/ g_object_ref( vobject ); } // assignment ... we must delete the old ref // old can be NULL, new must not be NULL VObject &operator=( const VObject &a ) { VipsObject *old_vobject; #ifdef DEBUG printf( "VObject assignment\n" ); printf( " reffing %p\n", a.vobject ); printf( " unreffing %p\n", vobject ); #endif /*DEBUG*/ 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() { #ifdef DEBUG printf( "VObject destructor\n" ); printf( " unreffing %p\n", vobject ); #endif /*DEBUG*/ 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; union { // we need to box and unbox VImage ... keep a pointer // to the VImage from C++ here VImage *vimage; // output double double *vdouble; // output int int *vint; // output doublearray std::vector *vvector; // output Blob VipsBlob **vblob; // output bool bool *vbool; }; 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, bool value ); VOption *set( const char *name, int value ); VOption *set( const char *name, double value ); VOption *set( const char *name, const char *value ); VOption *set( const char *name, VImage value ); VOption *set( const char *name, std::vector value ); VOption *set( const char *name, std::vector value ); VOption *set( const char *name, VipsBlob *value ); VOption *set( const char *name, bool *value ); VOption *set( const char *name, int *value ); VOption *set( const char *name, double *value ); VOption *set( const char *name, VImage *value ); VOption *set( const char *name, std::vector *value ); VOption *set( const char *name, VipsBlob **blob ); 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() ); } int width() { return( vips_image_get_width( get_image() ) ); } int height() { return( vips_image_get_height( get_image() ) ); } int bands() { return( vips_image_get_bands( get_image() ) ); } VipsBandFormat format() { return( vips_image_get_format( get_image() ) ); } VipsCoding coding() { return( vips_image_get_coding( get_image() ) ); } VipsInterpretation interpretation() { return( vips_image_get_interpretation( get_image() ) ); } VipsInterpretation guess_interpretation() { return( vips_image_guess_interpretation( get_image() ) ); } double xres() { return( vips_image_get_xres( get_image() ) ); } double yres() { return( vips_image_get_yres( get_image() ) ); } double xoffset() { return( vips_image_get_xoffset( get_image() ) ); } double yoffset() { return( vips_image_get_yoffset( get_image() ) ); } const char * filename() { return( vips_image_get_filename( get_image() ) ); } double scale() { return( vips_image_get_scale( get_image() ) ); } double offset() { return( vips_image_get_offset( get_image() ) ); } const void * data() { return( vips_image_get_data( get_image() ) ); } void set( const char *field, int value ) { vips_image_set_int( this->get_image(), field, value ); } void set( const char *field, double value ) { vips_image_set_double( this->get_image(), field, value ); } void set( const char *field, const char *value ) { vips_image_set_string( this->get_image(), field, value ); } void set( const char *field, VipsCallbackFn free_fn, void *data, size_t length ) { vips_image_set_blob( this->get_image(), field, free_fn, data, length ); } int get_typeof( const char *field ) { return( vips_image_get_typeof( this->get_image(), field ) ); } int get_int( const char *field ) throw( VError ) { int value; if( vips_image_get_int( this->get_image(), field, &value ) ) throw( VError() ); return( value ); } double get_double( const char *field ) throw( VError ) { double value; if( vips_image_get_double( this->get_image(), field, &value ) ) throw( VError() ); return( value ); } const char * get_string( const char *field ) throw( VError ) { const char *value; if( vips_image_get_string( this->get_image(), field, &value ) ) throw( VError() ); return( value ); } const void * get_blob( const char *field, size_t *length ) { void *value; if( vips_image_get_blob( this->get_image(), field, &value, length ) ) throw( VError() ); return( value ); } 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 ); VImage new_from_image( std::vector pixel ) throw( VError ); VImage new_from_image( double pixel ) throw( VError ); VImage new_matrix( int width, int height ) ; VImage new_matrixv( int width, int height, ... ); void write_to_file( const char *name, VOption *options = 0 ) throw( VError ); #include "vips-operators.h" // a few useful things VImage linear( double a, double b, VOption *options = 0 ) throw( VError ) { return( this->linear( to_vector( a ), to_vector( b ), options ) ); } VImage linear( std::vector a, double b, VOption *options = 0 ) throw( VError ) { return( this->linear( a, to_vector( b ), options ) ); } VImage linear( double a, std::vector b, VOption *options = 0 ) throw( VError ) { return( this->linear( to_vector( a ), b, options ) ); } std::vector bandsplit( VOption *options = 0 ) throw( VError ); VImage bandjoin( VImage other, VOption *options = 0 ) throw( VError ); VImage bandjoin( double other, VOption *options = 0 ) throw( VError ) { return( bandjoin( this->new_from_image( other ), options ) ); } VImage bandjoin( std::vector other, VOption *options = 0 ) throw( VError ) { return( bandjoin( this->new_from_image( other ), options ) ); } std::complex minpos( VOption *options = 0 ) throw( VError ); std::complex maxpos( VOption *options = 0 ) throw( VError ); VImage floor( VOption *options = 0 ) throw( VError ) { return( round( VIPS_OPERATION_ROUND_FLOOR, options ) ); } VImage ceil( VOption *options = 0 ) throw( VError ) { return( round( VIPS_OPERATION_ROUND_CEIL, options ) ); } VImage rint( VOption *options = 0 ) throw( VError ) { return( round( VIPS_OPERATION_ROUND_RINT, options ) ); } VImage real( VOption *options = 0 ) throw( VError ) { return( complexget( VIPS_OPERATION_COMPLEXGET_REAL, options ) ); } VImage imag( VOption *options = 0 ) throw( VError ) { return( complexget( VIPS_OPERATION_COMPLEXGET_IMAG, options ) ); } VImage polar( VOption *options = 0 ) throw( VError ) { return( complex( VIPS_OPERATION_COMPLEX_POLAR, options ) ); } VImage rect( VOption *options = 0 ) throw( VError ) { return( complex( VIPS_OPERATION_COMPLEX_RECT, options ) ); } VImage conj( VOption *options = 0 ) throw( VError ) { return( complex( VIPS_OPERATION_COMPLEX_CONJ, options ) ); } VImage sin( VOption *options = 0 ) throw( VError ) { return( math( VIPS_OPERATION_MATH_SIN, options ) ); } VImage cos( VOption *options = 0 ) throw( VError ) { return( math( VIPS_OPERATION_MATH_COS, options ) ); } VImage tan( VOption *options = 0 ) throw( VError ) { return( math( VIPS_OPERATION_MATH_TAN, options ) ); } VImage asin( VOption *options = 0 ) throw( VError ) { return( math( VIPS_OPERATION_MATH_ASIN, options ) ); } VImage acos( VOption *options = 0 ) throw( VError ) { return( math( VIPS_OPERATION_MATH_ACOS, options ) ); } VImage atan( VOption *options = 0 ) throw( VError ) { return( math( VIPS_OPERATION_MATH_ATAN, options ) ); } VImage log( VOption *options = 0 ) throw( VError ) { return( math( VIPS_OPERATION_MATH_LOG, options ) ); } VImage log10( VOption *options = 0 ) throw( VError ) { return( math( VIPS_OPERATION_MATH_LOG10, options ) ); } VImage exp( VOption *options = 0 ) throw( VError ) { return( math( VIPS_OPERATION_MATH_EXP, options ) ); } VImage exp10( VOption *options = 0 ) throw( VError ) { return( math( VIPS_OPERATION_MATH_EXP10, options ) ); } VImage pow( VImage other, VOption *options = 0 ) throw( VError ) { return( math2( other, VIPS_OPERATION_MATH2_POW, options ) ); } VImage pow( double other, VOption *options = 0 ) throw( VError ) { return( math2_const( to_vector( other ), VIPS_OPERATION_MATH2_POW, options ) ); } VImage pow( std::vector other, VOption *options = 0 ) throw( VError ) { return( math2_const( other, VIPS_OPERATION_MATH2_POW, options ) ); } VImage wop( VImage other, VOption *options = 0 ) throw( VError ) { return( math2( other, VIPS_OPERATION_MATH2_WOP, options ) ); } VImage wop( double other, VOption *options = 0 ) throw( VError ) { return( math2_const( to_vector( other ), VIPS_OPERATION_MATH2_WOP, options ) ); } VImage wop( std::vector other, VOption *options = 0 ) throw( VError ) { return( math2_const( other, VIPS_OPERATION_MATH2_WOP, options ) ); } VImage ifthenelse( std::vector th, VImage el, VOption *options = 0 ) throw( VError ) { return( ifthenelse( el.new_from_image( th ), el, options ) ); } VImage ifthenelse( VImage th, std::vector el, VOption *options = 0 ) throw( VError ) { return( ifthenelse( th, th.new_from_image( el ), options ) ); } VImage ifthenelse( std::vector th, std::vector el, VOption *options = 0 ) throw( VError ) { return( ifthenelse( new_from_image( th ), new_from_image( el ), options ) ); } VImage ifthenelse( double th, VImage el, VOption *options ) throw( VError ) { return( ifthenelse( to_vector( th ), el, options ) ); } VImage ifthenelse( VImage th, double el, VOption *options ) throw( VError ) { return( ifthenelse( th, to_vector( el ), options ) ); } VImage ifthenelse( double th, double el, VOption *options ) throw( VError ) { return( ifthenelse( to_vector( th ), to_vector( el ), options ) ); } // Operator overloads friend VImage operator+( VImage a, VImage b ) throw( VError ) { return( a.add( b ) ); } friend VImage operator+( double a, VImage b ) throw( VError ) { return( b.linear( 1.0, a ) ); } friend VImage operator+( VImage a, double b ) throw( VError ) { return( a.linear( 1.0, b ) ); } friend VImage operator+( std::vector a, VImage b ) throw( VError ) { return( b.linear( 1.0, a ) ); } friend VImage operator+( VImage a, std::vector b ) throw( VError ) { return( a.linear( 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.linear( -1.0, a ) ); } friend VImage operator-( VImage a, double b ) throw( VError ) { return( a.linear( 1.0, -b ) ); } friend VImage operator-( std::vector a, VImage b ) throw( VError ) { return( b.linear( -1.0, a ) ); } friend VImage operator-( VImage a, std::vector b ) throw( VError ) { return( a.linear( 1.0, vips8::negate( 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.linear( a, 0.0 ) ); } friend VImage operator*( VImage a, double b ) throw( VError ) { return( a.linear( b, 0.0 ) ); } friend VImage operator*( std::vector a, VImage b ) throw( VError ) { return( b.linear( a, 0.0 ) ); } friend VImage operator*( VImage a, std::vector b ) throw( VError ) { return( a.linear( 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 ).linear( a, 0.0 ) ); } friend VImage operator/( VImage a, double b ) throw( VError ) { return( a.linear( 1.0 / b, 0.0 ) ); } friend VImage operator/( std::vector a, VImage b ) throw( VError ) { return( b.pow( -1.0 ).linear( a, 0.0 ) ); } friend VImage operator/( VImage a, std::vector b ) throw( VError ) { return( a.linear( vips8::invert( 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_const( to_vector( b ) ) ); } friend VImage operator%( VImage a, std::vector b ) throw( VError ) { return( a.remainder_const( b ) ); } friend VImage operator<( VImage a, VImage b ) throw( VError ) { return( a.relational( b, VIPS_OPERATION_RELATIONAL_LESS ) ); } friend VImage operator<( double a, VImage b ) throw( VError ) { return( b.relational_const( to_vector( a ), VIPS_OPERATION_RELATIONAL_MORE ) ); } friend VImage operator<( VImage a, double b ) throw( VError ) { return( a.relational_const( to_vector( b ), VIPS_OPERATION_RELATIONAL_LESS ) ); } friend VImage operator<( std::vector a, VImage b ) throw( VError ) { return( b.relational_const( a, VIPS_OPERATION_RELATIONAL_MORE ) ); } friend VImage operator<( VImage a, std::vector b ) throw( VError ) { return( a.relational_const( b, VIPS_OPERATION_RELATIONAL_LESS ) ); } friend VImage operator<=( VImage a, VImage b ) throw( VError ) { return( a.relational( b, VIPS_OPERATION_RELATIONAL_LESSEQ ) ); } friend VImage operator<=( double a, VImage b ) throw( VError ) { return( b.relational_const( to_vector( a ), VIPS_OPERATION_RELATIONAL_MOREEQ ) ); } friend VImage operator<=( VImage a, double b ) throw( VError ) { return( a.relational_const( to_vector( b ), VIPS_OPERATION_RELATIONAL_LESSEQ ) ); } friend VImage operator<=( std::vector a, VImage b ) throw( VError ) { return( b.relational_const( a, VIPS_OPERATION_RELATIONAL_MOREEQ ) ); } friend VImage operator<=( VImage a, std::vector b ) throw( VError ) { return( a.relational_const( b, VIPS_OPERATION_RELATIONAL_LESSEQ ) ); } friend VImage operator>( VImage a, VImage b ) throw( VError ) { return( a.relational( b, VIPS_OPERATION_RELATIONAL_MORE ) ); } friend VImage operator>( double a, VImage b ) throw( VError ) { return( b.relational_const( to_vector( a ), VIPS_OPERATION_RELATIONAL_LESS ) ); } friend VImage operator>( VImage a, double b ) throw( VError ) { return( a.relational_const( to_vector( b ), VIPS_OPERATION_RELATIONAL_MORE ) ); } friend VImage operator>( std::vector a, VImage b ) throw( VError ) { return( b.relational_const( a, VIPS_OPERATION_RELATIONAL_LESS ) ); } friend VImage operator>( VImage a, std::vector b ) throw( VError ) { return( a.relational_const( b, VIPS_OPERATION_RELATIONAL_MORE ) ); } friend VImage operator>=( VImage a, VImage b ) throw( VError ) { return( a.relational( b, VIPS_OPERATION_RELATIONAL_MOREEQ ) ); } friend VImage operator>=( double a, VImage b ) throw( VError ) { return( b.relational_const( to_vector( a ), VIPS_OPERATION_RELATIONAL_LESSEQ ) ); } friend VImage operator>=( VImage a, double b ) throw( VError ) { return( a.relational_const( to_vector( b ), VIPS_OPERATION_RELATIONAL_MOREEQ ) ); } friend VImage operator>=( std::vector a, VImage b ) throw( VError ) { return( b.relational_const( a, VIPS_OPERATION_RELATIONAL_LESSEQ ) ); } friend VImage operator>=( VImage a, std::vector b ) throw( VError ) { return( a.relational_const( b, VIPS_OPERATION_RELATIONAL_MOREEQ ) ); } friend VImage operator==( VImage a, VImage b ) throw( VError ) { return( a.relational( b, VIPS_OPERATION_RELATIONAL_EQUAL ) ); } friend VImage operator==( double a, VImage b ) throw( VError ) { return( b.relational_const( to_vector( a ), VIPS_OPERATION_RELATIONAL_EQUAL ) ); } friend VImage operator==( VImage a, double b ) throw( VError ) { return( a.relational_const( to_vector( b ), VIPS_OPERATION_RELATIONAL_EQUAL ) ); } friend VImage operator==( std::vector a, VImage b ) throw( VError ) { return( b.relational_const( a, VIPS_OPERATION_RELATIONAL_EQUAL ) ); } friend VImage operator==( VImage a, std::vector b ) throw( VError ) { return( a.relational_const( b, VIPS_OPERATION_RELATIONAL_EQUAL ) ); } friend VImage operator!=( VImage a, VImage b ) throw( VError ) { return( a.relational( b, VIPS_OPERATION_RELATIONAL_NOTEQ ) ); } friend VImage operator!=( double a, VImage b ) throw( VError ) { return( b.relational_const( to_vector( a ), VIPS_OPERATION_RELATIONAL_NOTEQ ) ); } friend VImage operator!=( VImage a, double b ) throw( VError ) { return( a.relational_const( to_vector( b ), VIPS_OPERATION_RELATIONAL_NOTEQ ) ); } friend VImage operator!=( std::vector a, VImage b ) throw( VError ) { return( b.relational_const( a, VIPS_OPERATION_RELATIONAL_NOTEQ ) ); } friend VImage operator!=( VImage a, std::vector b ) throw( VError ) { return( a.relational_const( b, VIPS_OPERATION_RELATIONAL_NOTEQ ) ); } friend VImage operator&( VImage a, VImage b ) throw( VError ) { return( a.boolean( b, VIPS_OPERATION_BOOLEAN_AND ) ); } friend VImage operator&( double a, VImage b ) throw( VError ) { return( b.boolean_const( to_vector( a ), VIPS_OPERATION_BOOLEAN_AND ) ); } friend VImage operator&( VImage a, double b ) throw( VError ) { return( a.boolean_const( to_vector( b ), VIPS_OPERATION_BOOLEAN_AND ) ); } friend VImage operator&( std::vector a, VImage b ) throw( VError ) { return( b.boolean_const( a, VIPS_OPERATION_BOOLEAN_AND ) ); } friend VImage operator&( VImage a, std::vector b ) throw( VError ) { return( a.boolean_const( b, VIPS_OPERATION_BOOLEAN_AND ) ); } friend VImage operator|( VImage a, VImage b ) throw( VError ) { return( a.boolean( b, VIPS_OPERATION_BOOLEAN_OR ) ); } friend VImage operator|( double a, VImage b ) throw( VError ) { return( b.boolean_const( to_vector( a ), VIPS_OPERATION_BOOLEAN_OR ) ); } friend VImage operator|( VImage a, double b ) throw( VError ) { return( a.boolean_const( to_vector( b ), VIPS_OPERATION_BOOLEAN_OR ) ); } friend VImage operator|( std::vector a, VImage b ) throw( VError ) { return( b.boolean_const( a, VIPS_OPERATION_BOOLEAN_OR ) ); } friend VImage operator|( VImage a, std::vector b ) throw( VError ) { return( a.boolean_const( b, VIPS_OPERATION_BOOLEAN_OR ) ); } friend VImage operator^( VImage a, VImage b ) throw( VError ) { return( a.boolean( b, VIPS_OPERATION_BOOLEAN_EOR ) ); } friend VImage operator^( double a, VImage b ) throw( VError ) { return( b.boolean_const( to_vector( a ), VIPS_OPERATION_BOOLEAN_EOR ) ); } friend VImage operator^( VImage a, double b ) throw( VError ) { return( a.boolean_const( to_vector( b ), VIPS_OPERATION_BOOLEAN_EOR ) ); } friend VImage operator^( std::vector a, VImage b ) throw( VError ) { return( b.boolean_const( a, VIPS_OPERATION_BOOLEAN_EOR ) ); } friend VImage operator^( VImage a, std::vector b ) throw( VError ) { return( a.boolean_const( b, VIPS_OPERATION_BOOLEAN_EOR ) ); } friend VImage operator<<( VImage a, VImage b ) throw( VError ) { return( a.boolean( b, VIPS_OPERATION_BOOLEAN_LSHIFT ) ); } friend VImage operator<<( VImage a, double b ) throw( VError ) { return( a.boolean_const( to_vector( b ), VIPS_OPERATION_BOOLEAN_LSHIFT ) ); } friend VImage operator<<( VImage a, std::vector b ) throw( VError ) { return( a.boolean_const( b, VIPS_OPERATION_BOOLEAN_LSHIFT ) ); } friend VImage operator>>( VImage a, VImage b ) throw( VError ) { return( a.boolean( b, VIPS_OPERATION_BOOLEAN_RSHIFT ) ); } friend VImage operator>>( VImage a, double b ) throw( VError ) { return( a.boolean_const( to_vector( b ), VIPS_OPERATION_BOOLEAN_RSHIFT ) ); } friend VImage operator>>( VImage a, std::vector b ) throw( VError ) { return( a.boolean_const( b, VIPS_OPERATION_BOOLEAN_RSHIFT ) ); } friend VImage operator-( VImage a ) throw( VError ) { return( a * -1 ); } }; VIPS_NAMESPACE_END #endif /*VIPS_VIMAGE_H*/