diff --git a/TODO b/TODO index d9f97d91..edb6b9cf 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,6 @@ - vipsthumbnail should use "rd" mode -- should "vips" used "rd" mode as well? +- test "vips" rd open stuff - lcms2 needs testing diff --git a/libvips/include/vips/internal.h b/libvips/include/vips/internal.h index 8278eef0..0cce5f39 100644 --- a/libvips/include/vips/internal.h +++ b/libvips/include/vips/internal.h @@ -70,6 +70,11 @@ extern int im__concurrency; */ extern int im__progress; +/* A string giving the image size (in bytes of uncompressed image) above which + * we decompress to disc on open. + */ +extern char *im__disc_threshold; + typedef int (*im__fftproc_fn)( IMAGE *, IMAGE *, IMAGE * ); /* iofuncs diff --git a/libvips/iofuncs/dispatch_types.c b/libvips/iofuncs/dispatch_types.c index 64673a62..670d87a5 100644 --- a/libvips/iofuncs/dispatch_types.c +++ b/libvips/iofuncs/dispatch_types.c @@ -111,7 +111,7 @@ input_image_init( im_object *obj, char *str ) { IMAGE **im = (IMAGE **) obj; - return( !(*im = im_open( str, "r" )) ); + return( !(*im = im_open( str, "rd" )) ); } /* Input image type. @@ -213,7 +213,7 @@ input_imagevec_init( im_object *obj, char *str ) iv->vec[i] = NULL; for( i = 0; i < nargs; i++ ) - if( !(iv->vec[i] = im_open( strv[i], "r" )) ) { + if( !(iv->vec[i] = im_open( strv[i], "rd" )) ) { g_strfreev( strv ); return( -1 ); } diff --git a/libvips/iofuncs/im_init_world.c b/libvips/iofuncs/im_init_world.c index 8d024252..905eeb3c 100644 --- a/libvips/iofuncs/im_init_world.c +++ b/libvips/iofuncs/im_init_world.c @@ -287,6 +287,9 @@ static GOptionEntry option_entries[] = { N_( "set fatstrip height to N (DEBUG)" ), "N" }, { "vips-progress", 'p', 0, G_OPTION_ARG_NONE, &im__progress, N_( "show progress feedback" ), NULL }, + { "vips-disc-threshold", 'd', 0, G_OPTION_ARG_STRING, + &im__disc_threshold, + N_( "image size above which to decompress to disc" ), NULL }, { NULL } }; diff --git a/libvips/iofuncs/im_open.c b/libvips/iofuncs/im_open.c index 5c6e9458..519eaae5 100644 --- a/libvips/iofuncs/im_open.c +++ b/libvips/iofuncs/im_open.c @@ -96,6 +96,8 @@ Modified: * - break file format stuff out to the new pluggable image format system * 14/1/09 * - write to non-vips formats with a "written" callback + * 29/7/10 + * - disc open threshold stuff, open to disc mode */ /* @@ -150,6 +152,11 @@ Modified: */ int im__progress = 0; +/* A string giving the image size (in bytes of uncompressed image) above which + * we decompress to disc on open. Can be eg. "12m" for 12 megabytes. + */ +char *im__disc_threshold = NULL; + /* Delayed save: if we write to (eg.) TIFF, actually do the write * to a "p" and on "written" do im_vips2tiff() or whatever. Track save * parameters here. @@ -289,11 +296,63 @@ guess_size( VipsFormatClass *format, const char *filename ) return( size ); } +typedef struct { + const char unit; + int multiplier; +} Unit; + +static size_t +disc_threshold( void ) +{ + static gboolean done = FALSE; + static size_t threshold; + static Unit units[] = { + { 'k', 1024 }, + { 'm', 1024 * 1024 }, + { 'g', 1024 * 1024 * 1024 } + }; + + if( !done ) { + threshold = 1024 * 1024; + done = TRUE; + + if( im__disc_threshold ) { + int n; + int size; + char *unit; + + /* An easy way to alloc a buffer large enough. + */ + unit = g_strdup( im__disc_threshold ); + + n = sscanf( im__disc_threshold, "%d %s", &size, unit ); + if( n > 0 ) + threshold = size; + if( n > 1 ) { + int i; + + for( i = 0; i < IM_NUMBER( units ); i++ ) + if( tolower( unit[0] ) == + units[i].unit ) { + threshold *= + units[i].multiplier; + break; + } + } + } + } + +#ifdef DEBUG + printf( "disc_threshold: parsed \"im__disc_threshold\" as %zd\n", + im__disc_threshold, threshold ); +#endif /*DEBUG*/ + + return( threshold ); +} + static IMAGE * open_sub( VipsFormatClass *format, const char *filename, gboolean disc ) { - static const int use_disc_threshold = 1024 * 1024; - IMAGE *im; /* We open to disc if: @@ -308,7 +367,7 @@ open_sub( VipsFormatClass *format, const char *filename, gboolean disc ) size_t size; size = guess_size( format, filename ); - if( size > use_disc_threshold ) + if( size > disc_threshold() ) if( !(im = im__open_temp( "%s.v" )) ) return( NULL ); }