mask builders take prec, not integer

vips_gaussmat() and vips_logmat() used to default to float, but
vips_conv() defaulted to int ... so this failed:

	vips gaussmat m.v 2 0.1 --separable
	vips convsep k2.jpg x.jpg m.v

since we were using a small float mask with an integer convolution

This change makes everything int by default, with gaussmat having a new
param called --precision whose arg can be int or float.

The old @integer param is deprecated.
This commit is contained in:
John Cupitt 2014-12-16 20:48:11 +00:00
parent 1f85ef7fbb
commit 6e2135d8b5
15 changed files with 124 additions and 64 deletions

View File

@ -7,6 +7,8 @@
- support tiff XMP metadata
- support @density arg to magickload [Lovell]
- support python3.4 and python2.7 in new python binding
- vips_gaussmat() and vips_logmat() are now int by default, to match
vips_conv(), and use @precision, not @integer
25/7/14 started 7.41.0
- start working on --disable-deprecated

12
TODO
View File

@ -1,15 +1,3 @@
- try:
vips gaussmat m2.v 2 0.1 --separable
vips convsep k2.jpg x2.jpg m2.v
eog x2.jpg
it's too bright ... because gaussmat makes a float mask by default, but
conv does an int convolution by default
rather than an --integer switch on gaussmat, should it take --precision
instead, and default to INT, like conv?
- configure should check for pygobject too
PKG_CHECK_MODULES(PYTHON, [pygobject-3.0 >= $PYGOBJECT_REQUIRED])

View File

@ -75,7 +75,7 @@ vips_gaussblur_build( VipsObject *object )
if( vips_gaussmat( &t[0], gaussblur->sigma, gaussblur->min_ampl,
"separable", TRUE,
"integer", gaussblur->precision != VIPS_PRECISION_FLOAT,
"precision", gaussblur->precision,
NULL ) )
return( -1 );

View File

@ -236,7 +236,7 @@ vips_sharpen_build( VipsObject *object )
*/
if( vips_gaussmat( &t[1], 1 + sharpen->radius / 2, 0.2,
"separable", TRUE,
"integer", TRUE,
"precision", VIPS_PRECISION_INTEGER,
NULL ) )
return( -1 );

View File

