try to improve vips_resize() quality

small improvements to vips_resize() quality:

* turn down the anti-alias filter a little so we don't smudge out texture
* don't do the final sharpening pass if we skipped the anti-alias filter
* fix a >/>= mixup which meant we didn't sharpen for small resizes
This commit is contained in:
John Cupitt 2015-11-19 15:22:23 +00:00
parent 40173838d1
commit 8506ff13a6
4 changed files with 17 additions and 12 deletions

View File

@ -12,6 +12,7 @@
- sizealike / formatalike / bandsalike elide completely if they can for
a x2 saving in C stack use in many cases
- added vips_mapim() ... resample with an index image, plus test
- try to improve vips_resize() quality a little more
7/5/15 started 8.1.1
- oop, vips-8.0 wrapper script should be vips-8.1, thanks Danilo

3
TODO
View File

@ -6,9 +6,6 @@
- vips_resize() should not use the anti-alias filter if vips_shrink() has
not been called, ie. for shrinks < 2 or so
- still not happy about float->int mask conversion in im_vips2mask.c
- looks like we have a race in tiled threadcache? see

View File

@ -75,6 +75,7 @@ G_DEFINE_TYPE( VipsResize, vips_resize, VIPS_TYPE_RESAMPLE );
static int
vips_resize_build( VipsObject *object )
{
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
VipsResample *resample = VIPS_RESAMPLE( object );
VipsResize *resize = (VipsResize *) object;
@ -87,6 +88,7 @@ vips_resize_build( VipsObject *object )
int int_shrink_width;
double residual;
double sigma;
gboolean anti_alias;
if( VIPS_OBJECT_CLASS( vips_resize_parent_class )->build( object ) )
return( -1 );
@ -129,6 +131,7 @@ vips_resize_build( VipsObject *object )
/* A copy for enlarge resize.
*/
vips_info( class->nickname, "box shrink by x %d", int_shrink );
if( vips_shrink( in, &t[0], int_shrink, int_shrink, NULL ) )
return( -1 );
in = t[0];
@ -189,14 +192,19 @@ vips_resize_build( VipsObject *object )
* Don't blur for very small shrinks, blur with radius 1 for x1.5
* shrinks, blur radius 2 for x2.5 shrinks and above, etc.
*/
sigma = ((1.0 / residual) - 0.5) / 1.5;
if( residual < 1.0 &&
sigma > 0.1 ) {
sigma = ((1.0 / residual) - 0.5) / 2.0;
anti_alias = residual < 1.0 && sigma > 0.1;
if( anti_alias ) {
vips_info( class->nickname, "anti-alias sigma %g", sigma );
if( vips_gaussblur( in, &t[2], sigma, NULL ) )
return( -1 );
in = t[2];
}
vips_info( class->nickname, "residual affine %g", residual );
vips_info( class->nickname, "%s interpolation",
VIPS_OBJECT_GET_CLASS( resize->interpolate )->nickname );
if( vips_affine( in, &t[3], residual, 0, 0, residual,
"interpolate", resize->interpolate,
"idx", resize->idx,
@ -205,9 +213,12 @@ vips_resize_build( VipsObject *object )
return( -1 );
in = t[3];
/* If we are upsampling, don't sharpen.
/* If we are upsampling, don't sharpen. Also don't sharpen if we
* skipped the anti-alias filter.
*/
if( int_shrink > 1 ) {
if( int_shrink >= 1 &&
anti_alias ) {
vips_info( class->nickname, "final sharpen" );
t[5] = vips_image_new_matrixv( 3, 3,
-1.0, -1.0, -1.0,
-1.0, 32.0, -1.0,

View File

@ -439,10 +439,6 @@ thumbnail_shrink( VipsObject *process, VipsImage *in,
shrink = calculate_shrink( in );
vips_info( "vipsthumbnail", "shrink by %g", shrink );
vips_info( "vipsthumbnail", "%s interpolation",
VIPS_OBJECT_GET_CLASS( interp )->nickname );
if( vips_resize( in, &t[4], 1.0 / shrink,
"interpolate", interp,
NULL ) )