turn on seq mode automatically in cli

cli operations turn on seq mode automatically when they can

vips_operation_get_flags() added: lets you attach a set of flags to an
operation

flags for now are "nocache" (replacing the old nocache system) and "seqential"

if vips_object_set_argument_from_string() from string sees "seq" flag on the
object for which it is setting the arg, it enables sequential mode

all operations which can run sequentially have been tagged

the operation printer knows about flags and can display them
This commit is contained in:
John Cupitt 2012-07-10 10:51:40 +01:00
parent af1f2b47c1
commit 643dc28950
24 changed files with 178 additions and 34 deletions

View File

@ -12,6 +12,11 @@
- better thread safety for vips8 operation dispatch - better thread safety for vips8 operation dispatch
- better thread safety for upstream / downstream image linking - better thread safety for upstream / downstream image linking
- added "rs" open mode, removed "rd" - added "rs" open mode, removed "rd"
- added vips_operation_get_flags() ... system for attaching sets of flags to
operations
- added VIPS_OPERATION_SEQUENTIAL flag
- vips8 command-line interface uses this to turn sequential mode on
automatically when possible
18/6/12 started 7.28.9 18/6/12 started 7.28.9
- slightly more memory debugging output - slightly more memory debugging output

1
TODO
View File

@ -1,4 +1,3 @@
- test "rs" mode - test "rs" mode
can't see the code for "rd" mode? can't see the code for "rd" mode?

View File

