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
This commit is contained in:
John Cupitt 2015-11-13 14:48:02 +00:00
parent d88304a297
commit 3b32200cc1
2 changed files with 40 additions and 11 deletions

View File

@ -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

View File

@ -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 );
}