fix jaggies on the edge of affine output
and add a "background" param
This commit is contained in:
parent
ef9b23b95a
commit
fcec6d639b
@ -35,6 +35,8 @@
|
||||
- add vips_fill_nearest() ... fill pixels with nearest colour
|
||||
- add VIPS_COMBINE_MIN, a new combining mode for vips_compass()
|
||||
- vips_hist_find_indexed() now has a @combine parameter
|
||||
- vips_affine() and vips_similarity() have a "background" parameter
|
||||
- fix nasty jaggies on the edge of affine output
|
||||
|
||||
29/8/17 started 8.5.9
|
||||
- make --fail stop jpeg read on any libjpeg warning, thanks @mceachen
|
||||
|
@ -162,7 +162,7 @@ void vips__region_no_ownership( struct _VipsRegion *reg );
|
||||
|
||||
typedef int (*VipsRegionFillFn)( struct _VipsRegion *, void * );
|
||||
int vips_region_fill( struct _VipsRegion *reg,
|
||||
VipsRect *r, VipsRegionFillFn fn, void *a );
|
||||
const VipsRect *r, VipsRegionFillFn fn, void *a );
|
||||
|
||||
int vips__image_wio_output( struct _VipsImage *image );
|
||||
int vips__image_pio_output( struct _VipsImage *image );
|
||||
@ -185,7 +185,7 @@ void vips_region_dump_all( void );
|
||||
*/
|
||||
int vips__init( const char *argv0 );
|
||||
size_t vips__get_sizeof_vipsobject( void );
|
||||
int vips_region_prepare_many( struct _VipsRegion **reg, VipsRect *r );
|
||||
int vips_region_prepare_many( struct _VipsRegion **reg, const VipsRect *r );
|
||||
|
||||
/* Handy for debugging.
|
||||
*/
|
||||
|
@ -104,23 +104,25 @@ GType vips_region_get_type(void);
|
||||
|
||||
VipsRegion *vips_region_new( VipsImage *image );
|
||||
|
||||
int vips_region_buffer( VipsRegion *reg, VipsRect *r );
|
||||
int vips_region_image( VipsRegion *reg, VipsRect *r );
|
||||
int vips_region_buffer( VipsRegion *reg, const VipsRect *r );
|
||||
int vips_region_image( VipsRegion *reg, const VipsRect *r );
|
||||
int vips_region_region( VipsRegion *reg, VipsRegion *dest,
|
||||
VipsRect *r, int x, int y );
|
||||
const VipsRect *r, int x, int y );
|
||||
int vips_region_equalsregion( VipsRegion *reg1, VipsRegion *reg2 );
|
||||
int vips_region_position( VipsRegion *reg, int x, int y );
|
||||
|
||||
void vips_region_paint( VipsRegion *reg, VipsRect *r, int value );
|
||||
void vips_region_paint_pel( VipsRegion *reg, VipsRect *r, VipsPel *ink );
|
||||
void vips_region_paint( VipsRegion *reg, const VipsRect *r, int value );
|
||||
void vips_region_paint_pel( VipsRegion *reg,
|
||||
const VipsRect *r, const VipsPel *ink );
|
||||
void vips_region_black( VipsRegion *reg );
|
||||
void vips_region_copy( VipsRegion *reg, VipsRegion *dest,
|
||||
VipsRect *r, int x, int y );
|
||||
int vips_region_shrink( VipsRegion *from, VipsRegion *to, VipsRect *target );
|
||||
const VipsRect *r, int x, int y );
|
||||
int vips_region_shrink( VipsRegion *from,
|
||||
VipsRegion *to, const VipsRect *target );
|
||||
|
||||
int vips_region_prepare( VipsRegion *reg, VipsRect *r );
|
||||
int vips_region_prepare( VipsRegion *reg, const VipsRect *r );
|
||||
int vips_region_prepare_to( VipsRegion *reg,
|
||||
VipsRegion *dest, VipsRect *r, int x, int y );
|
||||
VipsRegion *dest, const VipsRect *r, int x, int y );
|
||||
|
||||
void vips_region_invalidate( VipsRegion *reg );
|
||||
|
||||
|
@ -563,7 +563,7 @@ vips_region_new( VipsImage *image )
|
||||
* Returns: 0 on success, or -1 for error.
|
||||
*/
|
||||
int
|
||||
vips_region_buffer( VipsRegion *reg, VipsRect *r )
|
||||
vips_region_buffer( VipsRegion *reg, const VipsRect *r )
|
||||
{
|
||||
VipsImage *im = reg->im;
|
||||
|
||||
@ -626,14 +626,14 @@ vips_region_buffer( VipsRegion *reg, VipsRect *r )
|
||||
* @reg: region to operate upon
|
||||
* @r: #VipsRect of pixels you need to be able to address
|
||||
*
|
||||
* The region is transformed so that at least @r pixels are available to be read from
|
||||
* image. The image needs to be a memory buffer or represent a file
|
||||
* on disc that has been mapped or can be mapped.
|
||||
* The region is transformed so that at least @r pixels are available to be
|
||||
* read from the image. The image needs to be a memory buffer or represent a
|
||||
* file on disc that has been mapped or can be mapped.
|
||||
*
|
||||
* Returns: 0 on success, or -1 for error.
|
||||
*/
|
||||
int
|
||||
vips_region_image( VipsRegion *reg, VipsRect *r )
|
||||
vips_region_image( VipsRegion *reg, const VipsRect *r )
|
||||
{
|
||||
VipsImage *image = reg->im;
|
||||
|
||||
@ -725,16 +725,15 @@ vips_region_image( VipsRegion *reg, VipsRect *r )
|
||||
* Performs all clipping necessary to ensure that @reg->valid is indeed
|
||||
* valid.
|
||||
*
|
||||
* If the region we attach to is moved or destroyed, we can be left with dangling
|
||||
* pointers! If the region we attach to is on another image, the two images
|
||||
* must have
|
||||
* the same sizeof( pel ).
|
||||
* If the region we attach to is moved or destroyed, we can be left with
|
||||
* dangling pointers! If the region we attach to is on another image, the
|
||||
* two images must have the same sizeof( pel ).
|
||||
*
|
||||
* Returns: 0 on success, or -1 for error.
|
||||
*/
|
||||
int
|
||||
vips_region_region( VipsRegion *reg,
|
||||
VipsRegion *dest, VipsRect *r, int x, int y )
|
||||
VipsRegion *dest, const VipsRect *r, int x, int y )
|
||||
{
|
||||
VipsRect image;
|
||||
VipsRect wanted;
|
||||
@ -885,7 +884,8 @@ vips_region_position( VipsRegion *reg, int x, int y )
|
||||
}
|
||||
|
||||
int
|
||||
vips_region_fill( VipsRegion *reg, VipsRect *r, VipsRegionFillFn fn, void *a )
|
||||
vips_region_fill( VipsRegion *reg,
|
||||
const VipsRect *r, VipsRegionFillFn fn, void *a )
|
||||
{
|
||||
g_assert( reg->im->dtype == VIPS_IMAGE_PARTIAL );
|
||||
g_assert( reg->im->generate_fn );
|
||||
@ -947,7 +947,7 @@ vips_region_fill( VipsRegion *reg, VipsRect *r, VipsRegionFillFn fn, void *a )
|
||||
* See also: vips_region_black().
|
||||
*/
|
||||
void
|
||||
vips_region_paint( VipsRegion *reg, VipsRect *r, int value )
|
||||
vips_region_paint( VipsRegion *reg, const VipsRect *r, int value )
|
||||
{
|
||||
VipsRect clipped;
|
||||
|
||||
@ -1011,7 +1011,7 @@ vips_region_paint( VipsRegion *reg, VipsRect *r, int value )
|
||||
* See also: vips_region_paint().
|
||||
*/
|
||||
void
|
||||
vips_region_paint_pel( VipsRegion *reg, VipsRect *r, VipsPel *ink )
|
||||
vips_region_paint_pel( VipsRegion *reg, const VipsRect *r, const VipsPel *ink )
|
||||
{
|
||||
VipsRect ovl;
|
||||
|
||||
@ -1076,7 +1076,8 @@ vips_region_black( VipsRegion *reg )
|
||||
* See also: vips_region_paint().
|
||||
*/
|
||||
void
|
||||
vips_region_copy( VipsRegion *reg, VipsRegion *dest, VipsRect *r, int x, int y )
|
||||
vips_region_copy( VipsRegion *reg,
|
||||
VipsRegion *dest, const VipsRect *r, int x, int y )
|
||||
{
|
||||
int z;
|
||||
int len = VIPS_IMAGE_SIZEOF_PEL( reg->im ) * r->width;
|
||||
@ -1135,7 +1136,8 @@ vips_region_copy( VipsRegion *reg, VipsRegion *dest, VipsRect *r, int x, int y )
|
||||
* VIPS_CODING_LABQ only.
|
||||
*/
|
||||
static void
|
||||
vips_region_shrink_labpack( VipsRegion *from, VipsRegion *to, VipsRect *target )
|
||||
vips_region_shrink_labpack( VipsRegion *from,
|
||||
VipsRegion *to, const VipsRect *target )
|
||||
{
|
||||
int ls = VIPS_REGION_LSKIP( from );
|
||||
|
||||
@ -1212,7 +1214,8 @@ vips_region_shrink_labpack( VipsRegion *from, VipsRegion *to, VipsRect *target )
|
||||
/* Generate area @target in @to using pixels in @from. Non-complex.
|
||||
*/
|
||||
static void
|
||||
vips_region_shrink_uncoded( VipsRegion *from, VipsRegion *to, VipsRect *target )
|
||||
vips_region_shrink_uncoded( VipsRegion *from,
|
||||
VipsRegion *to, const VipsRect *target )
|
||||
{
|
||||
int ls = VIPS_REGION_LSKIP( from );
|
||||
int ps = VIPS_IMAGE_SIZEOF_PEL( from->im );
|
||||
@ -1295,7 +1298,8 @@ vips_region_shrink_uncoded( VipsRegion *from, VipsRegion *to, VipsRect *target )
|
||||
* last band as alpha.
|
||||
*/
|
||||
static void
|
||||
vips_region_shrink_alpha( VipsRegion *from, VipsRegion *to, VipsRect *target )
|
||||
vips_region_shrink_alpha( VipsRegion *from,
|
||||
VipsRegion *to, const VipsRect *target )
|
||||
{
|
||||
int ls = VIPS_REGION_LSKIP( from );
|
||||
int nb = from->im->Bands;
|
||||
@ -1347,7 +1351,7 @@ vips_region_shrink_alpha( VipsRegion *from, VipsRegion *to, VipsRect *target )
|
||||
* See also: vips_region_copy().
|
||||
*/
|
||||
int
|
||||
vips_region_shrink( VipsRegion *from, VipsRegion *to, VipsRect *target )
|
||||
vips_region_shrink( VipsRegion *from, VipsRegion *to, const VipsRect *target )
|
||||
{
|
||||
VipsImage *image = from->im;
|
||||
|
||||
@ -1419,7 +1423,7 @@ vips_region_generate( VipsRegion *reg )
|
||||
* Returns: 0 on success, or -1 on error.
|
||||
*/
|
||||
int
|
||||
vips_region_prepare( VipsRegion *reg, VipsRect *r )
|
||||
vips_region_prepare( VipsRegion *reg, const VipsRect *r )
|
||||
{
|
||||
VipsImage *im = reg->im;
|
||||
|
||||
@ -1492,7 +1496,7 @@ vips_region_prepare( VipsRegion *reg, VipsRect *r )
|
||||
*/
|
||||
static int
|
||||
vips_region_prepare_to_generate( VipsRegion *reg,
|
||||
VipsRegion *dest, VipsRect *r, int x, int y )
|
||||
VipsRegion *dest, const VipsRect *r, int x, int y )
|
||||
{
|
||||
VipsImage *im = reg->im;
|
||||
VipsPel *p;
|
||||
@ -1551,7 +1555,7 @@ vips_region_prepare_to_generate( VipsRegion *reg,
|
||||
*/
|
||||
int
|
||||
vips_region_prepare_to( VipsRegion *reg,
|
||||
VipsRegion *dest, VipsRect *r, int x, int y )
|
||||
VipsRegion *dest, const VipsRect *r, int x, int y )
|
||||
{
|
||||
VipsImage *im = reg->im;
|
||||
VipsRect image;
|
||||
@ -1686,7 +1690,7 @@ vips_region_prepare_to( VipsRegion *reg,
|
||||
/* Don't use this, use vips_reorder_prepare_many() instead.
|
||||
*/
|
||||
int
|
||||
vips_region_prepare_many( VipsRegion **reg, VipsRect *r )
|
||||
vips_region_prepare_many( VipsRegion **reg, const VipsRect *r )
|
||||
{
|
||||
for( ; *reg; ++reg )
|
||||
if( vips_region_prepare( *reg, r ) )
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* affine transform with a supplied interpolator.
|
||||
*
|
||||
*
|
||||
* Copyright N. Dessipris
|
||||
* Written on: 01/11/1991
|
||||
* Modified on: 12/3/92 JC
|
||||
@ -84,6 +83,9 @@
|
||||
* 1/8/14
|
||||
* - revise transform ... again
|
||||
* - see new stress test in nip2/test/extras
|
||||
* 7/11/17
|
||||
* - add "background" parameter
|
||||
* - better clipping means we have no jaggies on edges
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -116,6 +118,7 @@
|
||||
/*
|
||||
#define DEBUG_VERBOSE
|
||||
#define DEBUG
|
||||
#define VIPS_DEBUG
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
@ -149,6 +152,14 @@ typedef struct _VipsAffine {
|
||||
|
||||
VipsTransformation trn;
|
||||
|
||||
/* Background colour.
|
||||
*/
|
||||
VipsArrayDouble *background;
|
||||
|
||||
/* The [double] converted to the input image format.
|
||||
*/
|
||||
VipsPel *ink;
|
||||
|
||||
} VipsAffine;
|
||||
|
||||
typedef VipsResampleClass VipsAffineClass;
|
||||
@ -275,7 +286,7 @@ vips_affine_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
|
||||
#endif /*DEBUG_VERBOSE*/
|
||||
|
||||
if( vips_rect_isempty( &clipped ) ) {
|
||||
vips_region_black( or );
|
||||
vips_region_paint_pel( or, r, affine->ink );
|
||||
return( 0 );
|
||||
}
|
||||
if( vips_region_prepare( ir, &clipped ) )
|
||||
@ -336,9 +347,9 @@ vips_affine_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
|
||||
/* Clip against iarea.
|
||||
*/
|
||||
if( fx >= ile &&
|
||||
fx < iri &&
|
||||
fx <= iri &&
|
||||
fy >= ito &&
|
||||
fy < ibo ) {
|
||||
fy <= ibo ) {
|
||||
/* Verify that we can read the whole stencil.
|
||||
* With DEBUG on this will range-check.
|
||||
*/
|
||||
@ -355,8 +366,10 @@ vips_affine_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
|
||||
q, ir, ix, iy );
|
||||
}
|
||||
else {
|
||||
/* Out of range: paint the background.
|
||||
*/
|
||||
for( z = 0; z < ps; z++ )
|
||||
q[z] = 0;
|
||||
q[z] = affine->ink[z];
|
||||
}
|
||||
|
||||
ix += ddx;
|
||||
@ -478,16 +491,36 @@ vips_affine_build( VipsObject *object )
|
||||
return( -1 );
|
||||
in = t[0];
|
||||
|
||||
/* Convert the background to the image's format.
|
||||
*/
|
||||
if( !(affine->ink = vips__vector_to_ink( class->nickname,
|
||||
resample->out,
|
||||
VIPS_AREA( affine->background )->data, NULL,
|
||||
VIPS_AREA( affine->background )->n )) )
|
||||
return( -1 );
|
||||
|
||||
/* Add new pixels around the input so we can interpolate at the edges.
|
||||
*
|
||||
* We add the interpolate stencil, plus one extra pixel on all the
|
||||
* edges. This means when we clip in generate (above) we can be sure
|
||||
* we clip outside the real pixels and don't get jaggies on edges.
|
||||
*/
|
||||
if( vips_embed( in, &t[2],
|
||||
window_offset, window_offset,
|
||||
in->Xsize + window_size - 1, in->Ysize + window_size - 1,
|
||||
"extend", VIPS_EXTEND_COPY,
|
||||
window_offset + 1, window_offset + 1,
|
||||
in->Xsize + window_size - 1 + 2,
|
||||
in->Ysize + window_size - 1 + 2,
|
||||
"extend", VIPS_EXTEND_BACKGROUND,
|
||||
"background", affine->background,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
in = t[2];
|
||||
|
||||
/* We've added a one-pixel border to the input: displace the transform
|
||||
* to compensate.
|
||||
*/
|
||||
affine->trn.idx -= 1;
|
||||
affine->trn.idy -= 1;
|
||||
|
||||
/* Normally SMALLTILE ... except if this is strictly a size
|
||||
* up/down affine.
|
||||
*/
|
||||
@ -591,11 +624,19 @@ vips_affine_class_init( VipsAffineClass *class )
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsAffine, idy ),
|
||||
-10000000, 10000000, 0 );
|
||||
|
||||
VIPS_ARG_BOXED( class, "background", 2,
|
||||
_( "Background" ),
|
||||
_( "Background value" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsAffine, background ),
|
||||
VIPS_TYPE_ARRAY_DOUBLE );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_affine_init( VipsAffine *affine )
|
||||
{
|
||||
affine->background = vips_array_double_newv( 1, 0.0 );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -616,6 +657,7 @@ vips_affine_init( VipsAffine *affine )
|
||||
* * @idy: %gdouble, input vertical offset
|
||||
* * @odx: %gdouble, output horizontal offset
|
||||
* * @ody: %gdouble, output vertical offset
|
||||
* * @background: #VipsArrayDouble colour for new pixels
|
||||
*
|
||||
* This operator performs an affine transform on an image using @interpolate.
|
||||
*
|
||||
@ -633,6 +675,8 @@ vips_affine_init( VipsAffine *affine )
|
||||
* By default @oarea is just large enough to cover the whole of the
|
||||
* transformed input image.
|
||||
*
|
||||
* New pixels are filled with @background. This defaults to zero (black).
|
||||
*
|
||||
* @interpolate defaults to bilinear.
|
||||
*
|
||||
* @idx, @idy, @odx, @ody default to zero.
|
||||
|
@ -10,6 +10,9 @@
|
||||
* - oops, missing scale from b, thanks Topochicho
|
||||
* 7/2/16
|
||||
* - use vips_reduce(), if we can
|
||||
* 17/11/17
|
||||
* ` - add optional "background" param
|
||||
* ` - don't use vips_reduce() since it has no "background" param
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -65,6 +68,7 @@ typedef struct _VipsSimilarity {
|
||||
double ody;
|
||||
double idx;
|
||||
double idy;
|
||||
VipsArrayDouble *background;
|
||||
|
||||
} VipsSimilarity;
|
||||
|
||||
@ -72,19 +76,6 @@ typedef VipsResampleClass VipsSimilarityClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsSimilarity, vips_similarity, VIPS_TYPE_RESAMPLE );
|
||||
|
||||
/* Map interpolator names to vips kernels.
|
||||
*/
|
||||
typedef struct _VipsInterpolateKernel {
|
||||
const char *nickname;
|
||||
VipsKernel kernel;
|
||||
} VipsInterpolateKernel;
|
||||
|
||||
static VipsInterpolateKernel vips_similarity_kernel[] = {
|
||||
{ "bicubic", VIPS_KERNEL_CUBIC },
|
||||
{ "bilinear", VIPS_KERNEL_LINEAR },
|
||||
{ "nearest", VIPS_KERNEL_NEAREST }
|
||||
};
|
||||
|
||||
static int
|
||||
vips_similarity_build( VipsObject *object )
|
||||
{
|
||||
@ -92,61 +83,23 @@ vips_similarity_build( VipsObject *object )
|
||||
VipsSimilarity *similarity = (VipsSimilarity *) object;
|
||||
VipsImage **t = (VipsImage **)
|
||||
vips_object_local_array( object, 4 );
|
||||
|
||||
gboolean handled;
|
||||
double a = similarity->scale * cos( VIPS_RAD( similarity->angle ) );
|
||||
double b = similarity->scale * -sin( VIPS_RAD( similarity->angle ) );
|
||||
double c = -b;
|
||||
double d = a;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_similarity_parent_class )->build( object ) )
|
||||
return( -1 );
|
||||
|
||||
handled = FALSE;
|
||||
|
||||
/* Use vips_reduce(), if we can.
|
||||
*/
|
||||
if( similarity->interpolate &&
|
||||
similarity->angle == 0.0 &&
|
||||
similarity->idx == 0.0 &&
|
||||
similarity->idy == 0.0 &&
|
||||
similarity->odx == 0.0 &&
|
||||
similarity->ody == 0.0 ) {
|
||||
const char *nickname = VIPS_OBJECT_GET_CLASS(
|
||||
similarity->interpolate )->nickname;
|
||||
|
||||
int i;
|
||||
|
||||
for( i = 0; i < VIPS_NUMBER( vips_similarity_kernel ); i++ ) {
|
||||
VipsInterpolateKernel *ik = &vips_similarity_kernel[i];
|
||||
|
||||
if( strcmp( nickname, ik->nickname ) == 0 ) {
|
||||
if( vips_reduce( resample->in, &t[0],
|
||||
1.0 / similarity->scale,
|
||||
1.0 / similarity->scale,
|
||||
"kernel", ik->kernel,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
|
||||
handled = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !handled ) {
|
||||
double a = similarity->scale *
|
||||
cos( VIPS_RAD( similarity->angle ) );
|
||||
double b = similarity->scale *
|
||||
-sin( VIPS_RAD( similarity->angle ) );
|
||||
double c = -b;
|
||||
double d = a;
|
||||
|
||||
if( vips_affine( resample->in, &t[0], a, b, c, d,
|
||||
"interpolate", similarity->interpolate,
|
||||
"odx", similarity->odx,
|
||||
"ody", similarity->ody,
|
||||
"idx", similarity->idx,
|
||||
"idy", similarity->idy,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
}
|
||||
if( vips_affine( resample->in, &t[0], a, b, c, d,
|
||||
"interpolate", similarity->interpolate,
|
||||
"odx", similarity->odx,
|
||||
"ody", similarity->ody,
|
||||
"idx", similarity->idx,
|
||||
"idy", similarity->idy,
|
||||
"background", similarity->background,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_write( t[0], resample->out ) )
|
||||
return( -1 );
|
||||
@ -214,6 +167,13 @@ vips_similarity_class_init( VipsSimilarityClass *class )
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsSimilarity, idy ),
|
||||
-10000000, 10000000, 0 );
|
||||
|
||||
VIPS_ARG_BOXED( class, "background", 2,
|
||||
_( "Background" ),
|
||||
_( "Background value" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsSimilarity, background ),
|
||||
VIPS_TYPE_ARRAY_DOUBLE );
|
||||
}
|
||||
|
||||
static void
|
||||
@ -226,6 +186,7 @@ vips_similarity_init( VipsSimilarity *similarity )
|
||||
similarity->ody = 0;
|
||||
similarity->idx = 0;
|
||||
similarity->idy = 0;
|
||||
similarity->background = vips_array_double_newv( 1, 0.0 );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -243,6 +204,8 @@ vips_similarity_init( VipsSimilarity *similarity )
|
||||
* * @idy: %gdouble, input vertical offset
|
||||
* * @odx: %gdouble, output horizontal offset
|
||||
* * @ody: %gdouble, output vertical offset
|
||||
* * @ody: %gdouble, output vertical offset
|
||||
* * @background: #VipsArrayDouble colour for new pixels
|
||||
*
|
||||
* This operator calls vips_affine() for you, calculating the matrix for the
|
||||
* affine transform from @scale and @angle. Other parameters are passed on to
|
||||
|
Loading…
Reference in New Issue
Block a user