From 3b32200cc112d55b5ebb87043bc4fcdd9af96223 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Fri, 13 Nov 2015 14:48:02 +0000 Subject: [PATCH] sizealike() and friends elide completely sizealike() / formatalike() and bandsalike() used to just vips_copy() if the image didn't need any changes ... this was fast, but left a vips_copy_gen() in the pipeline, wasting a lot of space on the C stack during recursion. They now vanish completely if the image is already in the right format. Since we call them before most image processing operations, and often all three of them, this saves a lot of C stack, more than x2 even in simple cases. There might also be a measureable CPU saving if the operations are very simple (eg. insert). See: http://stackoverflow.com/questions/33658795/difficulty-with-handling-very-large-image-using-vips --- ChangeLog | 2 ++ libvips/arithmetic/arithmetic.c | 49 +++++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 517d45e4..daf2d6e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,8 @@ - added bandjoin_const to add constant bands to an image - better alpha handling for tiff write, thanks sadaqatullahn - better cache sizing for vips_resize() +- sizealike / formatalike / bandsalike elide completely if they can for + a x2 saving in C stack use in many cases 7/5/15 started 8.1.1 - oop, vips-8.0 wrapper script should be vips-8.1, thanks Danilo diff --git a/libvips/arithmetic/arithmetic.c b/libvips/arithmetic/arithmetic.c index 0b6fe14d..0e334f76 100644 --- a/libvips/arithmetic/arithmetic.c +++ b/libvips/arithmetic/arithmetic.c @@ -315,8 +315,17 @@ vips__formatalike_vec( VipsImage **in, VipsImage **out, int n ) format = vips_format_common( format, in[i]->BandFmt ); for( i = 0; i < n; i++ ) - if( vips_cast( in[i], &out[i], format, NULL ) ) - return( -1 ); + if( in[i]->BandFmt == format ) { + /* Already in the right format ... just copy the image + * pointer and add a ref. + */ + out[i] = in[i]; + g_object_ref( in[i] ); + } + else { + if( vips_cast( in[i], &out[i], format, NULL ) ) + return( -1 ); + } return( 0 ); } @@ -338,9 +347,19 @@ vips__sizealike_vec( VipsImage **in, VipsImage **out, int n ) } for( i = 0; i < n; i++ ) - if( vips_embed( in[i], &out[i], - 0, 0, width_max, height_max, NULL ) ) - return( -1 ); + if( in[i]->Xsize == width_max && + in[i]->Ysize == height_max ) { + /* Already the right size ... just copy the image + * pointer and add a ref. + */ + out[i] = in[i]; + g_object_ref( in[i] ); + } + else { + if( vips_embed( in[i], &out[i], + 0, 0, width_max, height_max, NULL ) ) + return( -1 ); + } return( 0 ); } @@ -403,13 +422,21 @@ vips__bandalike_vec( const char *domain, } } - for( i = 0; i < n; i++ ) { - if( vips__bandup( domain, in[i], &out[i], max_bands ) ) - return( -1 ); + for( i = 0; i < n; i++ ) + if( in[i]->Bands == max_bands ) { + /* Already the right number of bands ... just copy the + * image pointer and add a ref. + */ + out[i] = in[i]; + g_object_ref( in[i] ); + } + else { + if( vips__bandup( domain, in[i], &out[i], max_bands ) ) + return( -1 ); - if( interpretation != VIPS_INTERPRETATION_ERROR ) - out[i]->Type = interpretation; - } + if( interpretation != VIPS_INTERPRETATION_ERROR ) + out[i]->Type = interpretation; + } return( 0 ); }