wrap im_remosaic() as a class

This commit is contained in:
John Cupitt 2014-05-27 15:18:19 +01:00
parent 781a7d4dc9
commit b8886fc209
6 changed files with 155 additions and 60 deletions

View File

@ -33,8 +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*(), im_global_balance*() redone as
classes
- im_*merge(), im_*mosaic(), im_match*(), im_global_balance*(), im_remosaic()
redone as classes
6/3/14 started 7.38.6
- grey ramp minimum was wrong

15
TODO
View File

@ -1,13 +1,10 @@
- more mosaicing?
- quickly wrap the useful bits of mosaicing
nip2 uses:
im_*merge() done
im_*mosaic() done
im_match_linear*() done
im_global_balancef() done
im_remosaic()
im_lrmerge1(), im_tbmerge1()
im_lrmosaic1(), im_tbmosaic1()
im_correl
im_align_bands()
im_maxpos_subpel()
- can we use postbuild elsewhere? look at use of "preclose" / "written", etc.

View File

@ -5134,3 +5134,20 @@ im_global_balancef( IMAGE *in, IMAGE *out, double gamma )
return( 0 );
}
int
im_remosaic( IMAGE *in, IMAGE *out, const char *old_str, const char *new_str )
{
VipsImage *x;
if( vips_remosaic( in, &x, old_str, new_str, NULL ) )
return( -1 );
if( im_copy( x, out ) ) {
g_object_unref( x );
return( -1 );
}
g_object_unref( x );
return( 0 );
}

View File

@ -44,12 +44,17 @@ int vips_merge( VipsImage *ref, VipsImage *sec, VipsImage **out,
int vips_mosaic( VipsImage *ref, VipsImage *sec, VipsImage **out,
VipsDirection direction, int xref, int yref, int xsec, int ysec, ... )
__attribute__((sentinel));
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));
int vips_remosaic( VipsImage *in, VipsImage **out,
const char *old_str, const char *new_str, ... )
__attribute__((sentinel));
#include <vips/vips.h>
@ -82,8 +87,6 @@ int im_correl( VipsImage *ref, VipsImage *sec,
int xref, int yref, int xsec, int ysec,
int hwindowsize, int hsearchsize,
double *correlation, int *x, int *y );
int im_remosaic( VipsImage *in, VipsImage *out,
const char *old_str, const char *new_str );
int im_align_bands( VipsImage *in, VipsImage *out );
int im_maxpos_subpel( VipsImage *in, double *x, double *y );

View File

@ -1064,6 +1064,9 @@ int im_match_linear_search( VipsImage *ref, VipsImage *sec, VipsImage *out,
int im_global_balance( VipsImage *in, VipsImage *out, double gamma );
int im_global_balancef( VipsImage *in, VipsImage *out, double gamma );
int im_remosaic( VipsImage *in, VipsImage *out,
const char *old_str, const char *new_str );
#ifdef __cplusplus
}
#endif /*__cplusplus*/

View File

