From 643dc28950dec40397e25db38bc0894576b1c444 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 10 Jul 2012 10:51:40 +0100 Subject: [PATCH] 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 --- ChangeLog | 5 +++ TODO | 1 - libvips/arithmetic/arithmetic.c | 3 ++ libvips/conversion/bandary.c | 2 + libvips/conversion/cast.c | 3 ++ libvips/conversion/copy.c | 3 ++ libvips/conversion/embed.c | 3 ++ libvips/conversion/extract.c | 3 ++ libvips/conversion/flatten.c | 3 ++ libvips/conversion/ifthenelse.c | 3 ++ libvips/conversion/insert.c | 3 ++ libvips/conversion/join.c | 3 ++ libvips/conversion/recomb.c | 3 ++ libvips/foreign/foreign.c | 19 +++++++++- libvips/include/vips/Makefile.am | 1 + libvips/include/vips/enumtypes.h | 3 ++ libvips/include/vips/foreign.h | 4 ++ libvips/include/vips/operation.h | 35 +++++++++++++---- libvips/iofuncs/Makefile.am | 1 + libvips/iofuncs/cache.c | 6 ++- libvips/iofuncs/enumtypes.c | 19 ++++++++++ libvips/iofuncs/object.c | 19 +++++++++- libvips/iofuncs/operation.c | 64 +++++++++++++++++++++----------- libvips/resample/shrink.c | 3 ++ 24 files changed, 178 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5af03869..e44fe7dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,11 @@ - better thread safety for vips8 operation dispatch - better thread safety for upstream / downstream image linking - 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 - slightly more memory debugging output diff --git a/TODO b/TODO index a1a19b70..06c486a9 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,3 @@ - - test "rs" mode can't see the code for "rd" mode? diff --git a/libvips/arithmetic/arithmetic.c b/libvips/arithmetic/arithmetic.c index 3fa79cd4..b746dccb 100644 --- a/libvips/arithmetic/arithmetic.c +++ b/libvips/arithmetic/arithmetic.c @@ -370,6 +370,7 @@ vips_arithmetic_class_init( VipsArithmeticClass *class ) { GObjectClass *gobject_class = G_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->get_property = vips_object_get_property; @@ -378,6 +379,8 @@ vips_arithmetic_class_init( VipsArithmeticClass *class ) vobject_class->description = _( "arithmetic operations" ); vobject_class->build = vips_arithmetic_build; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + VIPS_ARG_IMAGE( class, "out", 100, _( "Output" ), _( "Output image" ), diff --git a/libvips/conversion/bandary.c b/libvips/conversion/bandary.c index 673825ea..45bb4647 100644 --- a/libvips/conversion/bandary.c +++ b/libvips/conversion/bandary.c @@ -163,6 +163,7 @@ vips_bandary_class_init( VipsBandaryClass *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_bandary_class_init\n" ); @@ -173,6 +174,7 @@ vips_bandary_class_init( VipsBandaryClass *class ) vobject_class->description = _( "operations on image bands" ); vobject_class->build = vips_bandary_build; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; } static void diff --git a/libvips/conversion/cast.c b/libvips/conversion/cast.c index a18c2357..ee420694 100644 --- a/libvips/conversion/cast.c +++ b/libvips/conversion/cast.c @@ -462,6 +462,7 @@ vips_cast_class_init( VipsCastClass *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_cast_class_init\n" ); @@ -472,6 +473,8 @@ vips_cast_class_init( VipsCastClass *class ) vobject_class->description = _( "cast an image" ); vobject_class->build = vips_cast_build; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), _( "Input image" ), diff --git a/libvips/conversion/copy.c b/libvips/conversion/copy.c index 7570ef70..73927fd0 100644 --- a/libvips/conversion/copy.c +++ b/libvips/conversion/copy.c @@ -304,6 +304,7 @@ vips_copy_class_init( VipsCopyClass *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_copy_class_init\n" ); @@ -314,6 +315,8 @@ vips_copy_class_init( VipsCopyClass *class ) vobject_class->description = _( "copy an image" ); vobject_class->build = vips_copy_build; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), _( "Input image" ), diff --git a/libvips/conversion/embed.c b/libvips/conversion/embed.c index 1cf54d50..e90203a9 100644 --- a/libvips/conversion/embed.c +++ b/libvips/conversion/embed.c @@ -507,6 +507,7 @@ vips_embed_class_init( VipsEmbedClass *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_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->build = vips_embed_build; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + VIPS_ARG_IMAGE( class, "in", -1, _( "Input" ), _( "Input image" ), diff --git a/libvips/conversion/extract.c b/libvips/conversion/extract.c index 495c1005..d1b334e0 100644 --- a/libvips/conversion/extract.c +++ b/libvips/conversion/extract.c @@ -180,6 +180,7 @@ vips_extract_area_class_init( VipsExtractAreaClass *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_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->build = vips_extract_area_build; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + VIPS_ARG_IMAGE( class, "input", 0, _( "Input" ), _( "Input image" ), diff --git a/libvips/conversion/flatten.c b/libvips/conversion/flatten.c index 93946ddc..d4cd0461 100644 --- a/libvips/conversion/flatten.c +++ b/libvips/conversion/flatten.c @@ -358,6 +358,7 @@ vips_flatten_class_init( VipsFlattenClass *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_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->build = vips_flatten_build; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + VIPS_ARG_IMAGE( class, "in", 1, _( "Input" ), _( "Input image" ), diff --git a/libvips/conversion/ifthenelse.c b/libvips/conversion/ifthenelse.c index e0756e33..e2ac66a2 100644 --- a/libvips/conversion/ifthenelse.c +++ b/libvips/conversion/ifthenelse.c @@ -458,6 +458,7 @@ vips_ifthenelse_class_init( VipsIfthenelseClass *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_ifthenelse_class_init\n" ); @@ -468,6 +469,8 @@ vips_ifthenelse_class_init( VipsIfthenelseClass *class ) vobject_class->description = _( "ifthenelse an image" ); vobject_class->build = vips_ifthenelse_build; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + VIPS_ARG_IMAGE( class, "cond", -2, _( "Condition" ), _( "Condition input image" ), diff --git a/libvips/conversion/insert.c b/libvips/conversion/insert.c index 6b39c1cd..c100fa82 100644 --- a/libvips/conversion/insert.c +++ b/libvips/conversion/insert.c @@ -339,6 +339,7 @@ vips_insert_class_init( VipsInsertClass *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_insert_class_init\n" ); @@ -349,6 +350,8 @@ vips_insert_class_init( VipsInsertClass *class ) vobject_class->description = _( "insert an image" ); vobject_class->build = vips_insert_build; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + VIPS_ARG_IMAGE( class, "main", -1, _( "Main" ), _( "Main input image" ), diff --git a/libvips/conversion/join.c b/libvips/conversion/join.c index 815f4ccb..bcc6e307 100644 --- a/libvips/conversion/join.c +++ b/libvips/conversion/join.c @@ -200,6 +200,7 @@ vips_join_class_init( VipsJoinClass *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_join_class_init\n" ); @@ -210,6 +211,8 @@ vips_join_class_init( VipsJoinClass *class ) vobject_class->description = _( "join a pair of images" ); vobject_class->build = vips_join_build; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + VIPS_ARG_IMAGE( class, "in1", -1, _( "in1" ), _( "First input image" ), diff --git a/libvips/conversion/recomb.c b/libvips/conversion/recomb.c index 6d1b7ce8..197674ea 100644 --- a/libvips/conversion/recomb.c +++ b/libvips/conversion/recomb.c @@ -188,6 +188,7 @@ vips_recomb_class_init( VipsRecombClass *class ) { GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class ); gobject_class->set_property = vips_object_set_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->build = vips_recomb_build; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + VIPS_ARG_IMAGE( class, "in", 0, _( "Input" ), _( "Input image argument" ), diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 1ca49054..7787b017 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -702,7 +702,7 @@ vips_foreign_load_temp( VipsForeignLoad *load ) /* You can't reuse sequential operations. */ - vips_operation_set_nocache( VIPS_OPERATION( load ), TRUE ); + load->nocache = TRUE; return( vips_image_new() ); } @@ -889,11 +889,26 @@ vips_foreign_load_build( VipsObject *object ) 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 vips_foreign_load_class_init( VipsForeignLoadClass *class ) { GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsOperationClass *operation_class = (VipsOperationClass *) class; gobject_class->dispose = vips_foreign_load_dispose; 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->description = _( "file loaders" ); + operation_class->get_flags = vips_foreign_load_real_get_flags; + VIPS_ARG_IMAGE( class, "out", 2, _( "Output" ), _( "Output image" ), diff --git a/libvips/include/vips/Makefile.am b/libvips/include/vips/Makefile.am index ed64a858..138c57a4 100644 --- a/libvips/include/vips/Makefile.am +++ b/libvips/include/vips/Makefile.am @@ -63,6 +63,7 @@ vips_scan_headers = \ ${top_srcdir}/libvips/include/vips/conversion.h \ ${top_srcdir}/libvips/include/vips/util.h \ ${top_srcdir}/libvips/include/vips/image.h \ + ${top_srcdir}/libvips/include/vips/operation.h \ ${top_srcdir}/libvips/include/vips/object.h enumtypes.h: $(vips_scan_headers) Makefile diff --git a/libvips/include/vips/enumtypes.h b/libvips/include/vips/enumtypes.h index e313bd2e..44bc558d 100644 --- a/libvips/include/vips/enumtypes.h +++ b/libvips/include/vips/enumtypes.h @@ -57,6 +57,9 @@ GType vips_band_format_get_type (void) G_GNUC_CONST; #define VIPS_TYPE_BAND_FORMAT (vips_band_format_get_type()) GType vips_coding_get_type (void) G_GNUC_CONST; #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" */ GType vips_argument_flags_get_type (void) G_GNUC_CONST; #define VIPS_TYPE_ARGUMENT_FLAGS (vips_argument_flags_get_type()) diff --git a/libvips/include/vips/foreign.h b/libvips/include/vips/foreign.h index a1d42e40..cbe30807 100644 --- a/libvips/include/vips/foreign.h +++ b/libvips/include/vips/foreign.h @@ -136,6 +136,10 @@ typedef struct _VipsForeignLoad { * disc foreign or a memory buffer. This must be set by ->load(). */ VipsImage *real; + + /* Set this to tag the operation as nocache. + */ + gboolean nocache; } VipsForeignLoad; typedef struct _VipsForeignLoadClass { diff --git a/libvips/include/vips/operation.h b/libvips/include/vips/operation.h index bae34ae6..8689dcc2 100644 --- a/libvips/include/vips/operation.h +++ b/libvips/include/vips/operation.h @@ -36,6 +36,27 @@ extern "C" { #include +/** + * 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_OPERATION( obj ) \ (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ @@ -66,12 +87,6 @@ typedef struct _VipsOperation { guint 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; typedef struct _VipsOperationClass { @@ -80,10 +95,17 @@ typedef struct _VipsOperationClass { /* Print the usage message. */ 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; GType vips_operation_get_type( void ); +VipsOperationFlags vips_operation_get_flags( VipsOperation *operation ); void vips_operation_class_print_usage( VipsOperationClass *operation_class ); 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 ); void vips_cache_drop_all( void ); -void vips_operation_set_nocache( VipsOperation *operation, gboolean nocache ); int vips_cache_operation_buildp( VipsOperation **operation ); VipsOperation *vips_cache_operation_build( VipsOperation *operation ); void vips_cache_print( void ); diff --git a/libvips/iofuncs/Makefile.am b/libvips/iofuncs/Makefile.am index 0d538ae4..3c9cca3e 100644 --- a/libvips/iofuncs/Makefile.am +++ b/libvips/iofuncs/Makefile.am @@ -46,6 +46,7 @@ vips_scan_headers = \ ${top_srcdir}/libvips/include/vips/arithmetic.h \ ${top_srcdir}/libvips/include/vips/util.h \ ${top_srcdir}/libvips/include/vips/image.h \ + ${top_srcdir}/libvips/include/vips/operation.h \ ${top_srcdir}/libvips/include/vips/object.h enumtypes.c: $(vips_scan_headers) Makefile diff --git a/libvips/iofuncs/cache.c b/libvips/iofuncs/cache.c index 920b3591..55273763 100644 --- a/libvips/iofuncs/cache.c +++ b/libvips/iofuncs/cache.c @@ -693,7 +693,8 @@ vips_cache_operation_buildp( VipsOperation **operation ) if( !hit ) { if( vips__cache_trace ) { - if( (*operation)->nocache ) + if( vips_operation_get_flags( *operation ) & + VIPS_OPERATION_NOCACHE ) printf( "vips cache: uncacheable %p\n ", *operation ); else @@ -706,7 +707,8 @@ vips_cache_operation_buildp( VipsOperation **operation ) g_mutex_lock( vips_cache_lock ); - if( !(*operation)->nocache ) { + if( !(vips_operation_get_flags( *operation ) & + VIPS_OPERATION_NOCACHE) ) { vips_cache_ref( *operation ); g_hash_table_insert( vips_cache_table, *operation, *operation ); diff --git a/libvips/iofuncs/enumtypes.c b/libvips/iofuncs/enumtypes.c index c8eb8554..676d279b 100644 --- a/libvips/iofuncs/enumtypes.c +++ b/libvips/iofuncs/enumtypes.c @@ -492,6 +492,25 @@ vips_coding_get_type( void ) 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" */ GType vips_argument_flags_get_type( void ) diff --git a/libvips/iofuncs/object.c b/libvips/iofuncs/object.c index d809fe48..1c27fde7 100644 --- a/libvips/iofuncs/object.c +++ b/libvips/iofuncs/object.c @@ -1466,12 +1466,27 @@ vips_object_set_argument_from_string( VipsObject *object, if( g_type_is_a( otype, VIPS_TYPE_IMAGE ) ) { 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() * handles embedded options. */ - if( vips_foreign_load_options( value, &out, NULL ) ) - return( -1 ); + if( flags & VIPS_OPERATION_SEQUENTIAL ) { + 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_set_object( &gvalue, out ); diff --git a/libvips/iofuncs/operation.c b/libvips/iofuncs/operation.c index 7c6cda0d..e74e8d33 100644 --- a/libvips/iofuncs/operation.c +++ b/libvips/iofuncs/operation.c @@ -148,6 +148,24 @@ vips_operation_usage( VipsOperationClass *class, VipsBuf *buf ) vips_argument_class_map( object_class, (VipsArgumentClassMapFn) vips_operation_class_usage_arg, 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 * @@ -233,6 +251,14 @@ vips_operation_summary( VipsObject *object, VipsBuf *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 vips_operation_class_init( VipsOperationClass *class ) { @@ -248,6 +274,7 @@ vips_operation_class_init( VipsOperationClass *class ) vobject_class->dump = vips_operation_dump; class->usage = vips_operation_usage; + class->get_flags = vips_operation_real_get_flags; } 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) * @operation_class: class to print usage for @@ -913,24 +956,3 @@ vips_call_argv( VipsOperation *operation, int argc, char **argv ) 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; -} diff --git a/libvips/resample/shrink.c b/libvips/resample/shrink.c index f038c28d..747bdd6b 100644 --- a/libvips/resample/shrink.c +++ b/libvips/resample/shrink.c @@ -360,6 +360,7 @@ vips_shrink_class_init( VipsShrinkClass *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_shrink_class_init\n" ); @@ -370,6 +371,8 @@ vips_shrink_class_init( VipsShrinkClass *class ) vobject_class->description = _( "shrink an image" ); vobject_class->build = vips_shrink_build; + operation_class->flags = VIPS_OPERATION_SEQUENTIAL; + VIPS_ARG_DOUBLE( class, "xshrink", 8, _( "Xshrink" ), _( "Horizontal shrink factor" ),