diff --git a/ChangeLog b/ChangeLog
index e9b28b22..b5755822 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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*(), im_remosaic()
- redone as classes
+- im_*merge(), im_*mosaic(), im_match*(), im_global_balance*(), im_remosaic(),
+ im_*mosaic1() redone as classes
6/3/14 started 7.38.6
- grey ramp minimum was wrong
diff --git a/TODO b/TODO
index 14d3b7e2..d0d2a475 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,7 @@
- more mosaicing?
- im_lrmerge1(), im_tbmerge1()
- im_lrmosaic1(), im_tbmosaic1()
+ im_lrmosaic1(), im_tbmosaic1() done
+ im_lrmerge1(), im_tbmerge1()
im_correl
im_align_bands()
im_maxpos_subpel()
diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c
index 6fc4b27a..ed05a29f 100644
--- a/libvips/deprecated/vips7compat.c
+++ b/libvips/deprecated/vips7compat.c
@@ -5151,3 +5151,59 @@ im_remosaic( IMAGE *in, IMAGE *out, const char *old_str, const char *new_str )
return( 0 );
}
+
+int
+im_lrmosaic1( IMAGE *ref, IMAGE *sec, IMAGE *out,
+ int bandno,
+ int xr1, int yr1, int xs1, int ys1,
+ int xr2, int yr2, int xs2, int ys2,
+ int hwindowsize, int hsearchsize,
+ int balancetype,
+ int mwidth )
+{
+ VipsImage *x;
+
+ if( vips_mosaic1( ref, sec, &x, VIPS_DIRECTION_HORIZONTAL,
+ xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
+ "bandno", bandno,
+ "hwindow", hwindowsize,
+ "harea", hsearchsize,
+ "mblend", mwidth,
+ NULL ) )
+ return( -1 );
+ if( im_copy( x, out ) ) {
+ g_object_unref( x );
+ return( -1 );
+ }
+ g_object_unref( x );
+
+ return( 0 );
+}
+
+int
+im_tbmosaic1( IMAGE *ref, IMAGE *sec, IMAGE *out,
+ int bandno,
+ int xr1, int yr1, int xs1, int ys1,
+ int xr2, int yr2, int xs2, int ys2,
+ int hwindowsize, int hsearchsize,
+ int balancetype,
+ int mwidth )
+{
+ VipsImage *x;
+
+ if( vips_mosaic1( ref, sec, &x, VIPS_DIRECTION_VERTICAL,
+ xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
+ "bandno", bandno,
+ "hwindow", hwindowsize,
+ "harea", hsearchsize,
+ "mblend", mwidth,
+ 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 380fe9e5..247e25eb 100644
--- a/libvips/include/vips/mosaicing.h
+++ b/libvips/include/vips/mosaicing.h
@@ -44,6 +44,11 @@ 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_mosaic1( VipsImage *ref, VipsImage *sec, VipsImage **out,
+ VipsDirection direction,
+ int xr1, int yr1, int xs1, int ys1,
+ int xr2, int yr2, int xs2, int ys2, ... )
+ __attribute__((sentinel));
int vips_match( VipsImage *ref, VipsImage *sec, VipsImage **out,
int xr1, int yr1, int xs1, int ys1,
@@ -68,21 +73,6 @@ int im_tbmerge1( VipsImage *ref, VipsImage *sec, VipsImage *out,
int xr2, int yr2, int xs2, int ys2,
int mwidth );
-int im_lrmosaic1( VipsImage *ref, VipsImage *sec, VipsImage *out,
- int bandno,
- int xr1, int yr1, int xs1, int ys1,
- int xr2, int yr2, int xs2, int ys2,
- int hwindowsize, int hsearchsize,
- int balancetype,
- int mwidth );
-int im_tbmosaic1( VipsImage *ref, VipsImage *sec, VipsImage *out,
- int bandno,
- int xr1, int yr1, int xs1, int ys1,
- int xr2, int yr2, int xs2, int ys2,
- int hwindowsize, int hsearchsize,
- int balancetype,
- int mwidth );
-
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 3b1018f6..0c113b97 100644
--- a/libvips/include/vips/vips7compat.h
+++ b/libvips/include/vips/vips7compat.h
@@ -1067,6 +1067,21 @@ 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 );
+int im_lrmosaic1( VipsImage *ref, VipsImage *sec, VipsImage *out,
+ int bandno,
+ int xr1, int yr1, int xs1, int ys1,
+ int xr2, int yr2, int xs2, int ys2,
+ int hwindowsize, int hsearchsize,
+ int balancetype,
+ int mwidth );
+int im_tbmosaic1( VipsImage *ref, VipsImage *sec, VipsImage *out,
+ int bandno,
+ int xr1, int yr1, int xs1, int ys1,
+ int xr2, int yr2, int xs2, int ys2,
+ int hwindowsize, int hsearchsize,
+ int balancetype,
+ int mwidth );
+
#ifdef __cplusplus
}
#endif /*__cplusplus*/
diff --git a/libvips/mosaicing/match.c b/libvips/mosaicing/match.c
index 6cdec911..218c9806 100644
--- a/libvips/mosaicing/match.c
+++ b/libvips/mosaicing/match.c
@@ -288,14 +288,14 @@ vips_match_class_init( VipsMatchClass *class )
G_STRUCT_OFFSET( VipsMatch, harea ),
0, 1000000000, 1 );
- VIPS_ARG_BOOL( class, "search", 13,
+ VIPS_ARG_BOOL( class, "search", 15,
_( "search" ),
_( "Search to improve tie-points" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsMatch, search ),
FALSE );
- VIPS_ARG_INTERPOLATE( class, "interpolate", 2,
+ VIPS_ARG_INTERPOLATE( class, "interpolate", 16,
_( "Interpolate" ),
_( "Interpolate pixels with this" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
diff --git a/libvips/mosaicing/mosaic1.c b/libvips/mosaicing/mosaic1.c
index f90ee89d..3cc49fb8 100644
--- a/libvips/mosaicing/mosaic1.c
+++ b/libvips/mosaicing/mosaic1.c
@@ -410,133 +410,6 @@ rotjoin_search( IMAGE *ref, IMAGE *sec, IMAGE *out, joinfn jfn,
return( 0 );
}
-/**
- * im_lrmosaic1:
- * @ref: reference image
- * @sec: secondary image
- * @out: output image
- * @bandno: band to search for features
- * @xr1: first reference tie-point
- * @yr1: first reference tie-point
- * @xs1: first secondary tie-point
- * @ys1: first secondary tie-point
- * @xr2: second reference tie-point
- * @yr2: second reference tie-point
- * @xs2: second secondary tie-point
- * @ys2: second secondary tie-point
- * @hwindowsize: half window size
- * @hsearchsize: half search size
- * @balancetype: no longer used
- * @mwidth: maximum blend width
- *
- * This operation joins two images left-right (with @ref on the left)
- * given an approximate pair of tie-points. @sec is scaled and rotated as
- * necessary before the join.
- *
- * Before performing the transformation, the tie-points are improved by
- * searching band @bandno in an area of @sec of size @hsearchsize for a
- * match of size @hwindowsize to @ref.
- *
- * @mwidth limits the maximum width of the
- * blend area. A value of "-1" means "unlimited". The two images are blended
- * with a raised cosine.
- *
- * Pixels with all bands equal to zero are "transparent", that
- * is, zero pixels in the overlap area do not contribute to the merge.
- * This makes it possible to join non-rectangular images.
- *
- * If the number of bands differs, one of the images
- * must have one band. In this case, an n-band image is formed from the
- * one-band image by joining n copies of the one-band image together, and then
- * the two n-band images are operated upon.
- *
- * The two input images are cast up to the smallest common type (see table
- * Smallest common format in
- * arithmetic).
- *
- * See also: im_tbmosaic1(), im_lrmerge(), im_insert(), im_global_balance().
- *
- * Returns: 0 on success, -1 on error
- */
-int
-im_lrmosaic1( IMAGE *ref, IMAGE *sec, IMAGE *out,
- int bandno,
- int xr1, int yr1, int xs1, int ys1,
- int xr2, int yr2, int xs2, int ys2,
- int hwindowsize, int hsearchsize,
- int balancetype,
- int mwidth )
-{
- return( rotjoin_search( ref, sec, out, im__lrmerge1,
- bandno,
- xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
- hwindowsize, hsearchsize, balancetype,
- mwidth ) );
-}
-
-/**
- * im_tbmosaic1:
- * @ref: reference image
- * @sec: secondary image
- * @out: output image
- * @bandno: band to search for features
- * @xr1: first reference tie-point
- * @yr1: first reference tie-point
- * @xs1: first secondary tie-point
- * @ys1: first secondary tie-point
- * @xr2: second reference tie-point
- * @yr2: second reference tie-point
- * @xs2: second secondary tie-point
- * @ys2: second secondary tie-point
- * @hwindowsize: half window size
- * @hsearchsize: half search size
- * @balancetype: no longer used
- * @mwidth: maximum blend width
- *
- * This operation joins two images top-bottom (with @ref on the top)
- * given an approximate pair of tie-points. @sec is scaled and rotated as
- * necessary before the join.
- *
- * Before performing the transformation, the tie-points are improved by
- * searching band @bandno in an area of @sec of size @hsearchsize for a
- * match of size @hwindowsize to @ref.
- *
- * @mwidth limits the maximum height of the
- * blend area. A value of "-1" means "unlimited". The two images are blended
- * with a raised cosine.
- *
- * Pixels with all bands equal to zero are "transparent", that
- * is, zero pixels in the overlap area do not contribute to the merge.
- * This makes it possible to join non-rectangular images.
- *
- * If the number of bands differs, one of the images
- * must have one band. In this case, an n-band image is formed from the
- * one-band image by joining n copies of the one-band image together, and then
- * the two n-band images are operated upon.
- *
- * The two input images are cast up to the smallest common type (see table
- * Smallest common format in
- * arithmetic).
- *
- * See also: im_lrmosaic1(), im_tbmerge(), im_insert(), im_global_balance().
- *
- * Returns: 0 on success, -1 on error
- */
-int
-im_tbmosaic1( IMAGE *ref, IMAGE *sec, IMAGE *out,
- int bandno,
- int xr1, int yr1, int xs1, int ys1,
- int xr2, int yr2, int xs2, int ys2,
- int hwindowsize, int hsearchsize,
- int balancetype,
- int mwidth )
-{
- return( rotjoin_search( ref, sec, out, im__tbmerge1,
- bandno,
- xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
- hwindowsize, hsearchsize, balancetype, mwidth ) );
-}
-
#ifdef OLD
/* 1st order mosaic using im__find_lroverlap() ... does not work too well :(
* Look at im__find_lroverlap() for problem?
@@ -623,3 +496,292 @@ old_lrmosaic1( IMAGE *ref, IMAGE *sec, IMAGE *out,
return( 0 );
}
#endif /*OLD*/
+
+typedef struct {
+ VipsOperation parent_instance;
+
+ VipsImage *ref;
+ VipsImage *sec;
+ VipsImage *out;
+ VipsDirection direction;
+ int xr1;
+ int yr1;
+ int xs1;
+ int ys1;
+ int xr2;
+ int yr2;
+ int xs2;
+ int ys2;
+ int hwindow;
+ int harea;
+ gboolean search;
+ VipsInterpolate *interpolate;
+ int mblend;
+ int bandno;
+
+} VipsMosaic1;
+
+typedef VipsOperationClass VipsMosaic1Class;
+
+G_DEFINE_TYPE( VipsMosaic1, vips_mosaic1, VIPS_TYPE_OPERATION );
+
+static int
+vips_mosaic1_build( VipsObject *object )
+{
+ VipsMosaic1 *mosaic1 = (VipsMosaic1 *) object;
+
+ joinfn jfn;
+
+ g_object_set( mosaic1, "out", vips_image_new(), NULL );
+
+ if( VIPS_OBJECT_CLASS( vips_mosaic1_parent_class )->build( object ) )
+ return( -1 );
+
+ if( !mosaic1->interpolate )
+ mosaic1->interpolate = vips_interpolate_new( "bilinear" );
+
+ jfn = mosaic1->direction == VIPS_DIRECTION_HORIZONTAL ?
+ im__lrmerge1 : im__tbmerge1;
+
+ if( mosaic1->search ) {
+ if( rotjoin_search( mosaic1->ref, mosaic1->sec, mosaic1->out,
+ jfn,
+ mosaic1->bandno,
+ mosaic1->xr1, mosaic1->yr1, mosaic1->xs1, mosaic1->ys1,
+ mosaic1->xr2, mosaic1->yr2, mosaic1->xs2, mosaic1->ys2,
+ mosaic1->hwindow, mosaic1->harea,
+ 0,
+ mosaic1->mblend ) )
+ return( -1 );
+ }
+ else {
+ if( rotjoin( mosaic1->ref, mosaic1->sec, mosaic1->out,
+ jfn,
+ mosaic1->xr1, mosaic1->yr1, mosaic1->xs1, mosaic1->ys1,
+ mosaic1->xr2, mosaic1->yr2, mosaic1->xs2, mosaic1->ys2,
+ mosaic1->mblend ) )
+ return( -1 );
+ }
+
+ return( 0 );
+}
+
+static void
+vips_mosaic1_class_init( VipsMosaic1Class *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 = "mosaic1";
+ object_class->description = _( "first-order mosaic of two images" );
+ object_class->build = vips_mosaic1_build;
+
+ VIPS_ARG_IMAGE( class, "ref", 1,
+ _( "Reference" ),
+ _( "Reference image" ),
+ VIPS_ARGUMENT_REQUIRED_INPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, ref ) );
+
+ VIPS_ARG_IMAGE( class, "sec", 2,
+ _( "Secondary" ),
+ _( "Secondary image" ),
+ VIPS_ARGUMENT_REQUIRED_INPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, sec ) );
+
+ VIPS_ARG_IMAGE( class, "out", 3,
+ _( "Output" ),
+ _( "Output image" ),
+ VIPS_ARGUMENT_REQUIRED_OUTPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, out ) );
+
+ VIPS_ARG_ENUM( class, "direction", 4,
+ _( "Direction" ),
+ _( "Horizontal or vertcial mosaic" ),
+ VIPS_ARGUMENT_REQUIRED_INPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, direction ),
+ VIPS_TYPE_DIRECTION, VIPS_DIRECTION_HORIZONTAL );
+
+ VIPS_ARG_INT( class, "xr1", 5,
+ _( "xr1" ),
+ _( "Position of first reference tie-point" ),
+ VIPS_ARGUMENT_REQUIRED_INPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, xr1 ),
+ -1000000000, 1000000000, 1 );
+
+ VIPS_ARG_INT( class, "yr1", 6,
+ _( "yr1" ),
+ _( "Position of first reference tie-point" ),
+ VIPS_ARGUMENT_REQUIRED_INPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, yr1 ),
+ -1000000000, 1000000000, 1 );
+
+ VIPS_ARG_INT( class, "xs1", 7,
+ _( "xs1" ),
+ _( "Position of first secondary tie-point" ),
+ VIPS_ARGUMENT_REQUIRED_INPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, xs1 ),
+ -1000000000, 1000000000, 1 );
+
+ VIPS_ARG_INT( class, "ys1", 8,
+ _( "ys1" ),
+ _( "Position of first secondary tie-point" ),
+ VIPS_ARGUMENT_REQUIRED_INPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, ys1 ),
+ -1000000000, 1000000000, 1 );
+
+ VIPS_ARG_INT( class, "xr2", 9,
+ _( "xr2" ),
+ _( "Position of second reference tie-point" ),
+ VIPS_ARGUMENT_REQUIRED_INPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, xr2 ),
+ -1000000000, 1000000000, 1 );
+
+ VIPS_ARG_INT( class, "yr2", 10,
+ _( "yr2" ),
+ _( "Position of second reference tie-point" ),
+ VIPS_ARGUMENT_REQUIRED_INPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, yr2 ),
+ -1000000000, 1000000000, 1 );
+
+ VIPS_ARG_INT( class, "xs2", 11,
+ _( "xs2" ),
+ _( "Position of second secondary tie-point" ),
+ VIPS_ARGUMENT_REQUIRED_INPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, xs2 ),
+ -1000000000, 1000000000, 1 );
+
+ VIPS_ARG_INT( class, "ys2", 12,
+ _( "ys2" ),
+ _( "Position of second secondary tie-point" ),
+ VIPS_ARGUMENT_REQUIRED_INPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, ys2 ),
+ -1000000000, 1000000000, 1 );
+
+ VIPS_ARG_INT( class, "hwindow", 13,
+ _( "hwindow" ),
+ _( "Half window size" ),
+ VIPS_ARGUMENT_OPTIONAL_INPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, hwindow ),
+ 0, 1000000000, 1 );
+
+ VIPS_ARG_INT( class, "harea", 14,
+ _( "harea" ),
+ _( "Half area size" ),
+ VIPS_ARGUMENT_OPTIONAL_INPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, harea ),
+ 0, 1000000000, 1 );
+
+ VIPS_ARG_BOOL( class, "search", 13,
+ _( "search" ),
+ _( "Search to improve tie-points" ),
+ VIPS_ARGUMENT_OPTIONAL_INPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, search ),
+ FALSE );
+
+ VIPS_ARG_INTERPOLATE( class, "interpolate", 14,
+ _( "Interpolate" ),
+ _( "Interpolate pixels with this" ),
+ VIPS_ARGUMENT_OPTIONAL_INPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, interpolate ) );
+
+ VIPS_ARG_INT( class, "mblend", 15,
+ _( "Max blend" ),
+ _( "Maximum blend size" ),
+ VIPS_ARGUMENT_OPTIONAL_INPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, mblend ),
+ 0, 10000, 10 );
+
+ VIPS_ARG_INT( class, "bandno", 16,
+ _( "Search band" ),
+ _( "Band to search for features on" ),
+ VIPS_ARGUMENT_OPTIONAL_INPUT,
+ G_STRUCT_OFFSET( VipsMosaic1, bandno ),
+ 0, 10000, 0 );
+
+}
+
+static void
+vips_mosaic1_init( VipsMosaic1 *mosaic1 )
+{
+ mosaic1->hwindow = 5;
+ mosaic1->harea = 15;
+ mosaic1->mblend = 10;
+}
+
+/**
+ * vips_mosaic1:
+ * @ref: reference image
+ * @sec: secondary image
+ * @out: output image
+ * @direction: horizontal or vertical join
+ * @xr1: first reference tie-point
+ * @yr1: first reference tie-point
+ * @xs1: first secondary tie-point
+ * @ys1: first secondary tie-point
+ * @xr2: second reference tie-point
+ * @yr2: second reference tie-point
+ * @xs2: second secondary tie-point
+ * @ys2: second secondary tie-point
+ *
+ * Optional arguments:
+ *
+ * @search: search to improve tie-points
+ * @hwindow: half window size
+ * @harea: half search size
+ * @interpolate: interpolate pixels with this
+ * @mblend: maximum blend size
+ * @bandno: band to search for features
+ *
+ * This operation joins two images top-bottom (with @sec on the right)
+ * or left-right (with @sec at the bottom)
+ * given an approximate pair of tie-points. @sec is scaled and rotated as
+ * necessary before the join.
+ *
+ * Before performing the transformation, the tie-points are improved by
+ * searching band @bandno in an area of @sec of size @hsearchsize for a
+ * match of size @hwindowsize to @ref.
+ *
+ * If @search is %TRUE, before performing the transformation, the tie-points
+ * are improved by searching an area of @sec of size @harea for a
+ * mosaic1 of size @hwindow to @ref.
+ *
+ * @mblend limits the maximum size of the
+ * blend area. A value of "-1" means "unlimited". The two images are blended
+ * with a raised cosine.
+ *
+ * Pixels with all bands equal to zero are "transparent", that
+ * is, zero pixels in the overlap area do not contribute to the merge.
+ * This makes it possible to join non-rectangular images.
+ *
+ * If the number of bands differs, one of the images
+ * must have one band. In this case, an n-band image is formed from the
+ * one-band image by joining n copies of the one-band image together, and then
+ * the two n-band images are operated upon.
+ *
+ * The two input images are cast up to the smallest common type (see table
+ * Smallest common format in
+ * arithmetic).
+ *
+ * See also: vips_merge(), vips_insert(), vips_globalbalance().
+ *
+ * Returns: 0 on success, -1 on error
+ */
+int
+vips_mosaic1( VipsImage *ref, VipsImage *sec, VipsImage **out,
+ VipsDirection direction,
+ int xr1, int yr1, int xs1, int ys1,
+ int xr2, int yr2, int xs2, int ys2, ... )
+{
+ va_list ap;
+ int result;
+
+ va_start( ap, ys2 );
+ result = vips_call_split( "mosaic1", ap, ref, sec, out, direction,
+ xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2 );
+ va_end( ap );
+
+ return( result );
+}
diff --git a/libvips/mosaicing/mosaicing.c b/libvips/mosaicing/mosaicing.c
index b183ef20..0e03430b 100644
--- a/libvips/mosaicing/mosaicing.c
+++ b/libvips/mosaicing/mosaicing.c
@@ -97,11 +97,13 @@ vips_mosaicing_operation_init( void )
{
extern int vips_merge_get_type( void );
extern int vips_mosaic_get_type( void );
+ extern int vips_mosaic1_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_mosaic1_get_type();
vips_match_get_type();
vips_globalbalance_get_type();
}