@ -15,6 +15,9 @@
* - gtkdoc
* 20/10/13
* - redone as a class
* 16/12/14
* - default to int output to match vips_conv()
* - use @precision, not @integer
*/
/*
@ -69,7 +72,8 @@ typedef struct _VipsGaussmat {
double min_ampl;
gboolean separable;
gboolean integer;
gboolean integer; /* Deprecated */
VipsPrecision precision;
} VipsGaussmat;
@ -96,6 +100,13 @@ vips_gaussmat_build( VipsObject *object )
if( VIPS_OBJECT_CLASS( vips_gaussmat_parent_class )->build( object ) )
return( -1 );
if( vips_object_argument_isset( object, "integer" ) )
vips_warn( class->nickname,
"'integer' is deprecated, use 'precision' instead" );
if( vips_check_precision_intfloat( class->nickname,
gaussmat->precision ) )
return( -1 );
/* Find the size of the mask. Limit the mask size to 10k x 10k for
* sanity.
*/
@ -129,7 +140,7 @@ vips_gaussmat_build( VipsObject *object )
double distance = xo * xo + yo * yo;
double v = exp( -distance / sig2 );
if( gaussmat->integer )
if( gaussmat->precision == VIPS_PRECISION_INTEGER )
v = VIPS_RINT( 20 * v );
*VIPS_MATRIX( create->out, x, y ) = v;
@ -180,10 +191,17 @@ vips_gaussmat_class_init( VipsGaussmatClass *class )
VIPS_ARG_BOOL( class, "integer", 5,
_( "Integer" ),
_( "Generate integer Gaussian" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
G_STRUCT_OFFSET( VipsGaussmat, integer ),
FALSE );
VIPS_ARG_ENUM( class, "precision", 6,
_( "Precision" ),
_( "Generate with this precision" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsGaussmat, precision ),
VIPS_TYPE_PRECISION, VIPS_PRECISION_INTEGER );
}
static void
@ -191,6 +209,7 @@ vips_gaussmat_init( VipsGaussmat *gaussmat )
{
gaussmat->sigma = 1;
gaussmat->min_ampl = 0.1;
gaussmat->precision = VIPS_PRECISION_INTEGER;
}
/**
@ -203,7 +222,7 @@ vips_gaussmat_init( VipsGaussmat *gaussmat )
* Optional arguments:
*
* @separable: generate a separable gaussian
* @integer: generate an integer gaussian
* @precision: #VipsPrecision for @out
*
* Creates a circularly symmetric Gaussian image of radius
* @sigma. The size of the mask is determined by the variable @min_ampl;
@ -215,13 +234,13 @@ vips_gaussmat_init( VipsGaussmat *gaussmat )
* H(r) = exp( -(r * r) / (2 * @sigma * @sigma) )
*
* The generated image has odd size and its maximum value is normalised to
* 1.0, unless @integer is set.
* 1.0, unless @precision is #VIPS_PRECISION_INTEGER.
*
* If @separable is set, only the centre horizontal is generated. This is
* useful for separable convolutions.
*
* If @integer is set, an integer gaussian is generated. This is useful for
* integer convolutions.
* If @precision is #VIPS_PRECISION_INTEGER, an integer gaussian is generated.
* This is useful for integer convolutions.
*
* "scale" is set to the sum of all the mask elements.
*

View File

@ -14,6 +14,9 @@
* - gtkdoc
* 20/10/13
* - redone as a class from logmat.c
* 16/12/14
* - default to int output to match vips_conv()
* - use @precision, not @integer
*/
/*
@ -68,7 +71,8 @@ typedef struct _VipsLogmat {
double min_ampl;
gboolean separable;
gboolean integer;
gboolean integer; /* Deprecated */
VipsPrecision precision;
} VipsLogmat;
@ -95,6 +99,13 @@ vips_logmat_build( VipsObject *object )
if( VIPS_OBJECT_CLASS( vips_logmat_parent_class )->build( object ) )
return( -1 );
if( vips_object_argument_isset( object, "integer" ) )
vips_warn( class->nickname,
"'integer' is deprecated, use 'precision' instead" );
if( vips_check_precision_intfloat( class->nickname,
logmat->precision ) )
return( -1 );
/* Find the size of the mask. We want to eval the mask out to the
* flat zero part, ie. beyond the minimum and to the point where it
* comes back up towards zero.
@ -153,7 +164,7 @@ vips_logmat_build( VipsObject *object )
(2.0 - (distance / sig2)) *
exp( -distance / (2.0 * sig2) );
if( logmat->integer )
if( logmat->precision == VIPS_PRECISION_INTEGER )
v = VIPS_RINT( 20 * v );
*VIPS_MATRIX( create->out, x, y ) = v;
@ -204,10 +215,17 @@ vips_logmat_class_init( VipsLogmatClass *class )
VIPS_ARG_BOOL( class, "integer", 5,
_( "Integer" ),
_( "Generate integer Logmatian" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
G_STRUCT_OFFSET( VipsLogmat, integer ),
FALSE );
VIPS_ARG_ENUM( class, "precision", 6,
_( "Precision" ),
_( "Generate with this precision" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsLogmat, precision ),
VIPS_TYPE_PRECISION, VIPS_PRECISION_INTEGER );
}
static void
@ -215,6 +233,7 @@ vips_logmat_init( VipsLogmat *logmat )
{
logmat->sigma = 1;
logmat->min_ampl = 0.1;
logmat->precision = VIPS_PRECISION_INTEGER;
}
/**
@ -226,8 +245,8 @@ vips_logmat_init( VipsLogmat *logmat )
*
* Optional arguments:
*
* @separable: generate a separable logmatian
* @integer: generate an integer logmatian
* @separable: generate a separable mask
* @precision: #VipsPrecision for @out
*
* Creates a circularly symmetric Laplacian of Gaussian mask
* of radius
@ -246,13 +265,13 @@ vips_logmat_init( VipsLogmat *logmat )
* where s2 = @sigma * @sigma, s4 = s2 * s2, r2 = r * r.
*
* The generated mask has odd size and its maximum value is normalised to
* 1.0, unless @integer is set.
* 1.0, unless @precision is #VIPS_PRECISION_INTEGER.
*
* If @separable is set, only the centre horizontal is generated. This is
* useful for separable convolutions.
*
* If @integer is set, an integer logmatian is generated. This is useful for
* integer convolutions.
* If @precision is #VIPS_PRECISION_INTEGER, an integer mask is generated.
* This is useful for integer convolutions.
*
* "scale" is set to the sum of all the mask elements.
*

View File

@ -2169,6 +2169,7 @@ im_gauss_dmask( const char *filename, double sigma, double min_ampl )
DOUBLEMASK *msk;
if( vips_gaussmat( &t, sigma, min_ampl,
"precision", VIPS_PRECISION_FLOAT,
NULL ) )
return( NULL );
if( !(msk = im_vips2mask( t, filename )) ) {
@ -2187,6 +2188,7 @@ im_gauss_dmask_sep( const char *filename, double sigma, double min_ampl )
DOUBLEMASK *msk;
if( vips_gaussmat( &t, sigma, min_ampl,
"precision", VIPS_PRECISION_FLOAT,
"separable", TRUE,
NULL ) )
return( NULL );
@ -2205,9 +2207,7 @@ im_gauss_imask( const char *filename, double sigma, double min_ampl )
VipsImage *t;
INTMASK *msk;
if( vips_gaussmat( &t, sigma, min_ampl,
"integer", TRUE,
NULL ) )
if( vips_gaussmat( &t, sigma, min_ampl, NULL ) )
return( NULL );
if( !(msk = im_vips2imask( t, filename )) ) {
g_object_unref( t );
@ -2225,7 +2225,6 @@ im_gauss_imask_sep( const char *filename, double sigma, double min_ampl )
INTMASK *msk;
if( vips_gaussmat( &t, sigma, min_ampl,
"integer", TRUE,
"separable", TRUE,
NULL ) )
return( NULL );
@ -2244,9 +2243,7 @@ im_log_imask( const char *filename, double sigma, double min_ampl )
VipsImage *t;
INTMASK *msk;
if( vips_logmat( &t, sigma, min_ampl,
"integer", TRUE,
NULL ) )
if( vips_logmat( &t, sigma, min_ampl, NULL ) )
return( NULL );
if( !(msk = im_vips2imask( t, filename )) ) {
g_object_unref( t );
@ -2264,6 +2261,7 @@ im_log_dmask( const char *filename, double sigma, double min_ampl )
DOUBLEMASK *msk;
if( vips_logmat( &t, sigma, min_ampl,
"precision", VIPS_PRECISION_FLOAT,
NULL ) )
return( NULL );
if( !(msk = im_vips2mask( t, filename )) ) {

View File

@ -69,6 +69,7 @@ vips_scan_headers = \
${top_srcdir}/libvips/include/vips/convolution.h \
${top_srcdir}/libvips/include/vips/morphology.h \
${top_srcdir}/libvips/include/vips/draw.h \
${top_srcdir}/libvips/include/vips/basic.h \
${top_srcdir}/libvips/include/vips/object.h
enumtypes.h: $(vips_scan_headers) Makefile

View File

@ -59,6 +59,13 @@ typedef void *(*VipsSListMap4Fn)( void *item,
typedef void *(*VipsSListFold2Fn)( void *item,
void *a, void *b, void *c );
typedef enum {
VIPS_PRECISION_INTEGER,
VIPS_PRECISION_FLOAT,
VIPS_PRECISION_APPROXIMATE,
VIPS_PRECISION_LAST
} VipsPrecision;
#ifdef __cplusplus
}
#endif /*__cplusplus*/

