small cleanups for disable deprecated

- move matrixinvert to mosaicing, fix a leak
- add note to changelog
- small fixes

see https://github.com/libvips/libvips/pull/1593
This commit is contained in:
John Cupitt 2020-06-28 12:14:13 +01:00
parent e3a500204a
commit 5540fa97f4
10 changed files with 163 additions and 159 deletions

View File

@ -37,6 +37,8 @@
- pngsave @bitdepth parameter lets you write 1, 2 and 4 bit PNGs - pngsave @bitdepth parameter lets you write 1, 2 and 4 bit PNGs
- ppmsave also uses "bitdepth" now, for consistency - ppmsave also uses "bitdepth" now, for consistency
- reduce operation cache max to 100 - reduce operation cache max to 100
- rework the final bits of vips7 for vips8 [kleisauke]
- --disable-deprecated now works [kleisauke]
24/4/20 started 8.9.3 24/4/20 started 8.9.3
- better iiif tile naming [IllyaMoskvin] - better iiif tile naming [IllyaMoskvin]

View File

@ -24,8 +24,7 @@ SUBDIRS = \
iofuncs \ iofuncs \
morphology \ morphology \
mosaicing \ mosaicing \
create \ create
.
lib_LTLIBRARIES = libvips.la lib_LTLIBRARIES = libvips.la

View File

@ -25,7 +25,6 @@ libcreate_la_SOURCES = \
mask_gaussian_ring.c \ mask_gaussian_ring.c \
mask_gaussian_band.c \ mask_gaussian_band.c \
mask_fractal.c \ mask_fractal.c \
matrixinvert.c \
fractsurf.c \ fractsurf.c \
eye.c \ eye.c \
grey.c \ grey.c \

View File

@ -110,9 +110,6 @@ int vips_mask_fractal( VipsImage **out, int width, int height,
double fractal_dimension, ... ) double fractal_dimension, ... )
__attribute__((sentinel)); __attribute__((sentinel));
int vips_matrixinvert( VipsImage *m, VipsImage **out, ... )
__attribute__((sentinel));
int vips_fractsurf( VipsImage **out, int vips_fractsurf( VipsImage **out,
int width, int height, double fractal_dimension, ... ) int width, int height, double fractal_dimension, ... )
__attribute__((sentinel)); __attribute__((sentinel));

View File