@ -56,15 +56,25 @@
#include "mosaic.h"
#include "global_balance.h"
typedef struct _RemosaicData {
const char *old_str;
const char *new_str;
typedef struct {
VipsOperation parent_instance;
VipsImage *in;
VipsImage *out;
char *old_str;
char *new_str;
int new_len;
int old_len;
} RemosaicData;
} VipsRemosaic;
typedef VipsOperationClass VipsRemosaicClass;
G_DEFINE_TYPE( VipsRemosaic, vips_remosaic, VIPS_TYPE_OPERATION );
static IMAGE *
remosaic( JoinNode *node, RemosaicData *rd )
remosaic_fn( JoinNode *node, VipsRemosaic *remosaic )
{
SymbolTable *st = node->st;
IMAGE *im = node->im;
@ -79,17 +89,17 @@ remosaic( JoinNode *node, RemosaicData *rd )
return( NULL );
}
/* Remove substring rd->old_str from in->filename, replace with
* rd->new_str.
/* Remove substring remosaic->old_str from in->filename, replace with
* remosaic->new_str.
*/
im_strncpy( filename, im->filename, FILENAME_MAX );
if( (p = im_strrstr( filename, rd->old_str )) ) {
if( (p = im_strrstr( filename, remosaic->old_str )) ) {
int offset = p - &filename[0];
im_strncpy( p, rd->new_str, FILENAME_MAX - offset );
im_strncpy( p + rd->new_len,
im->filename + offset + rd->old_len,
FILENAME_MAX - offset - rd->new_len );
im_strncpy( p, remosaic->new_str, FILENAME_MAX - offset );
im_strncpy( p + remosaic->new_len,
im->filename + offset + remosaic->old_len,
FILENAME_MAX - offset - remosaic->new_len );
}
#ifdef DEBUG
@ -111,46 +121,111 @@ remosaic( JoinNode *node, RemosaicData *rd )
return( out );
}
/**
* im_remosaic:
* @in: mosaic to rebuild
* @out: output image
* @old_str: gamma of source images
* @new_str: gamma of source images
*
* im_remosaic() works rather as im_global_balance(). It takes apart the
* mosaiced image in and rebuilds it, substituting images.
*
* Unlike im_global_balance(), images are substituted based on their file
* names. The rightmost occurence of the string @old_str is swapped
* for @new_str, that file is opened, and that image substituted for
* the old image.
*
* It's convenient for multispectral images. You can mosaic one band, then
* use that mosaic as a template for mosaicing the others automatically.
*
* See also: im_lrmosaic(), im_global_balance().
*
* Returns: 0 on success, -1 on error
*/
int
im_remosaic( IMAGE *in, IMAGE *out, const char *old_str, const char *new_str )
static int
vips_remosaic_build( VipsObject *object )
{
SymbolTable *st;
RemosaicData rd;
VipsRemosaic *remosaic = (VipsRemosaic *) object;
if( !(st = im__build_symtab( out, SYM_TAB_SIZE )) ||
im__parse_desc( st, in ) )
SymbolTable *st;
g_object_set( remosaic, "out", vips_image_new(), NULL );
if( VIPS_OBJECT_CLASS( vips_remosaic_parent_class )->
build( object ) )
return( -1 );
/* Re-make mosaic.
*/
rd.old_str = old_str;
rd.new_str = new_str;
rd.new_len = strlen( new_str );
rd.old_len = strlen( old_str );
if( im__build_mosaic( st, out, (transform_fn) remosaic, &rd ) )
if( !(st = im__build_symtab( remosaic->out, SYM_TAB_SIZE )) ||
im__parse_desc( st, remosaic->in ) )
return( -1 );
remosaic->old_len = strlen( remosaic->old_str );
remosaic->new_len = strlen( remosaic->new_str );
if( im__build_mosaic( st, remosaic->out,
(transform_fn) remosaic_fn, remosaic ) )
return( -1 );
return( 0 );
}
static void
vips_remosaic_class_init( VipsRemosaicClass *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 = "remosaic";
object_class->description = _( "global balance an image mosaic" );
object_class->build = vips_remosaic_build;
VIPS_ARG_IMAGE( class, "in", 1,
_( "Input" ),
_( "Input image" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsRemosaic, in ) );
VIPS_ARG_IMAGE( class, "out", 2,
_( "Output" ),
_( "Output image" ),
VIPS_ARGUMENT_REQUIRED_OUTPUT,
G_STRUCT_OFFSET( VipsRemosaic, out ) );
VIPS_ARG_STRING( class, "old_str", 5,
_( "old_str" ),
_( "Search for this string" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsRemosaic, old_str ),
"" );
VIPS_ARG_STRING( class, "new_str", 6,
_( "new_str" ),
_( "And swap for this string" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsRemosaic, new_str ),
"" );
}
static void
vips_remosaic_init( VipsRemosaic *remosaic )
{
}
/**
* vips_remosaic:
* @in: mosaic to rebuild
* @out: output image
* @old_str: gamma of source images
* @new_str: gamma of source images
* @...: %NULL-terminated list of optional named arguments
*
* vips_remosaic() works rather as vips_globalbalance(). It takes apart the
* mosaiced image @in and rebuilds it, substituting images.
*
* Unlike vips_globalbalance(), images are substituted based on their file
* names. The rightmost occurence of the string @old_str is swapped
* for @new_str, that file is opened, and that image substituted for
* the old image.
*
* It's convenient for multispectral images. You can mosaic one band, then
* use that mosaic as a template for mosaicing the others automatically.
*
* See also: vips_globalbalance().
*
* Returns: 0 on success, -1 on error
*/
int
vips_remosaic( VipsImage *in, VipsImage **out,
const char *old_str, const char *new_str, ... )
{
va_list ap;
int result;
va_start( ap, new_str );
result = vips_call_split( "remosaic", ap, in, out, old_str, new_str );
va_end( ap );
return( result );
}