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
- ppmsave also uses "bitdepth" now, for consistency
- 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
- better iiif tile naming [IllyaMoskvin]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -46,16 +46,13 @@
#include <vips/vips.h>
#include "pcreate.h"
/* Our state.
*/
typedef struct _VipsMatrixinvert {
VipsCreate parent_instance;
VipsOperation parent_instance;
/* Input image.
*/
VipsImage *in;
VipsImage *out;
/* .. and cast to a matrix.
*/
@ -66,9 +63,9 @@ typedef struct _VipsMatrixinvert {
VipsImage *lu;
} 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
vips_matrixinvert_dispose( GObject *gobject )
@ -83,11 +80,11 @@ vips_matrixinvert_dispose( GObject *gobject )
/* 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.
*/
#define ME( m, i, j ) *VIPS_MATRIX( (m), (i), (j) )
#define ME( m, i, j ) (*VIPS_MATRIX( (m), (i), (j) ))
/**
* lu_decomp:
@ -268,149 +265,132 @@ lu_solve( VipsImage *lu, double *vec )
}
static int
vips_matrixinvert_direct( VipsImage *mat, VipsImage **out ) {
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 )
vips_matrixinvert_solve( VipsMatrixinvert *matrix )
{
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( matrix );
VipsImage *out = matrix->out;
int x, y;
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 );
int i, j;
double *vec;
if( !(matrix->lu = lu_decomp( matrix->mat ) ) )
return( -1 );
return( 0 );
}
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 )
if( !(vec = VIPS_ARRAY( matrix, matrix->lu->Xsize, double )) )
return( -1 );
for( j = 0; j < matrix->lu->Xsize; ++j ) {
for( i = 0; i < matrix->lu->Xsize; ++i )
vec[i] = 0.0;
vec[j] = 1.0;
if ( lu_solve( matrix->lu, vec ) ) {
g_free( vec );
if( lu_solve( matrix->lu, 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 );
}
for( i = 0; i < matrix->lu->Xsize; ++i )
ME( *out, i, j ) = vec[i];
ME( out, 0, 0 ) = 1.0 / det;
}
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 );
}
@ -419,19 +399,35 @@ static int
vips_matrixinvert_build( VipsObject *object )
{
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
VipsCreate *create = VIPS_CREATE( 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 );
if( vips_check_matrix( class->nickname, matrix->in, &matrix->mat ) )
return( -1 );
if( vips_matrixinvert_build_init( matrix ) ||
vips_matrixinvert_build_create( matrix, &create->out ) )
if( matrix->mat->Xsize != matrix->mat->Ysize ) {
vips_error( class->nickname, "%s", _( "non-square matrix" ) );
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 );
}
@ -455,6 +451,12 @@ vips_matrixinvert_class_init( VipsMatrixinvertClass *class )
_( "An square matrix" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
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
@ -465,7 +467,7 @@ vips_matrixinvert_init( VipsMatrixinvert *matrix )
/**
* vips_matrixinvert: (method)
* @m: matrix to invert
* @out: (out): output image
* @out: (out): output matrix
* @...: %NULL-terminated list of optional named arguments
*
* This operation calculates the inverse of the matrix represented in @m.

View File

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