diff --git a/ChangeLog b/ChangeLog index 7f5bc6b0..ed73bd73 100644 --- a/ChangeLog +++ b/ChangeLog @@ -33,7 +33,8 @@ - added im_tile_cache_random() to help nip2 - added hough_circle() to vips7 C++ API - added Travis CI config, thanks Lovell -- im_*merge(), im_*mosaic(), im_match*() redone as classes +- im_*merge(), im_*mosaic(), im_match*(), im_global_balance*() redone as + classes 6/3/14 started 7.38.6 - grey ramp minimum was wrong diff --git a/TODO b/TODO index 97ac6e1b..c42a42c5 100644 --- a/TODO +++ b/TODO @@ -1,12 +1,12 @@ -- quickly wrap the useful bits of mosaicing/ +- quickly wrap the useful bits of mosaicing nip2 uses: im_*merge() done im_*mosaic() done im_match_linear*() done - im_global_balancef() + im_global_balancef() done im_remosaic() - can we use postbuild elsewhere? look at use of "preclose" / "written", etc. diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index 5d361438..e14fd833 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -5095,3 +5095,42 @@ im_match_linear( IMAGE *ref, IMAGE *sec, IMAGE *out, return( 0 ); } + +int +im_global_balance( IMAGE *in, IMAGE *out, double gamma ) +{ + VipsImage *x; + + if( vips_globalbalance( in, &x, + "gamma", gamma, + "int_output", TRUE, + NULL ) ) + return( -1 ); + + if( im_copy( x, out ) ) { + g_object_unref( x ); + return( -1 ); + } + g_object_unref( x ); + + return( 0 ); +} + +int +im_global_balancef( IMAGE *in, IMAGE *out, double gamma ) +{ + VipsImage *x; + + if( vips_globalbalance( in, &x, + "gamma", gamma, + NULL ) ) + return( -1 ); + + if( im_copy( x, out ) ) { + g_object_unref( x ); + return( -1 ); + } + g_object_unref( x ); + + return( 0 ); +} diff --git a/libvips/include/vips/mosaicing.h b/libvips/include/vips/mosaicing.h index a36854a6..f01d8ca0 100644 --- a/libvips/include/vips/mosaicing.h +++ b/libvips/include/vips/mosaicing.h @@ -48,10 +48,8 @@ int vips_match( VipsImage *ref, VipsImage *sec, VipsImage **out, int xr1, int yr1, int xs1, int ys1, int xr2, int yr2, int xs2, int ys2, ... ) __attribute__((sentinel)); - - - - +int vips_globalbalance( VipsImage *in, VipsImage **out, ... ) + __attribute__((sentinel)); #include @@ -80,9 +78,6 @@ int im_tbmosaic1( VipsImage *ref, VipsImage *sec, VipsImage *out, int balancetype, int mwidth ); -int im_global_balance( VipsImage *in, VipsImage *out, double gamma ); -int im_global_balancef( VipsImage *in, VipsImage *out, double gamma ); - int im_correl( VipsImage *ref, VipsImage *sec, int xref, int yref, int xsec, int ysec, int hwindowsize, int hsearchsize, diff --git a/libvips/include/vips/vips7compat.h b/libvips/include/vips/vips7compat.h index 35480a09..9dcfa3a5 100644 --- a/libvips/include/vips/vips7compat.h +++ b/libvips/include/vips/vips7compat.h @@ -1061,6 +1061,9 @@ int im_match_linear_search( VipsImage *ref, VipsImage *sec, VipsImage *out, int xr2, int yr2, int xs2, int ys2, int hwindowsize, int hsearchsize ); +int im_global_balance( VipsImage *in, VipsImage *out, double gamma ); +int im_global_balancef( VipsImage *in, VipsImage *out, double gamma ); + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/libvips/mosaicing/global_balance.c b/libvips/mosaicing/global_balance.c index 72d532f5..e1c3884d 100644 --- a/libvips/mosaicing/global_balance.c +++ b/libvips/mosaicing/global_balance.c @@ -1705,13 +1705,108 @@ transformf( JoinNode *node, double *gamma ) return( out ); } +typedef struct { + VipsOperation parent_instance; + + VipsImage *in; + VipsImage *out; + + gboolean int_output; + double gamma; + +} VipsGlobalbalance; + +typedef VipsOperationClass VipsGlobalbalanceClass; + +G_DEFINE_TYPE( VipsGlobalbalance, vips_globalbalance, VIPS_TYPE_OPERATION ); + +static int +vips_globalbalance_build( VipsObject *object ) +{ + VipsGlobalbalance *globalbalance = (VipsGlobalbalance *) object; + + SymbolTable *st; + transform_fn trn; + + g_object_set( globalbalance, "out", vips_image_new(), NULL ); + + if( VIPS_OBJECT_CLASS( vips_globalbalance_parent_class )-> + build( object ) ) + return( -1 ); + + if( !(st = im__build_symtab( globalbalance->out, SYM_TAB_SIZE )) || + analyse_mosaic( st, globalbalance->in ) || + find_factors( st, globalbalance->gamma ) ) + return( -1 ); + + trn = globalbalance->int_output ? + (transform_fn) transform : (transform_fn) transformf; + if( im__build_mosaic( st, globalbalance->out, + trn, &globalbalance->gamma ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_globalbalance_class_init( VipsGlobalbalanceClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + object_class->nickname = "globalbalance"; + object_class->description = _( "global balance an image mosaic" ); + object_class->build = vips_globalbalance_build; + + VIPS_ARG_IMAGE( class, "in", 1, + _( "Input" ), + _( "Input image" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsGlobalbalance, in ) ); + + VIPS_ARG_IMAGE( class, "out", 2, + _( "Output" ), + _( "Output image" ), + VIPS_ARGUMENT_REQUIRED_OUTPUT, + G_STRUCT_OFFSET( VipsGlobalbalance, out ) ); + + VIPS_ARG_DOUBLE( class, "gamma", 5, + _( "gamma" ), + _( "Image gamma" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsGlobalbalance, gamma ), + 0.00001, 10, 1.6 ); + + VIPS_ARG_BOOL( class, "int_output", 7, + _( "Int output" ), + _( "Integer output" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsGlobalbalance, int_output ), + FALSE ); + +} + +static void +vips_globalbalance_init( VipsGlobalbalance *globalbalance ) +{ + globalbalance->gamma = 1.6; +} + /** - * im_global_balance: + * vips_globalbalance: * @in: mosaic to rebuild * @out: output image - * @gamma: gamma of source images + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: * - * im_global_balance() can be used to remove contrast differences in + * @gamma: gamma of source images + * @int_output: %TRUE for integer image output + * + * vips_globalbalance() can be used to remove contrast differences in * an assembled mosaic. * * It reads the History field attached to @in and builds a list of the source @@ -1726,56 +1821,28 @@ transformf( JoinNode *node, double *gamma ) * 1.0 will stop this. * * Each of the source images is transformed with the appropriate correction - * factor, then the mosaic is reassembled. @out always has the same #BandFmt - * as @in. Use im_global_balancef() to get float output and avoid clipping. + * factor, then the mosaic is reassembled. @out is #VIPS_FORMAT_FLOAT, but + * if @int_output is set, the output image is the same format as the input + * images. * * There are some conditions that must be met before this operation can work: * the source images must all be present under the filenames recorded in the * history on @in, and the mosaic must have been built using only operations in * this package. * - * See also: im_global_balancef(), im_remosaic(). + * See also: vips_remosaic(). * * Returns: 0 on success, -1 on error */ -int -im_global_balance( IMAGE *in, IMAGE *out, double gamma ) +int +vips_globalbalance( VipsImage *in, VipsImage **out, ... ) { - SymbolTable *st; + va_list ap; + int result; - if( !(st = im__build_symtab( out, SYM_TAB_SIZE )) || - analyse_mosaic( st, in ) || - find_factors( st, gamma ) || - im__build_mosaic( st, out, (transform_fn) transform, &gamma ) ) - return( -1 ); + va_start( ap, out ); + result = vips_call_split( "globalbalance", ap, in, out ); + va_end( ap ); - return( 0 ); -} - -/** - * im_global_balancef: - * @in: mosaic to rebuild - * @out: output image - * @gamma: gamma of source images - * - * Just as im_global_balance(), but the output image is always float. This - * stops overflow or underflow in the case of an extremely unbalanced image - * mosaic. - * - * See also: im_global_balance(), im_remosaic(). - * - * Returns: 0 on success, -1 on error - */ -int -im_global_balancef( IMAGE *in, IMAGE *out, double gamma ) -{ - SymbolTable *st; - - if( !(st = im__build_symtab( out, SYM_TAB_SIZE )) || - analyse_mosaic( st, in ) || - find_factors( st, gamma ) || - im__build_mosaic( st, out, (transform_fn) transformf, &gamma ) ) - return( -1 ); - - return( 0 ); + return( result ); } diff --git a/libvips/mosaicing/mosaicing.c b/libvips/mosaicing/mosaicing.c index 3d23be8f..b183ef20 100644 --- a/libvips/mosaicing/mosaicing.c +++ b/libvips/mosaicing/mosaicing.c @@ -58,14 +58,14 @@ * * The mosaicing functions can be grouped into layers: * - * The lowest level functions are im_correl(), im_lrmerge() and im_tbmerge(). + * The lowest level functions are im_correl() and vips_merge(). * im_correl() * searches a large image for a small sub-image, returning - * the position of the best sub-image match. im_lrmerge() and im_tbmerge() - * join two images together + * the position of the best sub-image match. vips_merge() + * joins two images together * left-right or up-down with a smooth seam. * - * Next, im_lrmosaic() and im_tbmosaic() use the + * Next, vips_mosaic() use the * search function plus the two low-level merge operations to join two images * given just an approximate overlap as a start point. * @@ -76,7 +76,7 @@ * them to rotate and scale the right-hand or bottom image before starting to * join. * - * Finally, im_global_balance() can be used to remove contrast differences in + * Finally, vips_globalbalance() can be used to remove contrast differences in * a mosaic * which has been assembled with these functions. It takes the mosaic apart, * measures image contrast differences along the seams, finds a set of @@ -98,8 +98,10 @@ vips_mosaicing_operation_init( void ) extern int vips_merge_get_type( void ); extern int vips_mosaic_get_type( void ); extern int vips_match_get_type( void ); + extern int vips_globalbalance_get_type( void ); vips_merge_get_type(); vips_mosaic_get_type(); vips_match_get_type(); + vips_globalbalance_get_type(); }