diff --git a/TODO b/TODO index 15abcec7..a9e9243e 100644 --- a/TODO +++ b/TODO @@ -4,27 +4,12 @@ heh fix -- use vips_object_set_from_string() for vips_foreign_load_options() and - friends - - - -- use this for dzsave_buffer - - - -- clean up foreign.c, there seems to be some cruft - vips_filename_suffix_match() is used by vips_foreign_load_new_from_foreign_sub(), but it splits on ':' ... argh! deprecate this thing and stop ':' split - vips_foreign_find_save() should split on [], there's something to find the - start of the rightmost [] pair, use that - - see also vips_foreign_find_save_buffer() - diff --git a/libvips/arithmetic/hough_line.c b/libvips/arithmetic/hough_line.c index 6fac6e2f..eaa5b8bd 100644 --- a/libvips/arithmetic/hough_line.c +++ b/libvips/arithmetic/hough_line.c @@ -37,6 +37,7 @@ #include #include +#include #include diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 6d3b03b6..a8b23b7d 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -466,6 +466,8 @@ vips_foreign_load_summary_class( VipsObjectClass *object_class, VipsBuf *buf ) if( !G_TYPE_IS_ABSTRACT( G_TYPE_FROM_CLASS( class ) ) ) { if( class->is_a ) vips_buf_appends( buf, ", is_a" ); + if( class->is_a_buffer ) + vips_buf_appends( buf, ", is_a_buffer" ); if( class->get_flags ) vips_buf_appends( buf, ", get_flags" ); if( class->get_flags_filename ) @@ -484,7 +486,7 @@ vips_foreign_load_summary_class( VipsObjectClass *object_class, VipsBuf *buf ) /* Can this VipsForeign open this file? */ static void * -vips_foreign_load_new_from_foreign_sub( VipsForeignLoadClass *load_class, +vips_foreign_find_load_sub( VipsForeignLoadClass *load_class, const char *filename ) { VipsForeignClass *class = VIPS_FOREIGN_CLASS( load_class ); @@ -504,35 +506,74 @@ vips_foreign_load_new_from_foreign_sub( VipsForeignLoadClass *load_class, * vips_foreign_find_load: * @filename: file to find a loader for * - * Searches for an operation you could use to load @filename. + * Searches for an operation you could use to load @filename. Any trailing + * options on @filename are stripped and ignored. * * See also: vips_foreign_load(). * * Returns: the name of an operation on success, %NULL on error */ const char * -vips_foreign_find_load( const char *filename ) +vips_foreign_find_load( const char *name ) { + char filename[VIPS_PATH_MAX]; + char option_string[VIPS_PATH_MAX]; VipsForeignLoadClass *load_class; + vips__filename_split8( name, filename, option_string ); + if( !vips_existsf( "%s", filename ) ) { vips_error( "VipsForeignLoad", - _( "file \"%s\" not found" ), filename ); + _( "file \"%s\" not found" ), name ); return( NULL ); } if( !(load_class = (VipsForeignLoadClass *) vips_foreign_map( "VipsForeignLoad", - (VipsSListMap2Fn) vips_foreign_load_new_from_foreign_sub, + (VipsSListMap2Fn) vips_foreign_find_load_sub, (void *) filename, NULL )) ) { vips_error( "VipsForeignLoad", - _( "\"%s\" is not a known file format" ), filename ); + _( "\"%s\" is not a known file format" ), name ); return( NULL ); } return( G_OBJECT_CLASS_NAME( load_class ) ); } +/** + * vips_foreign_load: + * @filename: file to load + * @out: output image + * @...: %NULL-terminated list of optional named arguments + * + * Loads @filename into @out using the loader recommended by + * vips_foreign_find_load(). + * + * See also: vips_foreign_save(), vips_foreign_load_options(). + * + * Returns: 0 on success, -1 on error + */ +int +vips_foreign_load( const char *name, VipsImage **out, ... ) +{ + char filename[VIPS_PATH_MAX]; + char option_string[VIPS_PATH_MAX]; + const char *operation_name; + va_list ap; + int result; + + vips__filename_split8( name, filename, option_string ); + if( !(operation_name = vips_foreign_find_load( filename )) ) + return( -1 ); + + va_start( ap, out ); + result = vips_call_split_option_string( operation_name, option_string, + ap, filename, out ); + va_end( ap ); + + return( result ); +} + /* Can this VipsForeign open this buffer? */ static void * @@ -547,10 +588,11 @@ vips_foreign_find_load_buffer_sub( VipsForeignLoadClass *load_class, } /** - * vips_foreign_find_load: - * @filename: file to find a loader for + * vips_foreign_find_load_buffer: + * @buf: start of memory buffer + * @len: length of memory buffer * - * Searches for an operation you could use to load @filename. + * Searches for an operation you could use to load a memory buffer. * * See also: vips_foreign_load_buffer(). * @@ -574,37 +616,45 @@ vips_foreign_find_load_buffer( void *buf, size_t len ) } /** - * vips_foreign_find_load_options: - * @filename: file to find a loader for + * vips_foreign_load_buffer: + * @buf: start of memory buffer + * @len: length of memory buffer + * @option_string: set of extra options as a string + * @out: output image + * @...: %NULL-terminated list of optional named arguments * - * Searches for an operation you could use to load @filename. + * Loads @buf, @len into @out using the loader recommended by + * vips_foreign_find_load_buffer(). @option_string can be used to give an + * extra set of load options. * - * Arguments to the loader may be embedded in the filename using the usual - * syntax. - * - * See also: vips_foreign_load(). + * See also: vips_foreign_save(), vips_foreign_load_options(). * * Returns: 0 on success, -1 on error */ -const char * -vips_foreign_find_load_options( const char *filename ) +int +vips_foreign_load_buffer( void *buf, size_t len, const char *option_string, + VipsImage **out, ... ) { - VipsObjectClass *oclass = g_type_class_ref( VIPS_TYPE_FOREIGN_LOAD ); - VipsObject *object; - const char *type_name; + const char *operation_name; + VipsArea *area; + va_list ap; + int result; - /* This will use vips_foreign_load_new_from_string() to pick a loader, - * then set options from the tail of the filename. This is rather slow - * :-( + if( !(operation_name = vips_foreign_find_load_buffer( buf, len )) ) + return( -1 ); + + /* We don't take a copy of the data or free it. */ - if( !(object = vips_object_new_from_string( oclass, filename )) ) - return( NULL ); + area = vips_area_new_blob( NULL, buf, len ); - type_name = G_OBJECT_TYPE_NAME( object ); + va_start( ap, out ); + result = vips_call_split_option_string( operation_name, + option_string, ap, area, out ); + va_end( ap ); - g_object_unref( object ); + vips_area_unref( area ); - return( type_name ); + return( result ); } /** @@ -694,7 +744,8 @@ vips_get_disc_threshold( void ) */ threshold = 100 * 1024 * 1024; - if( (env = g_getenv( "IM_DISC_THRESHOLD" )) ) + if( (env = g_getenv( "VIPS_DISC_THRESHOLD" )) || + (env = g_getenv( "IM_DISC_THRESHOLD" )) ) threshold = vips__parse_size( env ); if( vips__disc_threshold ) @@ -1039,135 +1090,6 @@ vips_foreign_save_summary_class( VipsObjectClass *object_class, VipsBuf *buf ) vips_enum_nick( VIPS_TYPE_SAVEABLE, class->saveable ) ); } -/* Can we write this filename with this file? - */ -static void * -vips_foreign_find_save_sub( VipsForeignSaveClass *save_class, - const char *filename ) -{ - VipsForeignClass *class = VIPS_FOREIGN_CLASS( save_class ); - - if( class->suffs && - vips_filename_suffix_match( filename, class->suffs ) ) - return( save_class ); - - return( NULL ); -} - -/** - * vips_foreign_find_save: - * @filename: name to find a saver for - * - * Searches for an operation you could use to write to @filename. - * - * @filename may not contain embedded options. See - * vips_foreign_find_save_options() if your filename may have options in. - * - * See also: vips_foreign_save(). - * - * Returns: the name of an operation on success, %NULL on error - */ -const char * -vips_foreign_find_save( const char *filename ) -{ - VipsForeignSaveClass *save_class; - - if( !(save_class = (VipsForeignSaveClass *) vips_foreign_map( - "VipsForeignSave", - (VipsSListMap2Fn) vips_foreign_find_save_sub, - (void *) filename, NULL )) ) { - vips_error( "VipsForeignSave", - _( "\"%s\" is not a known file format" ), filename ); - - return( NULL ); - } - - return( G_OBJECT_CLASS_NAME( save_class ) ); -} - -/* Can we write this buffer with this file type? - */ -static void * -vips_foreign_find_save_buffer_sub( VipsForeignSaveClass *save_class, - const char *suffix ) -{ - VipsObjectClass *object_class = VIPS_OBJECT_CLASS( save_class ); - VipsForeignClass *class = VIPS_FOREIGN_CLASS( save_class ); - - if( class->suffs && - vips_ispostfix( object_class->nickname, "_buffer" ) && - vips_filename_suffix_match( suffix, class->suffs ) ) - return( save_class ); - - return( NULL ); -} - -/** - * vips_foreign_find_save_buffer: - * @suffix: name to find a saver for - * - * Searches for an operation you could use to write to a buffer in @suffix - * format. - * - * @filename may not contain embedded options. See - * vips_foreign_find_save_options() if your filename may have options in. - * - * See also: vips_foreign_save_buffer(). - * - * Returns: the name of an operation on success, %NULL on error - */ -const char * -vips_foreign_find_save_buffer( const char *suffix ) -{ - VipsForeignSaveClass *save_class; - - if( !(save_class = (VipsForeignSaveClass *) vips_foreign_map( - "VipsForeignSave", - (VipsSListMap2Fn) vips_foreign_find_save_buffer_sub, - (void *) suffix, NULL )) ) { - vips_error( "VipsForeignSave", - _( "\"%s\" is not a known file format" ), suffix ); - - return( NULL ); - } - - return( G_OBJECT_CLASS_NAME( save_class ) ); -} - -/** - * vips_foreign_find_save_options: - * @filename: name to find a saver for - * - * Searches for an operation you could use to write to @filename. - * - * @filename may contain embedded options. See - * vips_foreign_find_save() if your filename does not have options in. - * - * See also: vips_foreign_write(). - * - * Returns: 0 on success, -1 on error - */ -const char * -vips_foreign_find_save_options( const char *filename ) -{ - VipsObjectClass *oclass = g_type_class_ref( VIPS_TYPE_FOREIGN_SAVE ); - VipsObject *object; - const char *type_name; - - /* This will use vips_foreign_save_new_from_string() to pick a saver, - * then set options from the tail of the filename. This is rather slow - * :-( - */ - if( !(object = vips_object_new_from_string( oclass, filename )) ) - return( NULL ); - - type_name = G_OBJECT_TYPE_NAME( object ); - - g_object_unref( object ); - - return( type_name ); -} - static VipsObject * vips_foreign_save_new_from_string( const char *string ) { @@ -1533,72 +1455,52 @@ vips_foreign_save_init( VipsForeignSave *object ) { } -/** - * vips_foreign_load: - * @filename: file to load - * @out: output image - * @...: %NULL-terminated list of optional named arguments - * - * Loads @filename into @out using the loader recommended by - * vips_foreign_find_load(). - * - * See also: vips_foreign_save(), vips_foreign_load_options(). - * - * Returns: 0 on success, -1 on error +/* Can we write this filename with this file? */ -int -vips_foreign_load( const char *filename, VipsImage **out, ... ) +static void * +vips_foreign_find_save_sub( VipsForeignSaveClass *save_class, + const char *filename ) { - const char *operation; - va_list ap; - int result; + VipsForeignClass *class = VIPS_FOREIGN_CLASS( save_class ); - if( !(operation = vips_foreign_find_load( filename )) ) - return( -1 ); + if( class->suffs && + vips_filename_suffix_match( filename, class->suffs ) ) + return( save_class ); - va_start( ap, out ); - result = vips_call_split( operation, ap, filename, out ); - va_end( ap ); - - return( result ); + return( NULL ); } /** - * vips_foreign_load_buffer: - * @buf: start of memory buffer - * @len: length of memory buffer - * @out: output image - * @...: %NULL-terminated list of optional named arguments + * vips_foreign_find_save: + * @filename: name to find a saver for * - * Loads @buf, @len into @out using the loader recommended by - * vips_foreign_find_load_buffer(). + * Searches for an operation you could use to write to @filename. + * Any trailing options on @filename are stripped and ignored. * - * See also: vips_foreign_save(), vips_foreign_load_options(). + * See also: vips_foreign_save(). * - * Returns: 0 on success, -1 on error + * Returns: the name of an operation on success, %NULL on error */ -int -vips_foreign_load_buffer( void *buf, size_t len, VipsImage **out, ... ) +const char * +vips_foreign_find_save( const char *name ) { - const char *operation; - VipsArea *area; - va_list ap; - int result; + char filename[VIPS_PATH_MAX]; + char option_string[VIPS_PATH_MAX]; + VipsForeignSaveClass *save_class; - if( !(operation = vips_foreign_find_load_buffer( buf, len )) ) - return( -1 ); + vips__filename_split8( name, filename, option_string ); - /* We don't take a copy of the data or free it. - */ - area = vips_area_new_blob( NULL, buf, len ); + if( !(save_class = (VipsForeignSaveClass *) vips_foreign_map( + "VipsForeignSave", + (VipsSListMap2Fn) vips_foreign_find_save_sub, + (void *) filename, NULL )) ) { + vips_error( "VipsForeignSave", + _( "\"%s\" is not a known file format" ), name ); - va_start( ap, out ); - result = vips_call_split( operation, ap, area, out ); - va_end( ap ); + return( NULL ); + } - vips_area_unref( area ); - - return( result ); + return( G_OBJECT_CLASS_NAME( save_class ) ); } /** @@ -1616,22 +1518,77 @@ vips_foreign_load_buffer( void *buf, size_t len, VipsImage **out, ... ) * Returns: 0 on success, -1 on error */ int -vips_foreign_save( VipsImage *in, const char *filename, ... ) +vips_foreign_save( VipsImage *in, const char *name, ... ) { - const char *operation; + char filename[VIPS_PATH_MAX]; + char option_string[VIPS_PATH_MAX]; + const char *operation_name; va_list ap; int result; - if( !(operation = vips_foreign_find_save( filename )) ) + vips__filename_split8( name, filename, option_string ); + + if( !(operation_name = vips_foreign_find_save( filename )) ) return( -1 ); - va_start( ap, filename ); - result = vips_call_split( operation, ap, in, filename ); + va_start( ap, name ); + result = vips_call_split_option_string( operation_name, option_string, + ap, in, filename ); va_end( ap ); return( result ); } +/* Can we write this buffer with this file type? + */ +static void * +vips_foreign_find_save_buffer_sub( VipsForeignSaveClass *save_class, + const char *suffix ) +{ + VipsObjectClass *object_class = VIPS_OBJECT_CLASS( save_class ); + VipsForeignClass *class = VIPS_FOREIGN_CLASS( save_class ); + + if( class->suffs && + vips_ispostfix( object_class->nickname, "_buffer" ) && + vips_filename_suffix_match( suffix, class->suffs ) ) + return( save_class ); + + return( NULL ); +} + +/** + * vips_foreign_find_save_buffer: + * @suffix: name to find a saver for + * + * Searches for an operation you could use to write to a buffer in @suffix + * format. + * + * See also: vips_foreign_save_buffer(). + * + * Returns: the name of an operation on success, %NULL on error + */ +const char * +vips_foreign_find_save_buffer( const char *name ) +{ + char suffix[VIPS_PATH_MAX]; + char option_string[VIPS_PATH_MAX]; + VipsForeignSaveClass *save_class; + + vips__filename_split8( name, suffix, option_string ); + + if( !(save_class = (VipsForeignSaveClass *) vips_foreign_map( + "VipsForeignSave", + (VipsSListMap2Fn) vips_foreign_find_save_buffer_sub, + (void *) suffix, NULL )) ) { + vips_error( "VipsForeignSave", + _( "\"%s\" is not a known file format" ), name ); + + return( NULL ); + } + + return( G_OBJECT_CLASS_NAME( save_class ) ); +} + /** * vips_foreign_save_buffer: * @in: image to write @@ -1651,66 +1608,26 @@ vips_foreign_save( VipsImage *in, const char *filename, ... ) */ int vips_foreign_save_buffer( VipsImage *in, - const char *suffix, void **buf, size_t *len, + const char *name, void **buf, size_t *len, ... ) { - char str[VIPS_PATH_MAX]; - char *p; + char suffix[VIPS_PATH_MAX]; + char option_string[VIPS_PATH_MAX]; const char *operation_name; - VipsOperation *operation; VipsArea *area; va_list ap; int result; - /* Take any [options] off the suffix. - */ - vips_strncpy( str, suffix, VIPS_PATH_MAX ); - if( (p = (char *) vips__find_rightmost_brackets( str )) ) - *p = '\0'; + vips__filename_split8( name, suffix, option_string ); - if( !(operation_name = vips_foreign_find_save_buffer( str )) ) + if( !(operation_name = vips_foreign_find_save_buffer( suffix )) ) return( -1 ); - if( !(operation = vips_operation_new( operation_name )) ) - return( -1 ); - - g_object_set( operation, "in", in, NULL ); - - /* Now set any operation args from the options list. - */ - if( (p = (char *) vips__find_rightmost_brackets( suffix )) && - vips_object_set_from_string( VIPS_OBJECT( operation ), p ) ) { - vips_object_unref_outputs( VIPS_OBJECT( operation ) ); - g_object_unref( operation ); - return( -1 ); - } - - /* Set any from varargs. - */ va_start( ap, len ); - result = vips_object_set_valist( VIPS_OBJECT( operation ), ap ); + result = vips_call_split_option_string( operation_name, option_string, + ap, in, &area ); va_end( ap ); - if( result ) { - vips_object_unref_outputs( VIPS_OBJECT( operation ) ); - g_object_unref( operation ); - return( -1 ); - } - - if( vips_cache_operation_buildp( &operation ) ) { - vips_object_unref_outputs( VIPS_OBJECT( operation ) ); - g_object_unref( operation ); - return( -1 ); - } - - g_object_get( operation, "buffer", &area, NULL ); - - /* Getting @buffer will have upped its count so it'll be safe. - * We can junk all other outputs, - */ - vips_object_unref_outputs( VIPS_OBJECT( operation ) ); - g_object_unref( operation ); - if( area ) { if( buf ) { *buf = area->data; @@ -1722,124 +1639,7 @@ vips_foreign_save_buffer( VipsImage *in, vips_area_unref( area ); } - return( 0 ); -} - -/** - * vips_foreign_load_options: - * @filename: file to load - * @out: output image - * @...: %NULL-terminated list of optional named arguments - * - * Loads @filename into @out using the loader recommended by - * vips_foreign_find_load(). - * - * Arguments to the loader may be embedded in the filename using the usual - * syntax. They may also be given as a set of NULL-terminated optional - * arguments. - * - * See also: vips_foreign_load(). - * - * Returns: 0 on success, -1 on error - */ -int -vips_foreign_load_options( const char *filename, VipsImage **out, ... ) -{ - VipsObjectClass *oclass = g_type_class_ref( VIPS_TYPE_FOREIGN_LOAD ); - - VipsObject *object; - va_list ap; - int result; - - /* This will use vips_foreign_load_new_from_string() to pick a loader, - * then set options from the remains of the string. - */ - if( !(object = vips_object_new_from_string( oclass, filename )) ) - return( -1 ); - - /* Also set options from args. - */ - va_start( ap, out ); - result = vips_object_set_valist( object, ap ); - va_end( ap ); - if( result ) - return( -1 ); - - if( vips_cache_operation_buildp( (VipsOperation **) &object ) ) { - /* The build may have made some output objects before - * failing. - */ - vips_object_unref_outputs( object ); - g_object_unref( object ); - return( -1 ); - } - - g_object_get( object, "out", out, NULL ); - - /* Getting @out will have upped its count so it'll be safe. - * We can junk all other outputs, - */ - vips_object_unref_outputs( object ); - - /* @out holds a ref to new_object, we can drop ours. - */ - g_object_unref( object ); - - return( 0 ); -} - -/** - * vips_foreign_save_options: - * @in: image to write - * @filename: file to write to - * @...: %NULL-terminated list of optional named arguments - * - * Saves @in to @filename using the saver recommended by - * vips_foreign_find_save(). - * - * Arguments to the saver may be embedded in the filename using the usual - * syntax. They may also be given as a set of NULL-terminated optional - * arguments. - * - * See also: vips_foreign_save(). - * - * Returns: 0 on success, -1 on error - */ -int -vips_foreign_save_options( VipsImage *in, const char *filename, ... ) -{ - VipsObjectClass *oclass = g_type_class_ref( VIPS_TYPE_FOREIGN_SAVE ); - - VipsObject *object; - va_list ap; - int result; - - /* This will use vips_foreign_save_new_from_string() to pick a saver, - * then set options from the tail of the filename. - */ - if( !(object = vips_object_new_from_string( oclass, filename )) ) - return( -1 ); - - g_object_set( object, "in", in, NULL ); - - /* Also set options from args. - */ - va_start( ap, filename ); - result = vips_object_set_valist( object, ap ); - va_end( ap ); - if( result ) - return( -1 ); - - /* ... and running _build() should save it. - */ - if( vips_cache_operation_buildp( (VipsOperation **) &object ) ) { - g_object_unref( object ); - return( -1 ); - } - - g_object_unref( object ); - - return( 0 ); + return( result ); } /* Called from iofuncs to init all operations in this dir. Use a plugin system diff --git a/libvips/include/vips/foreign.h b/libvips/include/vips/foreign.h index 489c93a7..118396ee 100644 --- a/libvips/include/vips/foreign.h +++ b/libvips/include/vips/foreign.h @@ -215,7 +215,6 @@ GType vips_foreign_load_get_type( void ); const char *vips_foreign_find_load( const char *filename ); const char *vips_foreign_find_load_buffer( void *buf, size_t len ); -const char *vips_foreign_find_load_options( const char *filename ); VipsForeignFlags vips_foreign_flags( const char *loader, const char *filename ); gboolean vips_foreign_is_a( const char *loader, const char *filename ); @@ -309,7 +308,6 @@ GType vips_foreign_save_get_type( void ); const char *vips_foreign_find_save( const char *filename ); const char * vips_foreign_find_save_buffer( const char *suffix ); -const char *vips_foreign_find_save_options( const char *filename ); /* Read/write an image convenience functions. */ @@ -318,12 +316,8 @@ int vips_foreign_load( const char *filename, VipsImage **out, ... ) int vips_foreign_save( VipsImage *in, const char *filename, ... ) __attribute__((sentinel)); -int vips_foreign_load_options( const char *filename, VipsImage **out, ... ) - __attribute__((sentinel)); -int vips_foreign_save_options( VipsImage *in, const char *filename, ... ) - __attribute__((sentinel)); - -int vips_foreign_load_buffer( void *buf, size_t len, VipsImage **out, ... ) +int vips_foreign_load_buffer( void *buf, size_t len, const char *option_string, + VipsImage **out, ... ) __attribute__((sentinel)); int vips_foreign_save_buffer( VipsImage *in, const char *suffix, void **buf, size_t *len, ... ) diff --git a/libvips/include/vips/operation.h b/libvips/include/vips/operation.h index e9697e61..0afb9a9d 100644 --- a/libvips/include/vips/operation.h +++ b/libvips/include/vips/operation.h @@ -104,6 +104,8 @@ VipsOperation *vips_operation_new( const char *name ); int vips_call( const char *operation_name, ... ) __attribute__((sentinel)); int vips_call_split( const char *operation_name, va_list optional, ... ); +int vips_call_split_option_string( const char *operation_name, + const char *option_string, va_list optional, ... ); void vips_call_options( GOptionGroup *group, VipsOperation *operation ); int vips_call_argv( VipsOperation *operation, int argc, char **argv ); diff --git a/libvips/include/vips/util.h b/libvips/include/vips/util.h index 152bcb2c..4bd3f069 100644 --- a/libvips/include/vips/util.h +++ b/libvips/include/vips/util.h @@ -257,6 +257,8 @@ const char *vips__token_must( const char *buffer, VipsToken *token, const char *vips__token_need( const char *buffer, VipsToken need_token, char *string, int size ); const char *vips__find_rightmost_brackets( const char *p ); +void vips__filename_split8( const char *name, + char *filename, char *option_string ); int vips_ispoweroftwo( int p ); int vips_amiMSBfirst( void ); diff --git a/libvips/iofuncs/error.c b/libvips/iofuncs/error.c index ac35d22f..6ce54362 100644 --- a/libvips/iofuncs/error.c +++ b/libvips/iofuncs/error.c @@ -431,7 +431,7 @@ vips_info( const char *domain, const char *fmt, ... ) * @ap: arguments to the format string * * Sends a formatted warning message to stderr. If you define the - * environment variable IM_WARNING, these message are surpressed. + * environment variable VIPS_WARNING, these message are surpressed. * * Warning messages are used to report things like overflow counts. * @@ -440,7 +440,8 @@ vips_info( const char *domain, const char *fmt, ... ) void vips_vwarn( const char *domain, const char *fmt, va_list ap ) { - if( !g_getenv( "IM_WARNING" ) ) { + if( !g_getenv( "IM_WARNING" ) && + !g_getenv( "VIPS_WARNING" ) ) { g_mutex_lock( vips__global_lock ); (void) fprintf( stderr, _( "%s: " ), _( "vips warning" ) ); if( domain ) diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index d274d83e..5a70ddc5 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -670,7 +670,7 @@ vips_image_rewind( VipsObject *object ) static void vips_image_save_cb( VipsImage *image, int *result ) { - if( vips_foreign_save_options( image, image->filename, NULL ) ) + if( vips_foreign_save( image, image->filename, NULL ) ) *result = -1; } @@ -737,6 +737,7 @@ static void vips_image_add_progress( VipsImage *image ) { if( vips__progress || + g_getenv( "VIPS_PROGRESS" ) || g_getenv( "IM_PROGRESS" ) ) { /* Keep the %complete we displayed last time here. @@ -825,14 +826,13 @@ vips_image_build( VipsObject *object ) VipsImage *t; if( mode[1] == 's' ) { - if( vips_foreign_load_options( filename, &t, + if( vips_foreign_load( filename, &t, "access", VIPS_ACCESS_SEQUENTIAL, NULL ) ) return( -1 ); } else { - if( vips_foreign_load_options( filename, &t, - NULL ) ) + if( vips_foreign_load( filename, &t, NULL ) ) return( -1 ); } @@ -855,7 +855,7 @@ vips_image_build( VipsObject *object ) */ g_assert( g_type_from_name( "VipsForeignSaveVips" ) ); - if( !(file_op = vips_foreign_find_save_options( filename )) ) + if( !(file_op = vips_foreign_find_save( filename )) ) return( -1 ); /* If this is the vips saver, just save directly ourselves. @@ -1579,7 +1579,7 @@ vips_image_new( void ) * location for the temporary file. * * The disc threshold can be set with the "--vips-disc-threshold" - * command-line argument, or the IM_DISC_THRESHOLD environment variable. + * command-line argument, or the VIPS_DISC_THRESHOLD environment variable. * The value is a simple integer, but can take a unit postfix of "k", * "m" or "g" to indicate kilobytes, megabytes or gigabytes. * diff --git a/libvips/iofuncs/init.c b/libvips/iofuncs/init.c index c0f80d15..9325f90d 100644 --- a/libvips/iofuncs/init.c +++ b/libvips/iofuncs/init.c @@ -246,7 +246,8 @@ vips__init( const char *argv0 ) /* Default info setting from env. */ - if( g_getenv( "IM_INFO" ) ) + if( g_getenv( "VIPS_INFO" ) || + g_getenv( "IM_INFO" ) ) vips__info = 1; /* Register base vips types. diff --git a/libvips/iofuncs/object.c b/libvips/iofuncs/object.c index 70cf40eb..5808da98 100644 --- a/libvips/iofuncs/object.c +++ b/libvips/iofuncs/object.c @@ -1672,8 +1672,7 @@ vips_object_set_argument_from_string( VipsObject *object, return( -1 ); } - /* Read the filename. vips_foreign_load_options() - * handles embedded options. + /* Read the filename. */ if( flags & VIPS_OPERATION_SEQUENTIAL_UNBUFFERED ) access = VIPS_ACCESS_SEQUENTIAL_UNBUFFERED; @@ -1682,7 +1681,7 @@ vips_object_set_argument_from_string( VipsObject *object, else access = VIPS_ACCESS_RANDOM; - if( vips_foreign_load_options( value, &out, + if( vips_foreign_load( value, &out, "access", access, NULL ) ) return( -1 ); @@ -1906,10 +1905,9 @@ vips_object_get_argument_to_string( VipsObject *object, VipsImage *in; /* Pull out the image and write it. - * vips_foreign_save_options() handles embedded options. */ g_object_get( object, name, &in, NULL ); - if( vips_foreign_save_options( in, arg, NULL ) ) { + if( vips_foreign_save( in, arg, NULL ) ) { g_object_unref( in ); return( -1 ); } @@ -2090,10 +2088,18 @@ vips_object_set_args( VipsObject *object, const char *p ) string, VIPS_PATH_MAX )) ) return( -1 ); - do { - if( !(p = vips__token_need( p, VIPS_TOKEN_STRING, - string, VIPS_PATH_MAX )) ) + if( !(p = vips__token_must( p, &token, string, VIPS_PATH_MAX )) ) + return( -1 ); + + for(;;) { + if( token == VIPS_TOKEN_RIGHT ) + break; + if( token != VIPS_TOKEN_STRING ) { + vips_error( class->nickname, + _( "expected string or ), saw %s" ), + vips_enum_nick( VIPS_TYPE_TOKEN, token ) ); return( -1 ); + } /* We have to look for a '=', ')' or a ',' to see if string is * a param name or a value. @@ -2136,14 +2142,19 @@ vips_object_set_args( VipsObject *object, const char *p ) return( -1 ); } - /* Now must be a , or a ). + /* Now must be a , or a ). */ - if( token != VIPS_TOKEN_RIGHT && token != VIPS_TOKEN_COMMA ) { + if( token == VIPS_TOKEN_COMMA ) { + if( !(p = vips__token_must( p, &token, + string, VIPS_PATH_MAX )) ) + return( -1 ); + } + else if( token != VIPS_TOKEN_RIGHT ) { vips_error( class->nickname, "%s", _( "not , or ) after parameter" ) ); return( -1 ); } - } while( token != VIPS_TOKEN_RIGHT ); + } if( (p = vips__token_get( p, &token, string, VIPS_PATH_MAX )) ) { vips_error( class->nickname, diff --git a/libvips/iofuncs/operation.c b/libvips/iofuncs/operation.c index 932c9036..de2d2215 100644 --- a/libvips/iofuncs/operation.c +++ b/libvips/iofuncs/operation.c @@ -647,6 +647,50 @@ vips_call_required_optional( VipsOperation **operation, return( result ); } +static int +vips_call_by_name( const char *operation_name, + const char *option_string, va_list required, va_list optional ) +{ + VipsOperation *operation; + int result; + + VIPS_DEBUG_MSG( "vips_call_by_name: starting for %s ...\n", + operation_name ); + + if( !(operation = vips_operation_new( operation_name )) ) + return( -1 ); + + /* Set str options before vargs options, so the user can't override + * thnigs we set deliberately. + */ + if( option_string && + vips_object_set_from_string( VIPS_OBJECT( operation ), + option_string ) ) { + vips_object_unref_outputs( VIPS_OBJECT( operation ) ); + g_object_unref( operation ); + + return( -1 ); + } + + result = vips_call_required_optional( &operation, required, optional ); + + /* Build failed: junk args and back out. + */ + if( result ) { + vips_object_unref_outputs( VIPS_OBJECT( operation ) ); + g_object_unref( operation ); + + return( -1 ); + } + + /* The operation we have built should now have been reffed by one of + * its arguments or have finished its work. Either way, we can unref. + */ + g_object_unref( operation ); + + return( result ); +} + int vips_call( const char *operation_name, ... ) { @@ -655,16 +699,9 @@ vips_call( const char *operation_name, ... ) va_list required; va_list optional; - VIPS_DEBUG_MSG( "vips_call: starting for %s ...\n", operation_name ); - if( !(operation = vips_operation_new( operation_name ) ) ) return( -1 ); -#ifdef VIPS_DEBUG - VIPS_DEBUG_MSG( "where:\n" ); - vips_object_print_dump( VIPS_OBJECT( operation ) ); -#endif /*VIPS_DEBUG*/ - /* We have to break the va_list into separate required and optional * components. * @@ -690,58 +727,43 @@ vips_call( const char *operation_name, ... ) } } VIPS_ARGUMENT_FOR_ALL_END - result = vips_call_required_optional( &operation, required, optional ); + /* We just needed this operation for the arg loop. + */ + g_object_unref( operation ); + + result = vips_call_by_name( operation_name, NULL, required, optional ); va_end( required ); va_end( optional ); - /* Failed: junk args and back out. - */ - if( result ) { - vips_object_unref_outputs( VIPS_OBJECT( operation ) ); - g_object_unref( operation ); - - return( -1 ); - } - - /* The operation we have built should now have been reffed by one of - * its arguments or have finished its work. Either way, we can unref. - */ - g_object_unref( operation ); - return( result ); } int vips_call_split( const char *operation_name, va_list optional, ... ) { - VipsOperation *operation; int result; va_list required; - VIPS_DEBUG_MSG( "vips_call_split: starting for %s ...\n", - operation_name ); - - if( !(operation = vips_operation_new( operation_name )) ) - return( -1 ); - va_start( required, optional ); - result = vips_call_required_optional( &operation, required, optional ); + result = vips_call_by_name( operation_name, NULL, + required, optional ); va_end( required ); - /* Build failed: junk args and back out. - */ - if( result ) { - vips_object_unref_outputs( VIPS_OBJECT( operation ) ); - g_object_unref( operation ); + return( result ); +} - return( -1 ); - } +int +vips_call_split_option_string( const char *operation_name, + const char *option_string, va_list optional, ... ) +{ + int result; + va_list required; - /* The operation we have built should now have been reffed by one of - * its arguments or have finished its work. Either way, we can unref. - */ - g_object_unref( operation ); + va_start( required, optional ); + result = vips_call_by_name( operation_name, option_string, + required, optional ); + va_end( required ); return( result ); } diff --git a/libvips/iofuncs/threadpool.c b/libvips/iofuncs/threadpool.c index 4dadc89a..4d3ae6a3 100644 --- a/libvips/iofuncs/threadpool.c +++ b/libvips/iofuncs/threadpool.c @@ -82,14 +82,10 @@ */ /* Maximum number of concurrent threads we allow. No reason for the limit, - * it's just there to stop mad values for IM_CONCURRENCY killing the system. + * it's just there to stop mad values for VIPS_CONCURRENCY killing the system. */ #define MAX_THREADS (1024) -/* Name of environment variable we get concurrency level from. - */ -#define IM_CONCURRENCY "IM_CONCURRENCY" - /* Default tile geometry ... can be set by init_world. */ int vips__tile_width = VIPS__TILE_WIDTH; @@ -218,7 +214,7 @@ vips_g_thread_new( const char *domain, GThreadFunc func, gpointer data ) * #VipsThreadPool. * * The special value 0 means "default". In this case, the number of threads is - * set by the environmnt variable IM_CONCURRENCY, or if that is not set, the + * set by the environmnt variable VIPS_CONCURRENCY, or if that is not set, the * number of threads availble on the hist machine. * * See also: vips_concurrency_get(). @@ -305,9 +301,9 @@ get_num_processors( void ) * "--vips-concurrency" to set this value. * * If vips_concurrency_set() has not been called and no command-line argument - * was used, vips uses the value of the environment variable IM_CONCURRENCY, + * was used, vips uses the value of the environment variable VIPS_CONCURRENCY, * - * If IM_CONCURRENCY has not been set, vips find the number of hardware + * If VIPS_CONCURRENCY has not been set, vips find the number of hardware * threads that the host machine can run in parallel and uses that value. * * The final value is clipped to the range 1 - 1024. @@ -327,7 +323,8 @@ vips_concurrency_get( void ) */ if( vips__concurrency > 0 ) nthr = vips__concurrency; - else if( (str = g_getenv( IM_CONCURRENCY )) && + else if( ((str = g_getenv( "VIPS_CONCURRENCY" )) || + (str = g_getenv( "IM_CONCURRENCY" ))) && (x = atoi( str )) > 0 ) nthr = x; else diff --git a/libvips/iofuncs/util.c b/libvips/iofuncs/util.c index 59ebc04d..c8840010 100644 --- a/libvips/iofuncs/util.c +++ b/libvips/iofuncs/util.c @@ -1428,6 +1428,24 @@ vips__find_rightmost_brackets( const char *p ) return( start[i] ); } +/* Split a vips8-style filename + options. + * + * filename and options must be VIPS_PATH_MAX in length. + */ +void +vips__filename_split8( const char *name, char *filename, char *option_string ) +{ + char *p; + + vips_strncpy( filename, name, VIPS_PATH_MAX ); + if( (p = (char *) vips__find_rightmost_brackets( filename )) ) { + vips_strncpy( option_string, p, VIPS_PATH_MAX ); + *p = '\0'; + } + else + vips_strncpy( option_string, "", VIPS_PATH_MAX ); +} + /* True if an int is a power of two ... 1, 2, 4, 8, 16, 32, etc. Do with just * integer arithmetic for portability. A previous Nicos version using doubles * and log/log failed on x86 with rounding problems. Return 0 for not diff --git a/libvips/iofuncs/vector.c b/libvips/iofuncs/vector.c index 6c772e65..565973f1 100644 --- a/libvips/iofuncs/vector.c +++ b/libvips/iofuncs/vector.c @@ -77,7 +77,8 @@ vips_vector_init( void ) /* Look for the environment variable IM_NOVECTOR and use that to turn * off as well. */ - if( g_getenv( "IM_NOVECTOR" ) ) + if( g_getenv( "VIPS_NOVECTOR" ) || + g_getenv( "IM_NOVECTOR" ) ) vips__vector_enabled = FALSE; #endif /*HAVE_ORC*/ } diff --git a/libvips/morphology/hitmiss.c b/libvips/morphology/hitmiss.c index 093b5ea4..fdbe4584 100644 --- a/libvips/morphology/hitmiss.c +++ b/libvips/morphology/hitmiss.c @@ -51,6 +51,7 @@ */ /* +#define DEBUG_VERBOSE #define DEBUG */ @@ -208,8 +209,14 @@ pass_compile_section( Pass *pass, Morph *morph, gboolean first_pass ) ASM3( "orb", "sum", "sum", "value" ); } else { - if( !mask->coeff[i] ) - ASM3( "andnb", "sum", "sum", "value" ); + if( !mask->coeff[i] ) { + /* You'd think we could use andnb, but it + * fails on some machines with some orc + * versions :( + */ + ASM3( "xorb", "value", "value", one ); + ASM3( "andb", "sum", "sum", "value" ); + } else ASM3( "andb", "sum", "sum", "value" ); } @@ -454,10 +461,10 @@ dilate_gen( REGION *or, void *vseq, void *a, void *b ) if( im_prepare( ir, &s ) ) return( -1 ); -#ifdef DEBUG +#ifdef DEBUG_VERBOSE printf( "dilate_gen: preparing %dx%d@%dx%d pixels\n", s.width, s.height, s.left, s.top ); -#endif /*DEBUG*/ +#endif /*DEBUG_VERBOSE*/ /* Scan mask, building offsets we check when processing. Only do this * if the bpl has changed since the previous im_prepare(). @@ -566,10 +573,10 @@ erode_gen( REGION *or, void *vseq, void *a, void *b ) if( im_prepare( ir, &s ) ) return( -1 ); -#ifdef DEBUG +#ifdef DEBUG_VERBOSE printf( "erode_gen: preparing %dx%d@%dx%d pixels\n", s.width, s.height, s.left, s.top ); -#endif /*DEBUG*/ +#endif /*DEBUG_VERBOSE*/ /* Scan mask, building offsets we check when processing. Only do this * if the bpl has changed since the previous im_prepare(). @@ -665,10 +672,10 @@ morph_vector_gen( REGION *or, void *vseq, void *a, void *b ) if( im_prepare( ir, &s ) ) return( -1 ); -#ifdef DEBUG +#ifdef DEBUG_VERBOSE printf( "morph_vector_gen: preparing %dx%d@%dx%d pixels\n", s.width, s.height, s.left, s.top ); -#endif /*DEBUG*/ +#endif /*DEBUG_VERBOSE*/ for( j = 0; j < morph->n_pass; j++ ) vips_executor_set_program( &executor[j],