add an anti-alias filter to vipsthumbnail

vipsthumbnail blurs slightly between shrink and affine, if the affine
will be doing a large shrink
This commit is contained in:
John Cupitt 2014-08-11 10:26:12 +01:00
parent 385b2ea5fa
commit ed3c56fcbf
2 changed files with 48 additions and 18 deletions

View File

@ -6,8 +6,9 @@
- argh fix affine, again, there were sometimes black bars with nohalo and the - argh fix affine, again, there were sometimes black bars with nohalo and the
vips8 interface vips8 interface
- pngsave in interlaced mode makes a copy of the image, so it's always seq - pngsave in interlaced mode makes a copy of the image, so it's always seq
- vipsthumbnail shrinks to 1/2 window_size: faster and better quality - vipsthumbnail shrinks to 1/2 window_size
- vipsthumbnail defaults to bicubic + nosharpen - vipsthumbnail has an anti-alias filter between shrink and affine
- vipsthumbnail defaults to bicubic
- better rounding behaviour for fixed-point bicubic reduces noise - better rounding behaviour for fixed-point bicubic reduces noise
- fix pngload with libpng >=1.6.11 - fix pngload with libpng >=1.6.11
- fix colour for openslide read associated - fix colour for openslide read associated

View File

@ -52,9 +52,10 @@
* 30/6/14 * 30/6/14
* - fix interlaced thumbnail output, thanks lovell * - fix interlaced thumbnail output, thanks lovell
* 3/8/14 * 3/8/14
* - box shrink less, use interpolator more, if the window_size is large * - box shrink less, use interpolator more, if window_size is large
* enough * enough
* - default to bicubic + nosharpen if bicubic is available * - default to bicubic if available
* - add an anti-alias filter between shrink and affine
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -72,7 +73,7 @@
#define ORIENTATION ("exif-ifd0-Orientation") #define ORIENTATION ("exif-ifd0-Orientation")
/* Default settings. We change the default to bicubic + nosharpen in main() if /* Default settings. We change the default to bicubic in main() if
* this vips has been compiled with bicubic support. * this vips has been compiled with bicubic support.
*/ */
@ -391,12 +392,15 @@ thumbnail_shrink( VipsObject *process, VipsImage *in,
VipsImage **t = (VipsImage **) vips_object_local_array( process, 10 ); VipsImage **t = (VipsImage **) vips_object_local_array( process, 10 );
VipsInterpretation interpretation = linear_processing ? VipsInterpretation interpretation = linear_processing ?
VIPS_INTERPRETATION_XYZ : VIPS_INTERPRETATION_sRGB; VIPS_INTERPRETATION_XYZ : VIPS_INTERPRETATION_sRGB;
const int window_size =
interp ? vips_interpolate_get_window_size( interp ) : 2;
int shrink; int shrink;
double residual; double residual;
int tile_width; int tile_width;
int tile_height; int tile_height;
int nlines; int nlines;
double sigma;
/* RAD needs special unpacking. /* RAD needs special unpacking.
*/ */
@ -474,6 +478,7 @@ thumbnail_shrink( VipsObject *process, VipsImage *in,
* has been used ... but it never will, since thread1 will block on * has been used ... but it never will, since thread1 will block on
* this cache lock. * this cache lock.
*/ */
vips_get_tile_size( in, vips_get_tile_size( in,
&tile_width, &tile_height, &nlines ); &tile_width, &tile_height, &nlines );
if( vips_tilecache( in, &t[4], if( vips_tilecache( in, &t[4],
@ -482,12 +487,38 @@ thumbnail_shrink( VipsObject *process, VipsImage *in,
"max_tiles", (nlines * 2) / 10, "max_tiles", (nlines * 2) / 10,
"access", VIPS_ACCESS_SEQUENTIAL, "access", VIPS_ACCESS_SEQUENTIAL,
"threaded", TRUE, "threaded", TRUE,
NULL ) || NULL ) )
vips_affine( t[4], &t[5], residual, 0, 0, residual,
"interpolate", interp,
NULL ) )
return( NULL ); return( NULL );
in = t[5]; in = t[4];
/* If the final affine will be doing a large downsample, we can get
* nasty aliasing on hard edges. Blur before affine to smooth this out.
*
* 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( sigma > 0.1 ) {
if( vips_gaussmat( &t[9], sigma, 0.2,
"separable", TRUE,
"integer", TRUE,
NULL ) ||
vips_convsep( in, &t[5], t[9], NULL ) )
return( NULL );
vips_info( "vipsthumbnail", "anti-alias, sigma %g",
sigma );
#ifdef DEBUG
printf( "anti-alias blur matrix is:\n" );
vips_matrixprint( t[9], NULL );
#endif /*DEBUG*/
in = t[5];
}
if( vips_affine( in, &t[6], residual, 0, 0, residual,
"interpolate", interp,
NULL ) )
return( NULL );
in = t[6];
vips_info( "vipsthumbnail", "residual scale by %g", residual ); vips_info( "vipsthumbnail", "residual scale by %g", residual );
vips_info( "vipsthumbnail", "%s interpolation", vips_info( "vipsthumbnail", "%s interpolation",
@ -511,10 +542,10 @@ thumbnail_shrink( VipsObject *process, VipsImage *in,
} }
else { else {
vips_info( "vipsthumbnail", "converting to sRGB" ); vips_info( "vipsthumbnail", "converting to sRGB" );
if( vips_colourspace( in, &t[6], if( vips_colourspace( in, &t[7],
VIPS_INTERPRETATION_sRGB, NULL ) ) VIPS_INTERPRETATION_sRGB, NULL ) )
return( NULL ); return( NULL );
in = t[6]; in = t[7];
} }
} }
else if( export_profile && else if( export_profile &&
@ -530,13 +561,13 @@ thumbnail_shrink( VipsObject *process, VipsImage *in,
vips_info( "vipsthumbnail", vips_info( "vipsthumbnail",
"exporting with profile %s", export_profile ); "exporting with profile %s", export_profile );
if( vips_icc_transform( in, &t[6], export_profile, if( vips_icc_transform( in, &t[7], export_profile,
"input_profile", import_profile, "input_profile", import_profile,
"embedded", TRUE, "embedded", TRUE,
NULL ) ) NULL ) )
return( NULL ); return( NULL );
in = t[6]; in = t[7];
} }
/* If we are upsampling, don't sharpen, since nearest looks dumb /* If we are upsampling, don't sharpen, since nearest looks dumb
@ -687,13 +718,11 @@ main( int argc, char **argv )
textdomain( GETTEXT_PACKAGE ); textdomain( GETTEXT_PACKAGE );
setlocale( LC_ALL, "" ); setlocale( LC_ALL, "" );
/* Does this vips have bicubic? Default to that + nosharpen if it /* Does this vips have bicubic? Default to that if it
* does. * does.
*/ */
if( vips_type_find( "VipsInterpolate", "bicubic" ) ) { if( vips_type_find( "VipsInterpolate", "bicubic" ) )
interpolator = "bicubic"; interpolator = "bicubic";
convolution_mask = "none";
}
context = g_option_context_new( _( "- thumbnail generator" ) ); context = g_option_context_new( _( "- thumbnail generator" ) );