@ -370,6 +370,7 @@ vips_arithmetic_class_init( VipsArithmeticClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
gobject_class->set_property = vips_object_set_property; gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property; gobject_class->get_property = vips_object_get_property;
@ -378,6 +379,8 @@ vips_arithmetic_class_init( VipsArithmeticClass *class )
vobject_class->description = _( "arithmetic operations" ); vobject_class->description = _( "arithmetic operations" );
vobject_class->build = vips_arithmetic_build; vobject_class->build = vips_arithmetic_build;
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
VIPS_ARG_IMAGE( class, "out", 100, VIPS_ARG_IMAGE( class, "out", 100,
_( "Output" ), _( "Output" ),
_( "Output image" ), _( "Output image" ),

View File

@ -163,6 +163,7 @@ vips_bandary_class_init( VipsBandaryClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
VIPS_DEBUG_MSG( "vips_bandary_class_init\n" ); VIPS_DEBUG_MSG( "vips_bandary_class_init\n" );
@ -173,6 +174,7 @@ vips_bandary_class_init( VipsBandaryClass *class )
vobject_class->description = _( "operations on image bands" ); vobject_class->description = _( "operations on image bands" );
vobject_class->build = vips_bandary_build; vobject_class->build = vips_bandary_build;
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
} }
static void static void

View File

@ -462,6 +462,7 @@ vips_cast_class_init( VipsCastClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
VIPS_DEBUG_MSG( "vips_cast_class_init\n" ); VIPS_DEBUG_MSG( "vips_cast_class_init\n" );
@ -472,6 +473,8 @@ vips_cast_class_init( VipsCastClass *class )
vobject_class->description = _( "cast an image" ); vobject_class->description = _( "cast an image" );
vobject_class->build = vips_cast_build; vobject_class->build = vips_cast_build;
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
VIPS_ARG_IMAGE( class, "in", 1, VIPS_ARG_IMAGE( class, "in", 1,
_( "Input" ), _( "Input" ),
_( "Input image" ), _( "Input image" ),

View File

@ -304,6 +304,7 @@ vips_copy_class_init( VipsCopyClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
VIPS_DEBUG_MSG( "vips_copy_class_init\n" ); VIPS_DEBUG_MSG( "vips_copy_class_init\n" );
@ -314,6 +315,8 @@ vips_copy_class_init( VipsCopyClass *class )
vobject_class->description = _( "copy an image" ); vobject_class->description = _( "copy an image" );
vobject_class->build = vips_copy_build; vobject_class->build = vips_copy_build;
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
VIPS_ARG_IMAGE( class, "in", 1, VIPS_ARG_IMAGE( class, "in", 1,
_( "Input" ), _( "Input" ),
_( "Input image" ), _( "Input image" ),

View File

@ -507,6 +507,7 @@ vips_embed_class_init( VipsEmbedClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
VIPS_DEBUG_MSG( "vips_embed_class_init\n" ); VIPS_DEBUG_MSG( "vips_embed_class_init\n" );
@ -517,6 +518,8 @@ vips_embed_class_init( VipsEmbedClass *class )
vobject_class->description = _( "embed an image in a larger image" ); vobject_class->description = _( "embed an image in a larger image" );
vobject_class->build = vips_embed_build; vobject_class->build = vips_embed_build;
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
VIPS_ARG_IMAGE( class, "in", -1, VIPS_ARG_IMAGE( class, "in", -1,
_( "Input" ), _( "Input" ),
_( "Input image" ), _( "Input image" ),

View File

@ -180,6 +180,7 @@ vips_extract_area_class_init( VipsExtractAreaClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
VIPS_DEBUG_MSG( "vips_extract_area_class_init\n" ); VIPS_DEBUG_MSG( "vips_extract_area_class_init\n" );
@ -190,6 +191,8 @@ vips_extract_area_class_init( VipsExtractAreaClass *class )
vobject_class->description = _( "extract an area from an image" ); vobject_class->description = _( "extract an area from an image" );
vobject_class->build = vips_extract_area_build; vobject_class->build = vips_extract_area_build;
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
VIPS_ARG_IMAGE( class, "input", 0, VIPS_ARG_IMAGE( class, "input", 0,
_( "Input" ), _( "Input" ),
_( "Input image" ), _( "Input image" ),

View File

@ -358,6 +358,7 @@ vips_flatten_class_init( VipsFlattenClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
VIPS_DEBUG_MSG( "vips_flatten_class_init\n" ); VIPS_DEBUG_MSG( "vips_flatten_class_init\n" );
@ -368,6 +369,8 @@ vips_flatten_class_init( VipsFlattenClass *class )
vobject_class->description = _( "flatten alpha out of an image" ); vobject_class->description = _( "flatten alpha out of an image" );
vobject_class->build = vips_flatten_build; vobject_class->build = vips_flatten_build;
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
VIPS_ARG_IMAGE( class, "in", 1, VIPS_ARG_IMAGE( class, "in", 1,
_( "Input" ), _( "Input" ),
_( "Input image" ), _( "Input image" ),

View File

@ -458,6 +458,7 @@ vips_ifthenelse_class_init( VipsIfthenelseClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
VIPS_DEBUG_MSG( "vips_ifthenelse_class_init\n" ); VIPS_DEBUG_MSG( "vips_ifthenelse_class_init\n" );
@ -468,6 +469,8 @@ vips_ifthenelse_class_init( VipsIfthenelseClass *class )
vobject_class->description = _( "ifthenelse an image" ); vobject_class->description = _( "ifthenelse an image" );
vobject_class->build = vips_ifthenelse_build; vobject_class->build = vips_ifthenelse_build;
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
VIPS_ARG_IMAGE( class, "cond", -2, VIPS_ARG_IMAGE( class, "cond", -2,
_( "Condition" ), _( "Condition" ),
_( "Condition input image" ), _( "Condition input image" ),

View File

@ -339,6 +339,7 @@ vips_insert_class_init( VipsInsertClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
VIPS_DEBUG_MSG( "vips_insert_class_init\n" ); VIPS_DEBUG_MSG( "vips_insert_class_init\n" );
@ -349,6 +350,8 @@ vips_insert_class_init( VipsInsertClass *class )
vobject_class->description = _( "insert an image" ); vobject_class->description = _( "insert an image" );
vobject_class->build = vips_insert_build; vobject_class->build = vips_insert_build;
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
VIPS_ARG_IMAGE( class, "main", -1, VIPS_ARG_IMAGE( class, "main", -1,
_( "Main" ), _( "Main" ),
_( "Main input image" ), _( "Main input image" ),

View File

@ -200,6 +200,7 @@ vips_join_class_init( VipsJoinClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
VIPS_DEBUG_MSG( "vips_join_class_init\n" ); VIPS_DEBUG_MSG( "vips_join_class_init\n" );
@ -210,6 +211,8 @@ vips_join_class_init( VipsJoinClass *class )
vobject_class->description = _( "join a pair of images" ); vobject_class->description = _( "join a pair of images" );
vobject_class->build = vips_join_build; vobject_class->build = vips_join_build;
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
VIPS_ARG_IMAGE( class, "in1", -1, VIPS_ARG_IMAGE( class, "in1", -1,
_( "in1" ), _( "in1" ),
_( "First input image" ), _( "First input image" ),

View File

@ -188,6 +188,7 @@ vips_recomb_class_init( VipsRecombClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class; VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
gobject_class->set_property = vips_object_set_property; gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property; gobject_class->get_property = vips_object_get_property;
@ -196,6 +197,8 @@ vips_recomb_class_init( VipsRecombClass *class )
object_class->description = _( "linear recombination with matrix" ); object_class->description = _( "linear recombination with matrix" );
object_class->build = vips_recomb_build; object_class->build = vips_recomb_build;
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
VIPS_ARG_IMAGE( class, "in", 0, VIPS_ARG_IMAGE( class, "in", 0,
_( "Input" ), _( "Input" ),
_( "Input image argument" ), _( "Input image argument" ),

View File

@ -702,7 +702,7 @@ vips_foreign_load_temp( VipsForeignLoad *load )
/* You can't reuse sequential operations. /* You can't reuse sequential operations.
*/ */
vips_operation_set_nocache( VIPS_OPERATION( load ), TRUE ); load->nocache = TRUE;
return( vips_image_new() ); return( vips_image_new() );
} }
@ -889,11 +889,26 @@ vips_foreign_load_build( VipsObject *object )
return( 0 ); return( 0 );
} }
static VipsOperationFlags
vips_foreign_load_real_get_flags( VipsOperation *operation )
{
VipsForeignLoad *load = VIPS_FOREIGN_LOAD( operation );
VipsOperationFlags flags;
flags = VIPS_OPERATION_CLASS( vips_foreign_load_parent_class )->
get_flags( operation );
if( load->nocache )
flags |= VIPS_OPERATION_NOCACHE;
return( flags );
}
static void static void
vips_foreign_load_class_init( VipsForeignLoadClass *class ) vips_foreign_load_class_init( VipsForeignLoadClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class; VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsOperationClass *operation_class = (VipsOperationClass *) class;
gobject_class->dispose = vips_foreign_load_dispose; gobject_class->dispose = vips_foreign_load_dispose;
gobject_class->set_property = vips_object_set_property; gobject_class->set_property = vips_object_set_property;
@ -905,6 +920,8 @@ vips_foreign_load_class_init( VipsForeignLoadClass *class )
object_class->nickname = "fileload"; object_class->nickname = "fileload";
object_class->description = _( "file loaders" ); object_class->description = _( "file loaders" );
operation_class->get_flags = vips_foreign_load_real_get_flags;
VIPS_ARG_IMAGE( class, "out", 2, VIPS_ARG_IMAGE( class, "out", 2,
_( "Output" ), _( "Output" ),
_( "Output image" ), _( "Output image" ),

View File

@ -63,6 +63,7 @@ vips_scan_headers = \
${top_srcdir}/libvips/include/vips/conversion.h \ ${top_srcdir}/libvips/include/vips/conversion.h \
${top_srcdir}/libvips/include/vips/util.h \ ${top_srcdir}/libvips/include/vips/util.h \
${top_srcdir}/libvips/include/vips/image.h \ ${top_srcdir}/libvips/include/vips/image.h \
${top_srcdir}/libvips/include/vips/operation.h \
${top_srcdir}/libvips/include/vips/object.h ${top_srcdir}/libvips/include/vips/object.h
enumtypes.h: $(vips_scan_headers) Makefile enumtypes.h: $(vips_scan_headers) Makefile

View File

@ -57,6 +57,9 @@ GType vips_band_format_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_BAND_FORMAT (vips_band_format_get_type()) #define VIPS_TYPE_BAND_FORMAT (vips_band_format_get_type())
GType vips_coding_get_type (void) G_GNUC_CONST; GType vips_coding_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_CODING (vips_coding_get_type()) #define VIPS_TYPE_CODING (vips_coding_get_type())
/* enumerations from "../../../libvips/include/vips/operation.h" */
GType vips_operation_flags_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_OPERATION_FLAGS (vips_operation_flags_get_type())
/* enumerations from "../../../libvips/include/vips/object.h" */ /* enumerations from "../../../libvips/include/vips/object.h" */
GType vips_argument_flags_get_type (void) G_GNUC_CONST; GType vips_argument_flags_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_ARGUMENT_FLAGS (vips_argument_flags_get_type()) #define VIPS_TYPE_ARGUMENT_FLAGS (vips_argument_flags_get_type())

View File

@ -136,6 +136,10 @@ typedef struct _VipsForeignLoad {
* disc foreign or a memory buffer. This must be set by ->load(). * disc foreign or a memory buffer. This must be set by ->load().
*/ */
VipsImage *real; VipsImage *real;
/* Set this to tag the operation as nocache.
*/
gboolean nocache;
} VipsForeignLoad; } VipsForeignLoad;
typedef struct _VipsForeignLoadClass { typedef struct _VipsForeignLoadClass {

View File

@ -36,6 +36,27 @@ extern "C" {
#include <vips/vips.h> #include <vips/vips.h>
/**
* VipsOperationFlags:
* @VIPS_OPERATION_NONE: no flags
* @VIPS_OPERATION_SEQUENTIAL: can work sequentially
* @VIPS_OPERATION_NOCACHE: must not be cached
*
* Flags we associate with an operation.
*
* @VIPS_OPERATION_SEQUENTIAL means that the operation works like vips_copy:
* it can happily process images top-to-bottom with only small non-local
* references.
*
* @VIPS_OPERATION_NOCACHE means that the operation must not be cached by
* vips.
*/
typedef enum /*< flags >*/ {
VIPS_OPERATION_NONE = 0,
VIPS_OPERATION_SEQUENTIAL = 1,
VIPS_OPERATION_NOCACHE = 2
} VipsOperationFlags;
#define VIPS_TYPE_OPERATION (vips_operation_get_type()) #define VIPS_TYPE_OPERATION (vips_operation_get_type())
#define VIPS_OPERATION( obj ) \ #define VIPS_OPERATION( obj ) \
(G_TYPE_CHECK_INSTANCE_CAST( (obj), \ (G_TYPE_CHECK_INSTANCE_CAST( (obj), \
@ -66,12 +87,6 @@ typedef struct _VipsOperation {
guint hash; guint hash;
gboolean found_hash; gboolean found_hash;
/* Set this before the end of _build() to stop this operation from
* being cached. Some things, like sequential read from a TIFF file,
* can't be reused.
*/
gboolean nocache;
} VipsOperation; } VipsOperation;
typedef struct _VipsOperationClass { typedef struct _VipsOperationClass {
@ -80,10 +95,17 @@ typedef struct _VipsOperationClass {
/* Print the usage message. /* Print the usage message.
*/ */
void (*usage)( struct _VipsOperationClass *, VipsBuf * ); void (*usage)( struct _VipsOperationClass *, VipsBuf * );
/* Return a set of operation flags. If @get_flags is NULL, just use
* flags.
*/
VipsOperationFlags (*get_flags)( VipsOperation * );
VipsOperationFlags flags;
} VipsOperationClass; } VipsOperationClass;
GType vips_operation_get_type( void ); GType vips_operation_get_type( void );
VipsOperationFlags vips_operation_get_flags( VipsOperation *operation );
void vips_operation_class_print_usage( VipsOperationClass *operation_class ); void vips_operation_class_print_usage( VipsOperationClass *operation_class );
int vips_operation_call_valist( VipsOperation *operation, va_list ap ); int vips_operation_call_valist( VipsOperation *operation, va_list ap );
@ -96,7 +118,6 @@ void vips_call_options( GOptionGroup *group, VipsOperation *operation );
int vips_call_argv( VipsOperation *operation, int argc, char **argv ); int vips_call_argv( VipsOperation *operation, int argc, char **argv );
void vips_cache_drop_all( void ); void vips_cache_drop_all( void );
void vips_operation_set_nocache( VipsOperation *operation, gboolean nocache );
int vips_cache_operation_buildp( VipsOperation **operation ); int vips_cache_operation_buildp( VipsOperation **operation );
VipsOperation *vips_cache_operation_build( VipsOperation *operation ); VipsOperation *vips_cache_operation_build( VipsOperation *operation );
void vips_cache_print( void ); void vips_cache_print( void );

View File

@ -46,6 +46,7 @@ vips_scan_headers = \
${top_srcdir}/libvips/include/vips/arithmetic.h \ ${top_srcdir}/libvips/include/vips/arithmetic.h \
${top_srcdir}/libvips/include/vips/util.h \ ${top_srcdir}/libvips/include/vips/util.h \
${top_srcdir}/libvips/include/vips/image.h \ ${top_srcdir}/libvips/include/vips/image.h \
${top_srcdir}/libvips/include/vips/operation.h \
${top_srcdir}/libvips/include/vips/object.h ${top_srcdir}/libvips/include/vips/object.h
enumtypes.c: $(vips_scan_headers) Makefile enumtypes.c: $(vips_scan_headers) Makefile

View File

@ -693,7 +693,8 @@ vips_cache_operation_buildp( VipsOperation **operation )
if( !hit ) { if( !hit ) {
if( vips__cache_trace ) { if( vips__cache_trace ) {
if( (*operation)->nocache ) if( vips_operation_get_flags( *operation ) &
VIPS_OPERATION_NOCACHE )
printf( "vips cache: uncacheable %p\n ", printf( "vips cache: uncacheable %p\n ",
*operation ); *operation );
else else
@ -706,7 +707,8 @@ vips_cache_operation_buildp( VipsOperation **operation )
g_mutex_lock( vips_cache_lock ); g_mutex_lock( vips_cache_lock );
if( !(*operation)->nocache ) { if( !(vips_operation_get_flags( *operation ) &
VIPS_OPERATION_NOCACHE) ) {
vips_cache_ref( *operation ); vips_cache_ref( *operation );
g_hash_table_insert( vips_cache_table, g_hash_table_insert( vips_cache_table,
*operation, *operation ); *operation, *operation );

View File

@ -492,6 +492,25 @@ vips_coding_get_type( void )
return( etype ); return( etype );
} }
/* enumerations from "../../libvips/include/vips/operation.h" */
GType
vips_operation_flags_get_type( void )
{
static GType etype = 0;
if( etype == 0 ) {
static const GFlagsValue values[] = {
{VIPS_OPERATION_NONE, "VIPS_OPERATION_NONE", "none"},
{VIPS_OPERATION_SEQUENTIAL, "VIPS_OPERATION_SEQUENTIAL", "sequential"},
{VIPS_OPERATION_NOCACHE, "VIPS_OPERATION_NOCACHE", "nocache"},
{0, NULL, NULL}
};
etype = g_flags_register_static( "VipsOperationFlags", values );
}
return( etype );
}
/* enumerations from "../../libvips/include/vips/object.h" */ /* enumerations from "../../libvips/include/vips/object.h" */
GType GType
vips_argument_flags_get_type( void ) vips_argument_flags_get_type( void )

View File

@ -1466,12 +1466,27 @@ vips_object_set_argument_from_string( VipsObject *object,
if( g_type_is_a( otype, VIPS_TYPE_IMAGE ) ) { if( g_type_is_a( otype, VIPS_TYPE_IMAGE ) ) {
VipsImage *out; VipsImage *out;
VipsOperationFlags flags;
flags = 0;
if( VIPS_IS_OPERATION( object ) )
flags = vips_operation_get_flags(
VIPS_OPERATION( object ) );
/* Read the filename. vips_foreign_load_options() /* Read the filename. vips_foreign_load_options()
* handles embedded options. * handles embedded options.
*/ */
if( vips_foreign_load_options( value, &out, NULL ) ) if( flags & VIPS_OPERATION_SEQUENTIAL ) {
return( -1 ); if( vips_foreign_load_options( value, &out,
"sequential", TRUE,
NULL ) )
return( -1 );
}
else {
if( vips_foreign_load_options( value, &out,
NULL ) )
return( -1 );
}
g_value_init( &gvalue, VIPS_TYPE_IMAGE ); g_value_init( &gvalue, VIPS_TYPE_IMAGE );
g_value_set_object( &gvalue, out ); g_value_set_object( &gvalue, out );

View File

@ -148,6 +148,24 @@ vips_operation_usage( VipsOperationClass *class, VipsBuf *buf )
vips_argument_class_map( object_class, vips_argument_class_map( object_class,
(VipsArgumentClassMapFn) vips_operation_class_usage_arg, (VipsArgumentClassMapFn) vips_operation_class_usage_arg,
buf, &usage ); buf, &usage );
/* Show flags.
*/
if( class->flags ) {
GFlagsValue *value;
VipsOperationFlags flags;
GFlagsClass *flags_class =
g_type_class_ref( VIPS_TYPE_OPERATION_FLAGS );
vips_buf_appendf( buf, "operation flags: " );
flags = class->flags;
while( flags && (value =
g_flags_get_first_value( flags_class, flags )) ) {
vips_buf_appendf( buf, "%s ", value->value_nick );
flags &= ~value->value;
}
vips_buf_appends( buf, "\n" );
}
} }
static void * static void *
@ -233,6 +251,14 @@ vips_operation_summary( VipsObject *object, VipsBuf *buf )
summary( object, buf ); summary( object, buf );
} }
static VipsOperationFlags
vips_operation_real_get_flags( VipsOperation *operation )
{
VipsOperationClass *class = VIPS_OPERATION_GET_CLASS( operation );
return( class->flags );
}
static void static void
vips_operation_class_init( VipsOperationClass *class ) vips_operation_class_init( VipsOperationClass *class )
{ {
@ -248,6 +274,7 @@ vips_operation_class_init( VipsOperationClass *class )
vobject_class->dump = vips_operation_dump; vobject_class->dump = vips_operation_dump;
class->usage = vips_operation_usage; class->usage = vips_operation_usage;
class->get_flags = vips_operation_real_get_flags;
} }
static void static void
@ -257,6 +284,22 @@ vips_operation_init( VipsOperation *operation )
*/ */
} }
/**
* vips_operation_get_flags:
* @operation: operation to fetch flags from
*
* Returns the set of flags for this operation.
*
* Returns: 0 on success, or -1 on error.
*/
VipsOperationFlags
vips_operation_get_flags( VipsOperation *operation )
{
VipsOperationClass *class = VIPS_OPERATION_GET_CLASS( operation );
return( class->get_flags( operation ) );
}
/** /**
* vips_operation_class_print_usage: (skip) * vips_operation_class_print_usage: (skip)
* @operation_class: class to print usage for * @operation_class: class to print usage for
@ -913,24 +956,3 @@ vips_call_argv( VipsOperation *operation, int argc, char **argv )
return( 0 ); return( 0 );
} }
/**
* vips_operation_set_nocache:
* @operation: operation to set
* @nocache: TRUE means don't cache this operation
*
* Set this before the end of _build() to stop this operation being cached.
* Some operations, like sequential read from a TIFF file, for example, cannot
* be reused.
*/
void
vips_operation_set_nocache( VipsOperation *operation, gboolean nocache )
{
#ifdef VIPS_DEBUG
printf( "vips_operation_set_nocache: " );
vips_object_print_name( VIPS_OBJECT( operation ) );
printf( " %d\n", nocache );
#endif /*VIPS_DEBUG*/
operation->nocache = nocache;
}

View File

@ -360,6 +360,7 @@ vips_shrink_class_init( VipsShrinkClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
VIPS_DEBUG_MSG( "vips_shrink_class_init\n" ); VIPS_DEBUG_MSG( "vips_shrink_class_init\n" );
@ -370,6 +371,8 @@ vips_shrink_class_init( VipsShrinkClass *class )
vobject_class->description = _( "shrink an image" ); vobject_class->description = _( "shrink an image" );
vobject_class->build = vips_shrink_build; vobject_class->build = vips_shrink_build;
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
VIPS_ARG_DOUBLE( class, "xshrink", 8, VIPS_ARG_DOUBLE( class, "xshrink", 8,
_( "Xshrink" ), _( "Xshrink" ),
_( "Horizontal shrink factor" ), _( "Horizontal shrink factor" ),