From 46212e92b1f943e6852e807db1ee6e5ca66b6ccf Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 28 Aug 2019 09:16:40 +0100 Subject: [PATCH] fix default sharpen sharpen with sigma 0.5 was doing nothing, since the new int precision rules meant that we generated a point-point convolution. This patch increases the int precision for sharpen, so we now work with sigma down to 0.5. Also: restore input colourspace. Previously, the output image was always LabS (the computation space for sharpen). Now, it transforms back to the input space. This is more in line with how other operators work. Thanks 2h4dl for pointing this out. See https://github.com/libvips/pyvips/issues/123 --- ChangeLog | 2 ++ libvips/convolution/sharpen.c | 16 +++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index edb52682..1374ffad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,8 @@ - clip coding and interpretation on vips image read - check image bounds for GIF load - prevent over-pre-shrink in thumbnail [kleisauke] +- fix sharpen with sigma 0.5 [2h4dl] +- sharpen restores input colourspace 24/5/19 started 8.8.1 - improve realpath() use on older libc diff --git a/libvips/convolution/sharpen.c b/libvips/convolution/sharpen.c index dc817575..38df2e48 100644 --- a/libvips/convolution/sharpen.c +++ b/libvips/convolution/sharpen.c @@ -39,6 +39,9 @@ * - swap "radius" for "sigma", allows finer control * - allow a much greater range of parameters * - move to defaults suitable for screen output + * 28/8/19 + * - fix sigma 0.5 case (thanks 2h4dl) + * - restore input colourspace */ /* @@ -170,11 +173,12 @@ vips_sharpen_build( VipsObject *object ) { VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); VipsSharpen *sharpen = (VipsSharpen *) object; - VipsImage **t = (VipsImage **) vips_object_local_array( object, 7 ); + VipsImage **t = (VipsImage **) vips_object_local_array( object, 8 ); VipsImage **args = (VipsImage **) vips_object_local_array( object, 2 ); VipsImage *in; int i; + VipsInterpretation old_interpretation; VIPS_GATE_START( "vips_sharpen_build: build" ); @@ -190,6 +194,7 @@ vips_sharpen_build( VipsObject *object ) in = sharpen->in; + old_interpretation = in->Type; if( vips_colourspace( in, &t[0], VIPS_INTERPRETATION_LABS, NULL ) ) return( -1 ); in = t[0]; @@ -199,10 +204,10 @@ vips_sharpen_build( VipsObject *object ) vips_check_format( class->nickname, in, VIPS_FORMAT_SHORT ) ) return( -1 ); - /* Stop at 20% of max ... a bit mean. We always sharpen a short, + /* Stop at 10% of max ... a bit mean. We always sharpen a short, * so there's no point using a float mask. */ - if( vips_gaussmat( &t[1], sharpen->sigma, 0.2, + if( vips_gaussmat( &t[1], sharpen->sigma, 0.1, "separable", TRUE, "precision", VIPS_PRECISION_INTEGER, NULL ) ) @@ -284,10 +289,11 @@ vips_sharpen_build( VipsObject *object ) g_object_set( object, "out", vips_image_new(), NULL ); - /* Reattach the rest. + /* Reattach the rest, back to the start colourspace. */ if( vips_bandjoin2( t[5], t[3], &t[6], NULL ) || - vips_image_write( t[6], sharpen->out ) ) + vips_colourspace( t[6], &t[7], old_interpretation, NULL ) || + vips_image_write( t[7], sharpen->out ) ) return( -1 ); VIPS_GATE_STOP( "vips_sharpen_build: build" );