@ -92,6 +92,9 @@ int vips_remosaic( VipsImage *in, VipsImage **out,
const char *old_str, const char *new_str, ... ) const char *old_str, const char *new_str, ... )
__attribute__((sentinel)); __attribute__((sentinel));
int vips_matrixinvert( VipsImage *m, VipsImage **out, ... )
__attribute__((sentinel));
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -192,7 +192,6 @@ vips_morph_start( VipsImage *out, void *a, void *b )
{ {
VipsImage *in = (VipsImage *) a; VipsImage *in = (VipsImage *) a;
VipsMorph *morph = (VipsMorph *) b; VipsMorph *morph = (VipsMorph *) b;
VipsImage *M = morph->M;
VipsMorphSequence *seq; VipsMorphSequence *seq;
@ -227,8 +226,10 @@ vips_morph_start( VipsImage *out, void *a, void *b )
/* Vector mode. /* Vector mode.
*/ */
if( morph->n_pass ) { if( morph->n_pass ) {
seq->t1 = VIPS_ARRAY( NULL, VIPS_IMAGE_N_ELEMENTS( in ), VipsPel ); seq->t1 = VIPS_ARRAY( NULL,
seq->t2 = VIPS_ARRAY( NULL, VIPS_IMAGE_N_ELEMENTS( in ), VipsPel ); VIPS_IMAGE_N_ELEMENTS( in ), VipsPel );
seq->t2 = VIPS_ARRAY( NULL,
VIPS_IMAGE_N_ELEMENTS( in ), VipsPel );
if( !seq->t1 || if( !seq->t1 ||
!seq->t2 ) { !seq->t2 ) {
@ -628,7 +629,6 @@ vips_morph_gen_vector( VipsRegion *or,
VipsMorphSequence *seq = (VipsMorphSequence *) vseq; VipsMorphSequence *seq = (VipsMorphSequence *) vseq;
VipsMorph *morph = (VipsMorph *) b; VipsMorph *morph = (VipsMorph *) b;
VipsImage *M = morph->M; VipsImage *M = morph->M;
VipsImage *in = (VipsImage *) a;
VipsRegion *ir = seq->ir; VipsRegion *ir = seq->ir;
VipsRect *r = &or->valid; VipsRect *r = &or->valid;
int sz = VIPS_REGION_N_ELEMENTS( or ); int sz = VIPS_REGION_N_ELEMENTS( or );

View File

@ -6,6 +6,7 @@ libmosaicing_la_SOURCES = \
mosaic.c \ mosaic.c \
match.c \ match.c \
mosaic1.c \ mosaic1.c \
matrixinvert.c \
global_balance.c \ global_balance.c \
im_avgdxdy.c \ im_avgdxdy.c \
im_chkpair.c \ im_chkpair.c \

View File

@ -1483,7 +1483,7 @@ vips__build_mosaic( SymbolTable *st, VipsImage *out, transform_fn tfn, void *a )
} }
static int static int
vips__transposematrix( VipsImage *in, VipsImage **out ) vips__matrixtranspose( VipsImage *in, VipsImage **out )
{ {
int yc, xc; int yc, xc;
@ -1502,7 +1502,7 @@ vips__transposematrix( VipsImage *in, VipsImage **out )
} }
static int static int
vips__multiplymatrix( VipsImage *in1, VipsImage *in2, VipsImage **out ) vips__matrixmultiply( VipsImage *in1, VipsImage *in2, VipsImage **out )
{ {
int xc, yc, col; int xc, yc, col;
double sum; double sum;
@ -1512,7 +1512,7 @@ vips__multiplymatrix( VipsImage *in1, VipsImage *in2, VipsImage **out )
/* Check matrix sizes. /* Check matrix sizes.
*/ */
if( in1->Xsize != in2->Ysize ) { if( in1->Xsize != in2->Ysize ) {
vips_error( "vips__multiplymatrix", "%s", _( "bad sizes" ) ); vips_error( "vips__matrixmultiply", "%s", _( "bad sizes" ) );
return( -1 ); return( -1 );
} }
@ -1577,11 +1577,11 @@ find_factors( SymbolTable *st, double gamma )
/* Calculate LMS. /* Calculate LMS.
*/ */
if( vips__transposematrix( t[1], &t[2] ) || if( vips__matrixtranspose( t[1], &t[2] ) ||
vips__multiplymatrix( t[2], t[1], &t[3] ) || vips__matrixmultiply( t[2], t[1], &t[3] ) ||
vips_matrixinvert( t[3], &t[4], NULL ) || vips_matrixinvert( t[3], &t[4], NULL ) ||
vips__multiplymatrix( t[4], t[2], &t[5] ) || vips__matrixmultiply( t[4], t[2], &t[5] ) ||
vips__multiplymatrix( t[5], t[0], &t[6] ) ) vips__matrixmultiply( t[5], t[0], &t[6] ) )
return( -1 ); return( -1 );
/* Make array of correction factors. /* Make array of correction factors.

View File

@ -46,16 +46,13 @@
#include <vips/vips.h> #include <vips/vips.h>
#include "pcreate.h"
/* Our state. /* Our state.
*/ */
typedef struct _VipsMatrixinvert { typedef struct _VipsMatrixinvert {
VipsCreate parent_instance; VipsOperation parent_instance;
/* Input image.
*/
VipsImage *in; VipsImage *in;
VipsImage *out;
/* .. and cast to a matrix. /* .. and cast to a matrix.
*/ */
@ -66,9 +63,9 @@ typedef struct _VipsMatrixinvert {
VipsImage *lu; VipsImage *lu;
} VipsMatrixinvert; } VipsMatrixinvert;
typedef VipsCreateClass VipsMatrixinvertClass; typedef VipsOperationClass VipsMatrixinvertClass;
G_DEFINE_TYPE( VipsMatrixinvert, vips_matrixinvert, VIPS_TYPE_CREATE ); G_DEFINE_TYPE( VipsMatrixinvert, vips_matrixinvert, VIPS_TYPE_OPERATION );
static void static void
vips_matrixinvert_dispose( GObject *gobject ) vips_matrixinvert_dispose( GObject *gobject )
@ -83,11 +80,11 @@ vips_matrixinvert_dispose( GObject *gobject )
/* DBL_MIN is smallest *normalized* double precision float /* DBL_MIN is smallest *normalized* double precision float
*/ */
#define TOO_SMALL 2.0 * DBL_MIN #define TOO_SMALL (2.0 * DBL_MIN)
/* Save a bit of typing. /* Save a bit of typing.
*/ */
#define ME( m, i, j ) *VIPS_MATRIX( (m), (i), (j) ) #define ME( m, i, j ) (*VIPS_MATRIX( (m), (i), (j) ))
/** /**
* lu_decomp: * lu_decomp:
@ -268,149 +265,132 @@ lu_solve( VipsImage *lu, double *vec )
} }
static int static int
vips_matrixinvert_direct( VipsImage *mat, VipsImage **out ) { vips_matrixinvert_solve( VipsMatrixinvert *matrix )
switch( mat->Xsize ) {
case 1: {
double det = ME( mat, 0, 0 );
if( fabs( det ) < TOO_SMALL ) {
/* divisor is near zero */
vips_error( "matrixinvert",
"%s", _( "singular or near-singular matrix" ) );
return( -1 );
}
ME( *out, 0, 0 ) = 1.0 / det;
return( 0 );
}
case 2: {
double det = ME( mat, 0, 0 ) * ME( mat, 1, 1 ) -
ME( mat, 0, 1 ) * ME( mat, 1, 0 );
if( fabs( det ) < TOO_SMALL ) {
/* divisor is near zero */
vips_error( "matrixinvert",
"%s", _( "singular or near-singular matrix" ) );
return( -1 );
}
double tmp = 1.0 / det;
ME( *out, 0, 0 ) = tmp * ME( mat, 1, 1 );
ME( *out, 0, 1 ) = -tmp * ME( mat, 0, 1 );
ME( *out, 1, 0 ) = -tmp * ME( mat, 1, 0 );
ME( *out, 1, 1 ) = tmp * ME( mat, 0, 0 );
return( 0 );
}
case 3: {
double det = ME( mat, 0, 0 ) * ( ME( mat, 1, 1 ) *
ME( mat, 2, 2 ) - ME( mat, 1, 2 ) * ME( mat, 2, 1 ) );
det -= ME( mat, 0, 1 ) * ( ME( mat, 1, 0 ) *
ME( mat, 2, 2 ) - ME( mat, 1, 2 ) * ME( mat, 2, 0) );
det += ME( mat, 0, 2) * ( ME( mat, 1, 0 ) *
ME( mat, 2, 1 ) - ME( mat, 1, 1 ) * ME( mat, 2, 0 ) );
if( fabs( det ) < TOO_SMALL ) {
/* divisor is near zero */
vips_error( "matrixinvert",
"%s", _( "singular or near-singular matrix" ) );
return( -1 );
}
double tmp = 1.0 / det;
ME( *out, 0, 0 ) = tmp * ( ME( mat, 1, 1 ) * ME( mat, 2, 2 ) -
ME( mat, 1, 2 ) * ME( mat, 2, 1 ) );
ME( *out, 1, 0 ) = tmp * ( ME( mat, 1, 2 ) * ME( mat, 2, 0 ) -
ME( mat, 1, 0 ) * ME( mat, 2, 2 ) );
ME( *out, 2, 0 ) = tmp * ( ME( mat, 1, 0 ) * ME( mat, 2, 1 ) -
ME( mat, 1, 1 ) * ME( mat, 2, 0 ) );
ME( *out, 0, 1 ) = tmp * ( ME( mat, 0, 2 ) * ME( mat, 2, 1 ) -
ME( mat, 0, 1 ) * ME( mat, 2, 2 ) );
ME( *out, 1, 1 ) = tmp * ( ME( mat, 0, 0 ) * ME( mat, 2, 2 ) -
ME( mat, 0, 2 ) * ME( mat, 2, 0 ) );
ME( *out, 2, 1 ) = tmp * ( ME( mat, 0, 1 ) * ME( mat, 2, 0 ) -
ME( mat, 0, 0 ) * ME( mat, 2, 1 ) );
ME( *out, 0, 2 ) = tmp * ( ME( mat, 0, 1 ) * ME( mat, 1, 2 ) -
ME( mat, 0, 2 ) * ME( mat, 1, 1 ) );
ME( *out, 1, 2 ) = tmp * ( ME( mat, 0, 2 ) * ME( mat, 1, 0 ) -
ME( mat, 0, 0 ) * ME( mat, 1, 2 ) );
ME( *out, 2, 2 ) = tmp * ( ME( mat, 0, 0 ) * ME( mat, 1, 1 ) -
ME( mat, 0, 1 ) * ME( mat, 1, 0 ) );
return( 0 );
}
/* TODO(kleisauke):
* We sometimes use 4x4 matrices, could we also make a
* direct version for those? For e.g.:
* https://stackoverflow.com/a/1148405/10952119 */
default:
return( -1 );
}
}
static int
vips_matrixinvert_build_init( VipsMatrixinvert *matrix )
{ {
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( matrix ); VipsImage *out = matrix->out;
int x, y; int i, j;
double *vec;
if( !matrix->mat ||
matrix->mat->Xsize != matrix->mat->Ysize ) {
vips_error( class->nickname, "%s", _( "non-square matrix" ) );
return( -1 );
}
/* No need to LU decompose the matrix for < 4x4 matrices
*/
if( matrix->mat->Xsize < 4 )
return( 0 );
if( !(matrix->lu = lu_decomp( matrix->mat ) ) ) if( !(matrix->lu = lu_decomp( matrix->mat ) ) )
return( -1 ); return( -1 );
return( 0 ); if( !(vec = VIPS_ARRAY( matrix, matrix->lu->Xsize, double )) )
}
static int
vips_matrixinvert_build_create( VipsMatrixinvert *matrix, VipsImage **out )
{
int i, j;
double *vec;
*out = vips_image_new_matrix( matrix->mat->Xsize, matrix->mat->Ysize );
/* Direct path for < 4x4 matrices
*/
if( matrix->mat->Xsize < 4 )
return( vips_matrixinvert_direct( matrix->mat, out ) );
vec = VIPS_ARRAY( NULL, matrix->lu->Xsize, double );
if( !vec )
return( -1 ); return( -1 );
for( j = 0; j < matrix->lu->Xsize; ++j ) { for( j = 0; j < matrix->lu->Xsize; ++j ) {
for( i = 0; i < matrix->lu->Xsize; ++i ) for( i = 0; i < matrix->lu->Xsize; ++i )
vec[i] = 0.0; vec[i] = 0.0;
vec[j] = 1.0; vec[j] = 1.0;
if ( lu_solve( matrix->lu, vec ) ) { if( lu_solve( matrix->lu, vec ) )
g_free( vec ); return( -1 );
for( i = 0; i < matrix->lu->Xsize; ++i )
ME( out, i, j ) = vec[i];
}
return( 0 );
}
static int
vips_matrixinvert_direct( VipsMatrixinvert *matrix )
{
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( matrix );
VipsImage *in = matrix->mat;
VipsImage *out = matrix->out;
switch( matrix->mat->Xsize ) {
case 1:
{
double det = ME( in, 0, 0 );
if( fabs( det ) < TOO_SMALL ) {
/* divisor is near zero */
vips_error( class->nickname,
"%s", _( "singular or near-singular matrix" ) );
return( -1 ); return( -1 );
} }
for( i = 0; i < matrix->lu->Xsize; ++i ) ME( out, 0, 0 ) = 1.0 / det;
ME( *out, i, j ) = vec[i]; }
break;
case 2:
{
double det = ME( in, 0, 0 ) * ME( in, 1, 1 ) -
ME( in, 0, 1 ) * ME( in, 1, 0 );
double tmp;
if( fabs( det ) < TOO_SMALL ) {
/* divisor is near zero */
vips_error( class->nickname,
"%s", _( "singular or near-singular matrix" ) );
return( -1 );
}
tmp = 1.0 / det;
ME( out, 0, 0 ) = tmp * ME( in, 1, 1 );
ME( out, 0, 1 ) = -tmp * ME( in, 0, 1 );
ME( out, 1, 0 ) = -tmp * ME( in, 1, 0 );
ME( out, 1, 1 ) = tmp * ME( in, 0, 0 );
}
break;
case 3:
{
double det;
double tmp;
det = ME( in, 0, 0 ) * ( ME( in, 1, 1 ) *
ME( in, 2, 2 ) - ME( in, 1, 2 ) * ME( in, 2, 1 ) );
det -= ME( in, 0, 1 ) * ( ME( in, 1, 0 ) *
ME( in, 2, 2 ) - ME( in, 1, 2 ) * ME( in, 2, 0) );
det += ME( in, 0, 2) * ( ME( in, 1, 0 ) *
ME( in, 2, 1 ) - ME( in, 1, 1 ) * ME( in, 2, 0 ) );
if( fabs( det ) < TOO_SMALL ) {
/* divisor is near zero */
vips_error( class->nickname,
"%s", _( "singular or near-singular matrix" ) );
return( -1 );
}
tmp = 1.0 / det;
ME( out, 0, 0 ) = tmp * ( ME( in, 1, 1 ) * ME( in, 2, 2 ) -
ME( in, 1, 2 ) * ME( in, 2, 1 ) );
ME( out, 1, 0 ) = tmp * ( ME( in, 1, 2 ) * ME( in, 2, 0 ) -
ME( in, 1, 0 ) * ME( in, 2, 2 ) );
ME( out, 2, 0 ) = tmp * ( ME( in, 1, 0 ) * ME( in, 2, 1 ) -
ME( in, 1, 1 ) * ME( in, 2, 0 ) );
ME( out, 0, 1 ) = tmp * ( ME( in, 0, 2 ) * ME( in, 2, 1 ) -
ME( in, 0, 1 ) * ME( in, 2, 2 ) );
ME( out, 1, 1 ) = tmp * ( ME( in, 0, 0 ) * ME( in, 2, 2 ) -
ME( in, 0, 2 ) * ME( in, 2, 0 ) );
ME( out, 2, 1 ) = tmp * ( ME( in, 0, 1 ) * ME( in, 2, 0 ) -
ME( in, 0, 0 ) * ME( in, 2, 1 ) );
ME( out, 0, 2 ) = tmp * ( ME( in, 0, 1 ) * ME( in, 1, 2 ) -
ME( in, 0, 2 ) * ME( in, 1, 1 ) );
ME( out, 1, 2 ) = tmp * ( ME( in, 0, 2 ) * ME( in, 1, 0 ) -
ME( in, 0, 0 ) * ME( in, 1, 2 ) );
ME( out, 2, 2 ) = tmp * ( ME( in, 0, 0 ) * ME( in, 1, 1 ) -
ME( in, 0, 1 ) * ME( in, 1, 0 ) );
}
break;
/* TODO(kleisauke):
* We sometimes use 4x4 matrices, could we also make a
* direct version for those? For e.g.:
* https://stackoverflow.com/a/1148405/10952119 */
default:
g_assert( 0 );
return( -1 );
} }
g_free( vec );
return( 0 ); return( 0 );
} }
@ -419,19 +399,35 @@ static int
vips_matrixinvert_build( VipsObject *object ) vips_matrixinvert_build( VipsObject *object )
{ {
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
VipsCreate *create = VIPS_CREATE( object );
VipsMatrixinvert *matrix = (VipsMatrixinvert *) object; VipsMatrixinvert *matrix = (VipsMatrixinvert *) object;
VipsImage **t = (VipsImage **) vips_object_local_array( object, 1 );
if( VIPS_OBJECT_CLASS( vips_matrixinvert_parent_class )->build( object ) ) if( VIPS_OBJECT_CLASS( vips_matrixinvert_parent_class )->
build( object ) )
return( -1 ); return( -1 );
if( vips_check_matrix( class->nickname, matrix->in, &matrix->mat ) ) if( vips_check_matrix( class->nickname, matrix->in, &matrix->mat ) )
return( -1 ); return( -1 );
if( vips_matrixinvert_build_init( matrix ) || if( matrix->mat->Xsize != matrix->mat->Ysize ) {
vips_matrixinvert_build_create( matrix, &create->out ) ) vips_error( class->nickname, "%s", _( "non-square matrix" ) );
return( -1 ); return( -1 );
}
g_object_set( matrix,
"out", vips_image_new_matrix( matrix->mat->Xsize,
matrix->mat->Ysize ),
NULL );
/* Direct path for < 4x4 matrices
*/
if( matrix->mat->Xsize >= 4 ) {
if( vips_matrixinvert_solve( matrix ) )
return( -1 );
}
else {
if( vips_matrixinvert_direct( matrix ) )
return( -1 );
}
return( 0 ); return( 0 );
} }
@ -455,6 +451,12 @@ vips_matrixinvert_class_init( VipsMatrixinvertClass *class )
_( "An square matrix" ), _( "An square matrix" ),
VIPS_ARGUMENT_REQUIRED_INPUT, VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsMatrixinvert, in ) ); G_STRUCT_OFFSET( VipsMatrixinvert, in ) );
VIPS_ARG_IMAGE( class, "out", 1,
_( "Output" ),
_( "Output matrix" ),
VIPS_ARGUMENT_REQUIRED_OUTPUT,
G_STRUCT_OFFSET( VipsMatrixinvert, out ) );
} }
static void static void
@ -465,7 +467,7 @@ vips_matrixinvert_init( VipsMatrixinvert *matrix )
/** /**
* vips_matrixinvert: (method) * vips_matrixinvert: (method)
* @m: matrix to invert * @m: matrix to invert
* @out: (out): output image * @out: (out): output matrix
* @...: %NULL-terminated list of optional named arguments * @...: %NULL-terminated list of optional named arguments
* *
* This operation calculates the inverse of the matrix represented in @m. * This operation calculates the inverse of the matrix represented in @m.

View File

@ -43,8 +43,9 @@
#include <vips/internal.h> #include <vips/internal.h>
#include <vips/transform.h> #include <vips/transform.h>
/* DBL_MIN is smallest *normalized* double precision float */ /* DBL_MIN is smallest *normalized* double precision float
#define TOO_SMALL 2.0 * DBL_MIN */
#define TOO_SMALL (2.0 * DBL_MIN)
/* Calculate the inverse transformation. /* Calculate the inverse transformation.
*/ */