diff --git a/ChangeLog b/ChangeLog index 9d063433..e7518ec3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,7 @@ - sharpen has a new @sigma param, @radius is deprecated - sharpen allows a much greater range of parameters - better handling of deprecated args in python +- much better handling of arrayimage command-line args 27/1/16 started 8.2.3 - fix a crash with SPARC byte-order labq vips images diff --git a/libvips/conversion/arrayjoin.c b/libvips/conversion/arrayjoin.c index 91de3995..712791c2 100644 --- a/libvips/conversion/arrayjoin.c +++ b/libvips/conversion/arrayjoin.c @@ -134,6 +134,10 @@ vips_arrayjoin_build( VipsObject *object ) return( -1 ); in = vips_array_image_get( join->in, &n ); + /* Array length zero means error. + */ + if( n == 0 ) + return( -1 ); /* Move all input images to a common format and number of bands. */ @@ -291,6 +295,7 @@ vips_arrayjoin_class_init( VipsArrayjoinClass *class ) { GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class ); VIPS_DEBUG_MSG( "vips_arrayjoin_class_init\n" ); @@ -301,6 +306,8 @@ vips_arrayjoin_class_init( VipsArrayjoinClass *class ) vobject_class->description = _( "join an array of images" ); vobject_class->build = vips_arrayjoin_build; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; + VIPS_ARG_BOXED( class, "in", -1, _( "Input" ), _( "Array of input images" ), diff --git a/libvips/include/vips/image.h b/libvips/include/vips/image.h index 1c354757..ee8d7a6b 100644 --- a/libvips/include/vips/image.h +++ b/libvips/include/vips/image.h @@ -493,6 +493,8 @@ int vips_system( const char *cmd_format, ... ) */ VipsArrayImage *vips_array_image_new( VipsImage **array, int n ); VipsArrayImage *vips_array_image_newv( int n, ... ); +VipsArrayImage *vips_array_image_new_from_string( const char *string, + VipsAccess flags ); VipsArrayImage *vips_array_image_empty( void ); VipsArrayImage *vips_array_image_append( VipsArrayImage *array, VipsImage *image ); diff --git a/libvips/iofuncs/object.c b/libvips/iofuncs/object.c index c7412e2a..6e311381 100644 --- a/libvips/iofuncs/object.c +++ b/libvips/iofuncs/object.c @@ -1818,16 +1818,16 @@ vips_object_set_argument_from_string( VipsObject *object, VipsOperationFlags flags; VipsAccess access; - flags = 0; - if( VIPS_IS_OPERATION( object ) ) - flags = vips_operation_get_flags( - VIPS_OPERATION( object ) ); - if( !value ) { vips_object_no_value( object, name ); return( -1 ); } + flags = 0; + if( VIPS_IS_OPERATION( object ) ) + flags = vips_operation_get_flags( + VIPS_OPERATION( object ) ); + /* Read the filename. */ if( flags & VIPS_OPERATION_SEQUENTIAL_UNBUFFERED ) @@ -1850,6 +1850,44 @@ vips_object_set_argument_from_string( VipsObject *object, */ g_object_unref( out ); } + else if( g_type_is_a( otype, VIPS_TYPE_ARRAY_IMAGE ) ) { + /* We have to have a special case for this, we can't just rely + * on transform_g_string_array_image(), since we need to be + * able to set the access hint on the image. + */ + VipsArrayImage *array_image; + VipsOperationFlags flags; + VipsAccess access; + + if( !value ) { + vips_object_no_value( object, name ); + return( -1 ); + } + + flags = 0; + if( VIPS_IS_OPERATION( object ) ) + flags = vips_operation_get_flags( + VIPS_OPERATION( object ) ); + + if( flags & VIPS_OPERATION_SEQUENTIAL_UNBUFFERED ) + access = VIPS_ACCESS_SEQUENTIAL_UNBUFFERED; + else if( flags & VIPS_OPERATION_SEQUENTIAL ) + access = VIPS_ACCESS_SEQUENTIAL; + else + access = VIPS_ACCESS_RANDOM; + + if( !(array_image = + vips_array_image_new_from_string( value, access )) ) + return( -1 ); + + g_value_init( &gvalue, VIPS_TYPE_ARRAY_IMAGE ); + g_value_set_boxed( &gvalue, array_image ); + + /* Setting gvalue will have upped @array_image's count again, + * go back to 1 so that gvalue has the only ref. + */ + vips_area_unref( (VipsArea *) array_image ); + } else if( g_type_is_a( otype, VIPS_TYPE_OBJECT ) && (oclass = g_type_class_ref( otype )) ) { VipsObject *new_object; diff --git a/libvips/iofuncs/type.c b/libvips/iofuncs/type.c index 192e86ea..23ca5919 100644 --- a/libvips/iofuncs/type.c +++ b/libvips/iofuncs/type.c @@ -1089,43 +1089,6 @@ vips_array_double_get_type( void ) return( type ); } -static void -transform_g_string_array_image( const GValue *src_value, GValue *dest_value ) -{ - char *str; - int n; - char *p, *q; - int i; - VipsImage **array; - - /* We need a copy of the string, since we insert \0 during - * scan. - */ - str = g_value_dup_string( src_value ); - - n = 0; - for( p = str; (q = vips_break_token( p, " " )); p = q ) - n += 1; - - g_free( str ); - - vips_value_set_array_image( dest_value, n ); - array = vips_value_get_array_image( dest_value, NULL ); - - str = g_value_dup_string( src_value ); - - for( i = 0, p = str; (q = vips_break_token( p, " " )); i++, p = q ) - if( !(array[i] = vips_image_new_from_file( p, NULL )) ) { - /* Set the dest to length zero to indicate error. - */ - vips_value_set_array_image( dest_value, 0 ); - g_free( str ); - return; - } - - g_free( str ); -} - /** * vips_array_image_new: * @array: (array length=n): array of #VipsImage @@ -1205,6 +1168,52 @@ vips_array_image_newv( int n, ... ) return( (VipsArrayImage *) area ); } +VipsArrayImage * +vips_array_image_new_from_string( const char *string, VipsAccess access ) +{ + char *str; + int n; + VipsArea *area; + VipsImage **array; + char *p, *q; + int i; + + /* We need a copy of the string, since we insert \0 during + * scan. + */ + str = g_strdup( string ); + + n = 0; + for( p = str; (q = vips_break_token( p, " \n\t\r" )); p = q ) + n += 1; + + g_free( str ); + + area = vips_area_new_array_object( n ); + area->type = VIPS_TYPE_IMAGE; + + array = vips_area_get_data( area, NULL, NULL, NULL, NULL ); + + str = g_strdup( string ); + + i = 0; + for( p = str; (q = vips_break_token( p, " \n\t\r" )); p = q ) { + if( !(array[i] = vips_image_new_from_file( p, + "access", access, + NULL )) ) { + vips_area_unref( area ); + g_free( str ); + return( NULL ); + } + + i += 1; + } + + g_free( str ); + + return( (VipsArrayImage *) area ); +} + /** * vips_array_image_empty: * @@ -1284,6 +1293,31 @@ vips_array_image_get( VipsArrayImage *array, int *n ) return( (VipsImage **) VIPS_ARRAY_ADDR( array, 0 ) ); } +static void +transform_g_string_array_image( const GValue *src_value, GValue *dest_value ) +{ + char *str; + VipsArrayImage *array_image; + + str = g_value_dup_string( src_value ); + + /* We can't get access here, just assume nothing. See the special case + * in vips_object_new_from_string() for how we usually get this right. + */ + if( !(array_image = vips_array_image_new_from_string( str, 0 )) ) { + /* Set the dest to length zero to indicate error. + */ + vips_value_set_array_image( dest_value, 0 ); + g_free( str ); + return; + } + + g_free( str ); + + g_value_set_boxed( dest_value, array_image ); + vips_area_unref( (VipsArea *) array_image ); +} + GType vips_array_image_get_type( void ) {