View File

@ -38,13 +38,6 @@
extern "C" {
#endif /*__cplusplus*/
typedef enum {
VIPS_PRECISION_INTEGER,
VIPS_PRECISION_FLOAT,
VIPS_PRECISION_APPROXIMATE,
VIPS_PRECISION_LAST
} VipsPrecision;
typedef enum {
VIPS_COMBINE_MAX,
VIPS_COMBINE_SUM,

View File

@ -78,8 +78,6 @@ GType vips_pcs_get_type (void) G_GNUC_CONST;
GType vips_operation_flags_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_OPERATION_FLAGS (vips_operation_flags_get_type())
/* enumerations from "../../../libvips/include/vips/convolution.h" */
GType vips_precision_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_PRECISION (vips_precision_get_type())
GType vips_combine_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_COMBINE (vips_combine_get_type())
/* enumerations from "../../../libvips/include/vips/morphology.h" */
@ -88,6 +86,9 @@ GType vips_operation_morphology_get_type (void) G_GNUC_CONST;
/* enumerations from "../../../libvips/include/vips/draw.h" */
GType vips_combine_mode_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_COMBINE_MODE (vips_combine_mode_get_type())
/* enumerations from "../../../libvips/include/vips/basic.h" */
GType vips_precision_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_PRECISION (vips_precision_get_type())
/* enumerations from "../../../libvips/include/vips/object.h" */
GType vips_argument_flags_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_ARGUMENT_FLAGS (vips_argument_flags_get_type())

View File

@ -73,6 +73,7 @@ int vips_check_bands_1orn( const char *domain, VipsImage *im1, VipsImage *im2 );
int vips_check_bands_1orn_unary( const char *domain, VipsImage *im, int n );
int vips_check_bands_same( const char *domain, VipsImage *im1, VipsImage *im2 );
int vips_check_bandno( const char *domain, VipsImage *im, int bandno );
int vips_check_int( const char *domain, VipsImage *im );
int vips_check_uint( const char *domain, VipsImage *im );
int vips_check_uintorf( const char *domain, VipsImage *im );
@ -91,6 +92,9 @@ int vips_check_hist( const char *domain, VipsImage *im );
int vips_check_matrix( const char *domain, VipsImage *im, VipsImage **out );
int vips_check_separable( const char *domain, VipsImage *im );
int vips_check_precision_intfloat( const char *domain,
VipsPrecision precision );
#ifdef __cplusplus
}
#endif /*__cplusplus*/

View File

@ -66,6 +66,7 @@ vips_scan_headers = \
${top_srcdir}/libvips/include/vips/convolution.h \
${top_srcdir}/libvips/include/vips/morphology.h \
${top_srcdir}/libvips/include/vips/draw.h \
${top_srcdir}/libvips/include/vips/basic.h \
${top_srcdir}/libvips/include/vips/object.h
enumtypes.c: $(vips_scan_headers) Makefile

View File

@ -674,25 +674,6 @@ vips_operation_flags_get_type( void )
}
/* enumerations from "../../libvips/include/vips/convolution.h" */
GType
vips_precision_get_type( void )
{
static GType etype = 0;
if( etype == 0 ) {
static const GEnumValue values[] = {
{VIPS_PRECISION_INTEGER, "VIPS_PRECISION_INTEGER", "integer"},
{VIPS_PRECISION_FLOAT, "VIPS_PRECISION_FLOAT", "float"},
{VIPS_PRECISION_APPROXIMATE, "VIPS_PRECISION_APPROXIMATE", "approximate"},
{VIPS_PRECISION_LAST, "VIPS_PRECISION_LAST", "last"},
{0, NULL, NULL}
};
etype = g_enum_register_static( "VipsPrecision", values );
}
return( etype );
}
GType
vips_combine_get_type( void )
{
static GType etype = 0;
@ -748,6 +729,26 @@ vips_combine_mode_get_type( void )
return( etype );
}
/* enumerations from "../../libvips/include/vips/basic.h" */
GType
vips_precision_get_type( void )
{
static GType etype = 0;
if( etype == 0 ) {
static const GEnumValue values[] = {
{VIPS_PRECISION_INTEGER, "VIPS_PRECISION_INTEGER", "integer"},
{VIPS_PRECISION_FLOAT, "VIPS_PRECISION_FLOAT", "float"},
{VIPS_PRECISION_APPROXIMATE, "VIPS_PRECISION_APPROXIMATE", "approximate"},
{VIPS_PRECISION_LAST, "VIPS_PRECISION_LAST", "last"},
{0, NULL, NULL}
};
etype = g_enum_register_static( "VipsPrecision", values );
}
return( etype );
}
/* enumerations from "../../libvips/include/vips/object.h" */
GType
vips_argument_flags_get_type( void )

View File

@ -1317,3 +1317,29 @@ vips_check_separable( const char *domain, VipsImage *im )
return( 0 );
}
/**
* vips_check_precision_intfloat:
* @domain: the originating domain for the error message
* @precision: precision to check
*
* Check that @prec image is either float or int.
* If not, set an error message
* and return non-zero.
*
* See also: vips_error().
*
* Returns: 0 on OK, or -1 on error.
*/
int
vips_check_precision_intfloat( const char *domain, VipsPrecision precision )
{
if( precision != VIPS_PRECISION_INTEGER &&
precision != VIPS_PRECISION_FLOAT ) {
vips_error( domain,
"%s", _( "precision must be int or float" ) );
return( -1 );
}
return( 0 );
}