make linear and cubic adaptive
This commit is contained in:
parent
cfa96f735a
commit
68ed42e2fa
|
@ -28,6 +28,7 @@
|
||||||
- vips_image_write() severs all links between images, when it can ... thanks
|
- vips_image_write() severs all links between images, when it can ... thanks
|
||||||
Warren and Nakilon
|
Warren and Nakilon
|
||||||
- vector path for convolution is more accurate and can handle larger masks
|
- vector path for convolution is more accurate and can handle larger masks
|
||||||
|
- linear and cubic kernels for reduce are higer quality
|
||||||
|
|
||||||
29/8/17 started 8.5.9
|
29/8/17 started 8.5.9
|
||||||
- make --fail stop jpeg read on any libjpeg warning, thanks @mceachen
|
- make --fail stop jpeg read on any libjpeg warning, thanks @mceachen
|
||||||
|
|
7
TODO
7
TODO
|
@ -1,9 +1,4 @@
|
||||||
- vips_image_write() to a temp file is rather broken
|
- rewind should break more things ... does it remove upsteam/downstream? does it
|
||||||
|
|
||||||
things like reorder and upstream/downstream will still be keeping links after
|
|
||||||
write, so unreffing the input will eventually trigger a crash
|
|
||||||
|
|
||||||
rewind should break more things ... does it remove upsteam/downstream? does it
|
|
||||||
just need to remove reorder links?
|
just need to remove reorder links?
|
||||||
|
|
||||||
perhaps reorder should use upstream/downstream, then it will be broken anyway
|
perhaps reorder should use upstream/downstream, then it will be broken anyway
|
||||||
|
|
|
@ -57,14 +57,12 @@
|
||||||
/**
|
/**
|
||||||
* VipsKernel:
|
* VipsKernel:
|
||||||
* @VIPS_KERNEL_NEAREST: The nearest pixel to the point.
|
* @VIPS_KERNEL_NEAREST: The nearest pixel to the point.
|
||||||
* @VIPS_KERNEL_LINEAR: Calculate a pixel value using linear interpolation.
|
* @VIPS_KERNEL_LINEAR: Convolve with a triangle filter.
|
||||||
* @VIPS_KERNEL_CUBIC: Calculate using a 4-element cubic kernel.
|
* @VIPS_KERNEL_CUBIC: Convolve with a cubic filter.
|
||||||
* @VIPS_KERNEL_LANCZOS2: Calculate with a two-lobe Lanczos kernel.
|
* @VIPS_KERNEL_LANCZOS2: Convolve with a two-lobe Lanczos kernel.
|
||||||
* @VIPS_KERNEL_LANCZOS3: Calculate with a three-lobe Lanczos kernel.
|
* @VIPS_KERNEL_LANCZOS3: Convolve with a three-lobe Lanczos kernel.
|
||||||
*
|
*
|
||||||
* The resampling kernels vips supports. See vips_reduce(), for example.
|
* The resampling kernels vips supports. See vips_reduce(), for example.
|
||||||
*
|
|
||||||
* The Lanczos kernels vary in size with the downsampling ratio.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct _VipsReduce {
|
typedef struct _VipsReduce {
|
||||||
|
|
|
@ -101,10 +101,10 @@ vips_reduce_get_points( VipsKernel kernel, double shrink )
|
||||||
return( 1 );
|
return( 1 );
|
||||||
|
|
||||||
case VIPS_KERNEL_LINEAR:
|
case VIPS_KERNEL_LINEAR:
|
||||||
return( 2 );
|
return( rint( 2 * shrink ) + 1 );
|
||||||
|
|
||||||
case VIPS_KERNEL_CUBIC:
|
case VIPS_KERNEL_CUBIC:
|
||||||
return( 4 );
|
return( rint( 4 * shrink ) + 1 );
|
||||||
|
|
||||||
case VIPS_KERNEL_LANCZOS2:
|
case VIPS_KERNEL_LANCZOS2:
|
||||||
/* Needs to be in sync with calculate_coefficients_lanczos().
|
/* Needs to be in sync with calculate_coefficients_lanczos().
|
||||||
|
@ -131,12 +131,11 @@ vips_reduce_make_mask( double *c, VipsKernel kernel, double shrink, double x )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_KERNEL_LINEAR:
|
case VIPS_KERNEL_LINEAR:
|
||||||
c[0] = 1.0 - x;
|
calculate_coefficients_triangle( c, shrink, x );
|
||||||
c[1] = x;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_KERNEL_CUBIC:
|
case VIPS_KERNEL_CUBIC:
|
||||||
calculate_coefficients_catmull( c, x );
|
calculate_coefficients_adaptive_catmull( c, shrink, x );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_KERNEL_LANCZOS2:
|
case VIPS_KERNEL_LANCZOS2:
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
* - add @centre option
|
* - add @centre option
|
||||||
* 6/3/17
|
* 6/3/17
|
||||||
* - moved the cache to shrinkv
|
* - moved the cache to shrinkv
|
||||||
|
* 15/10/17
|
||||||
|
* - make LINEAR and CUBIC adaptive
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -101,13 +103,10 @@ G_DEFINE_TYPE( VipsResize, vips_resize, VIPS_TYPE_RESAMPLE );
|
||||||
* This depends on the scale and the kernel we will use for residual resizing.
|
* This depends on the scale and the kernel we will use for residual resizing.
|
||||||
* For upsizing and nearest-neighbour downsize, we want no shrinking.
|
* For upsizing and nearest-neighbour downsize, we want no shrinking.
|
||||||
*
|
*
|
||||||
* Linear and cubic are fixed-size kernels and for a 0 offset are point
|
* The others are adaptive: the size of the kernel changes with the shrink
|
||||||
* samplers. We will get aliasing if we do more than a x2 shrink with them.
|
* factor. We will get the best quality (but be the slowest) if we let
|
||||||
*
|
* reduce do all the work. Leave it the final 200 - 300% to do as a compromise
|
||||||
* Lanczos is adaptive: the size of the kernel changes with the shrink factor.
|
* for efficiency.
|
||||||
* We will get the best quality (but be the slowest) if we let reduce do all
|
|
||||||
* the work. Leave it the final 200 - 300% to do as a compromise for
|
|
||||||
* efficiency.
|
|
||||||
*
|
*
|
||||||
* FIXME: this is rather ugly. Kernel should be a class and this info should be
|
* FIXME: this is rather ugly. Kernel should be a class and this info should be
|
||||||
* stored in there.
|
* stored in there.
|
||||||
|
@ -127,12 +126,9 @@ vips_resize_int_shrink( VipsResize *resize, double scale )
|
||||||
|
|
||||||
case VIPS_KERNEL_LINEAR:
|
case VIPS_KERNEL_LINEAR:
|
||||||
case VIPS_KERNEL_CUBIC:
|
case VIPS_KERNEL_CUBIC:
|
||||||
default:
|
|
||||||
shrink = VIPS_FLOOR( 1.0 / scale );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VIPS_KERNEL_LANCZOS2:
|
case VIPS_KERNEL_LANCZOS2:
|
||||||
case VIPS_KERNEL_LANCZOS3:
|
case VIPS_KERNEL_LANCZOS3:
|
||||||
|
default:
|
||||||
shrink = VIPS_MAX( 1, VIPS_FLOOR( 1.0 / (scale * 2) ) );
|
shrink = VIPS_MAX( 1, VIPS_FLOOR( 1.0 / (scale * 2) ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -311,6 +311,48 @@ calculate_coefficients_catmull( double c[4], const double x )
|
||||||
c[2] = cthr;
|
c[2] = cthr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Calculate a catmull kernel for shrinking.
|
||||||
|
*/
|
||||||
|
static void inline
|
||||||
|
calculate_coefficients_adaptive_catmull( double *c,
|
||||||
|
const double shrink, const double x )
|
||||||
|
{
|
||||||
|
/* Needs to be in sync with vips_reduce_get_points().
|
||||||
|
*/
|
||||||
|
const int n_points = rint( 4 * shrink ) + 1;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
double sum;
|
||||||
|
|
||||||
|
sum = 0;
|
||||||
|
for( i = 0; i < n_points; i++ ) {
|
||||||
|
const double xp = (i - (2 * shrink - 1) - x) / shrink;
|
||||||
|
const double axp = VIPS_FABS( xp );
|
||||||
|
const double axp2 = axp * axp;
|
||||||
|
const double axp3 = axp2 * axp;
|
||||||
|
const double a = -0.5;
|
||||||
|
|
||||||
|
double l;
|
||||||
|
|
||||||
|
if( axp <= 1 )
|
||||||
|
l = (a + 2) * axp3 -
|
||||||
|
(a + 3) * axp2 + 1;
|
||||||
|
else if( axp <= 2 )
|
||||||
|
l = a * axp3 -
|
||||||
|
5 * a * axp2 +
|
||||||
|
8 * a * axp -
|
||||||
|
4 * a;
|
||||||
|
else
|
||||||
|
l = 0.0;
|
||||||
|
|
||||||
|
c[i] = l;
|
||||||
|
sum += l;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i = 0; i < n_points; i++ )
|
||||||
|
c[i] /= sum;
|
||||||
|
}
|
||||||
|
|
||||||
/* Given an x in [0,1] (we can have x == 1 when building tables),
|
/* Given an x in [0,1] (we can have x == 1 when building tables),
|
||||||
* calculate c0 .. c(@a * @shrink + 1), the lanczos coefficients. This is called
|
* calculate c0 .. c(@a * @shrink + 1), the lanczos coefficients. This is called
|
||||||
* from the interpolator as well as from the table builder.
|
* from the interpolator as well as from the table builder.
|
||||||
|
@ -355,6 +397,37 @@ calculate_coefficients_lanczos( double *c,
|
||||||
c[i] /= sum;
|
c[i] /= sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Given an x in [0,1] (we can have x == 1 when building tables),
|
||||||
|
* calculate c0 .. c(@shrink + 1), the triangle coefficients. This is called
|
||||||
|
* from the interpolator as well as from the table builder.
|
||||||
|
*/
|
||||||
|
static void inline
|
||||||
|
calculate_coefficients_triangle( double *c, const double shrink, const double x )
|
||||||
|
{
|
||||||
|
/* Needs to be in sync with vips_reduce_get_points().
|
||||||
|
*/
|
||||||
|
const int n_points = rint( 2 * shrink ) + 1;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
double sum;
|
||||||
|
|
||||||
|
sum = 0;
|
||||||
|
for( i = 0; i < n_points; i++ ) {
|
||||||
|
double xp = (i - (shrink - 1) - x) / shrink;
|
||||||
|
|
||||||
|
double l;
|
||||||
|
|
||||||
|
l = 1.0 - VIPS_FABS( xp );
|
||||||
|
l = VIPS_MAX( 0.0, l );
|
||||||
|
|
||||||
|
c[i] = l;
|
||||||
|
sum += l;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i = 0; i < n_points; i++ )
|
||||||
|
c[i] /= sum;
|
||||||
|
}
|
||||||
|
|
||||||
/* Our inner loop for resampling with a convolution. Operate on elements of
|
/* Our inner loop for resampling with a convolution. Operate on elements of
|
||||||
* type T, gather results in an intermediate of type IT.
|
* type T, gather results in an intermediate of type IT.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue