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:
parent
e3a500204a
commit
5540fa97f4
@ -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]
|
||||||
|
@ -24,8 +24,7 @@ SUBDIRS = \
|
|||||||
iofuncs \
|
iofuncs \
|
||||||
morphology \
|
morphology \
|
||||||
mosaicing \
|
mosaicing \
|
||||||
create \
|
create
|
||||||
.
|
|
||||||
|
|
||||||
lib_LTLIBRARIES = libvips.la
|
lib_LTLIBRARIES = libvips.la
|
||||||
|
|
||||||
|
@ -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 \
|
||||||
|
@ -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));
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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 );
|
||||||
|
@ -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 \
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user