add VIPS_ARGUMENT_MODIFY

a flag for arguments meaning the operator will modify an input

the python binding uses this to take a copy of the arg before calling
This commit is contained in:
John Cupitt 2014-09-15 14:47:34 +01:00
parent a82fa01781
commit c4a3e9a1a0
6 changed files with 25 additions and 10 deletions

View File

@ -5,6 +5,8 @@
- return of vips_init(), but just for bindings - return of vips_init(), but just for bindings
- revised type.c to make it more binding-friendly - revised type.c to make it more binding-friendly
- add @background arg to save: the colour to flatten against - add @background arg to save: the colour to flatten against
- add VIPS_ARGUMENT_MODIFY flag ... used for draw_circle etc, meaning an op
which modifies its argument
8/9/14 started 7.40.9 8/9/14 started 7.40.9
- support jfif resunit "none" - support jfif resunit "none"

View File

@ -115,7 +115,7 @@ vips_draw_class_init( VipsDrawClass *class )
VIPS_ARG_IMAGE( class, "image", 1, VIPS_ARG_IMAGE( class, "image", 1,
_( "Image" ), _( "Image" ),
_( "Image to draw on" ), _( "Image to draw on" ),
VIPS_ARGUMENT_REQUIRED_INPUT, VIPS_ARGUMENT_REQUIRED_INPUT | VIPS_ARGUMENT_MODIFY,
G_STRUCT_OFFSET( VipsDraw, image ) ); G_STRUCT_OFFSET( VipsDraw, image ) );
} }

View File

@ -63,7 +63,8 @@ typedef enum /*< flags >*/ {
VIPS_ARGUMENT_SET_ALWAYS = 8, VIPS_ARGUMENT_SET_ALWAYS = 8,
VIPS_ARGUMENT_INPUT = 16, VIPS_ARGUMENT_INPUT = 16,
VIPS_ARGUMENT_OUTPUT = 32, VIPS_ARGUMENT_OUTPUT = 32,
VIPS_ARGUMENT_DEPRECATED = 64 VIPS_ARGUMENT_DEPRECATED = 64,
VIPS_ARGUMENT_MODIFY = 128
} VipsArgumentFlags; } VipsArgumentFlags;
/* Useful flag combinations. User-visible ones are: /* Useful flag combinations. User-visible ones are:

View File

@ -743,6 +743,7 @@ vips_argument_flags_get_type( void )
{VIPS_ARGUMENT_INPUT, "VIPS_ARGUMENT_INPUT", "input"}, {VIPS_ARGUMENT_INPUT, "VIPS_ARGUMENT_INPUT", "input"},
{VIPS_ARGUMENT_OUTPUT, "VIPS_ARGUMENT_OUTPUT", "output"}, {VIPS_ARGUMENT_OUTPUT, "VIPS_ARGUMENT_OUTPUT", "output"},
{VIPS_ARGUMENT_DEPRECATED, "VIPS_ARGUMENT_DEPRECATED", "deprecated"}, {VIPS_ARGUMENT_DEPRECATED, "VIPS_ARGUMENT_DEPRECATED", "deprecated"},
{VIPS_ARGUMENT_MODIFY, "VIPS_ARGUMENT_MODIFY", "modify"},
{0, NULL, NULL} {0, NULL, NULL}
}; };

View File

@ -169,6 +169,7 @@
* @VIPS_ARGUMENT_INPUT: is an input argument (one we depend on) * @VIPS_ARGUMENT_INPUT: is an input argument (one we depend on)
* @VIPS_ARGUMENT_OUTPUT: is an output argument (depends on us) * @VIPS_ARGUMENT_OUTPUT: is an output argument (depends on us)
* @VIPS_ARGUMENT_DEPRECATED: just there for back-compat, hide * @VIPS_ARGUMENT_DEPRECATED: just there for back-compat, hide
* @VIPS_ARGUMENT_MODIFY: the input argument will be modified
* *
* Flags we associate with each object argument. * Flags we associate with each object argument.
* *
@ -186,6 +187,9 @@
* looked for if required, are not checked for "have-been-set". You can * looked for if required, are not checked for "have-been-set". You can
* deprecate a required argument, but you must obviously add a new required * deprecate a required argument, but you must obviously add a new required
* argument if you do. * argument if you do.
*
* Input args with @VIPS_ARGUMENT_MODIFY will be modified by the operation.
* This is used for things like the in-place drawing operations.
*/ */
/* Our signals. /* Our signals.

View File

@ -79,6 +79,11 @@ class Argument:
if not isinstance(value, Vips.Blob): if not isinstance(value, Vips.Blob):
value = Vips.Blob.new(None, value) value = Vips.Blob.new(None, value)
# MODIFY input images need to be copied before assigning them
if self.flags & Vips.ArgumentFlags.MODIFY:
print 'taking copy of MODIFY image arg'
value = value.copy()
logging.debug('assigning %s' % self.prop.value_type) logging.debug('assigning %s' % self.prop.value_type)
self.op.props.__setattr__(self.name, value) self.op.props.__setattr__(self.name, value)
@ -171,16 +176,18 @@ def _call_base(name, required, optional, self = None, option_string = None):
args = [Argument(op2, x) for x in op2.props] args = [Argument(op2, x) for x in op2.props]
args.sort(lambda a, b: a.priority - b.priority) args.sort(lambda a, b: a.priority - b.priority)
# find all required output args
# we can't check assigned here (since we captured the value before the call)
# but the getattr will test that for us anyway
required_output = [x for x in args if x.flags & enm.OUTPUT and
x.flags & enm.REQUIRED]
# gather output args # gather output args
out = [] out = []
for x in required_output:
out.append(x.get_value()) for x in args:
# required output arg
if x.flags & enm.OUTPUT and x.flags & enm.REQUIRED:
out.append(x.get_value())
# modified input arg ... this will get the result of the copy() we
# did above
if x.flags & enm.INPUT and x.flags & enm.MODIFY:
out.append(x.get_value())
# find all optional output args # find all optional output args
optional_output = [x.name for x in args if x.flags & enm.OUTPUT and optional_output = [x.name for x in args if x.flags & enm.OUTPUT and