Class: Vips::Operation
- Inherits:
-
Object
- Object
- GObject::GObject
- Object
- Vips::Operation
- Defined in:
- lib/vips/operation.rb
Defined Under Namespace
Modules: OperationLayout Classes: ManagedStruct, Struct
Class Method Summary collapse
-
.call(name, supplied, optional = {}, option_string = "") ⇒ Object
This is the public entry point for the vips binding.
-
.find_inside(object, &block) ⇒ Object
search array for the first element to match a predicate ...
-
.imageize(match_image, value) ⇒ Object
expand a constant into an image.
Instance Method Summary collapse
- #argument_map(&block) ⇒ Object
- #build ⇒ Object
-
#get_construct_args ⇒ Object
not quick! try to call this infrequently.
- #get_flags ⇒ Object
-
#initialize(value) ⇒ Operation
constructor
A new instance of Operation.
-
#set(name, value, match_image = nil, flags = 0) ⇒ Object
set an operation argument, expanding constants and copying images as required.
Methods inherited from Object
#get, #get_pspec, #get_typeof, #get_typeof_error, print_all
Methods inherited from GObject::GObject
#ffi_managed_struct, ffi_managed_struct, ffi_struct, #ffi_struct
Constructor Details
#initialize(value) ⇒ Operation
Returns a new instance of Operation.
60 61 62 63 64 65 66 67 68 69 |
# File 'lib/vips/operation.rb', line 60 def initialize value # allow init with a pointer so we can wrap the return values from # things like _build if value.is_a? String value = Vips::vips_operation_new value raise Vips::Error if value == nil end super value end |
Class Method Details
.call(name, supplied, optional = {}, option_string = "") ⇒ Object
This is the public entry point for the vips binding. call will run any vips operation, for example:
out = Vips::Operation.call "black", [100, 100], {:bands => 12}
will call the C function
vips_black( &out, 100, 100, "bands", 12, NULL );
There are Image#method_missing hooks which will run call for you on Image for undefined instance or class methods. So you can also write:
out = Vips::Image.black 100, 100, bands: 12
Or perhaps:
x = Vips::Image.black 100, 100
y = x.invert
to run the vips_invert()
operator.
There are also a set of operator overloads and some convenience functions, see Image.
If the operator needs a vector constant, call will turn a scalar
into a
vector for you. So for x.linear a, b
, which calculates
x * a + b
where a
and b
are vector constants, you can write:
x = Vips::Image.black 100, 100, bands: 3
y = x.linear 1, 2
y = x.linear [1], 4
y = x.linear [1, 2, 3], 4
or any other combination. The operator overloads use this facility to support all the variations on:
x = Vips::Image.black 100, 100, bands: 3
y = x * 2
y = x + [1,2,3]
y = x % [1]
Similarly, wherever an image is required, you can use a constant. The constant will be expanded to an image matching the first input image argument. For example, you can write:
x = Vips::Image.black 100, 100, bands: 3
y = x.bandjoin 255
to add an extra band to the image where each pixel in the new band has the constant value 255.
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
# File 'lib/vips/operation.rb', line 226 def self.call name, supplied, optional = {}, option_string = "" GLib::logger.debug("Vips::VipsOperation.call") { "name = #{name}, supplied = #{supplied}, " + "optional = #{optional}, option_string = #{option_string}" } op = Operation.new name # find and classify all the arguments the operator can take args = op.get_construct_args required_input = [] optional_input = {} required_output = [] optional_output = {} args.each do |name, flags| next if (flags & ARGUMENT_DEPRECATED) != 0 if (flags & ARGUMENT_INPUT) != 0 if (flags & ARGUMENT_REQUIRED) != 0 required_input << [name, flags] else optional_input[name] = flags end end # MODIFY INPUT args count as OUTPUT as well if (flags & ARGUMENT_OUTPUT) != 0 || ((flags & ARGUMENT_INPUT) != 0 && (flags & ARGUMENT_MODIFY) != 0) if (flags & ARGUMENT_REQUIRED) != 0 required_output << [name, flags] else optional_output[name] = flags end end end # so we should have been supplied with n_required_input values, or # n_required_input + 1 if there's a hash of options at the end unless supplied.is_a? Array raise Vips::Error, "unable to call #{name}: " + "argument array is not an array" end unless optional.is_a? Hash raise Vips::Error, "unable to call #{name}: " + "optional arguments are not a hash" end if supplied.length != required_input.length raise Vips::Error, "unable to call #{name}: " + "you supplied #{supplied.length} arguments, " + "but operation needs #{required_input.length}." end # very that all supplied_optional keys are in optional_input or # optional_output optional.each do |key, value| arg_name = key.to_s unless optional_input.has_key?(arg_name) || optional_output.has_key?(arg_name) raise Vips::Error, "unable to call #{name}: " + "unknown option #{arg_name}" end end # the first image arg is the thing we expand constants to match ... # we need to find it # # look inside array and hash arguments, since we may be passing an # array of images match_image = find_inside(supplied) do |value| value.is_a? Image end # set any string args first so they can't be overridden if option_string != nil if Vips::vips_object_set_from_string(op, option_string) != 0 raise Vips::Error end end # set all required inputs required_input.each_index do |i| arg_name = required_input[i][0] flags = required_input[i][1] value = supplied[i] op.set arg_name, value, match_image, flags end # set all optional inputs optional.each do |key, value| arg_name = key.to_s if optional_input.has_key? arg_name flags = optional_input[arg_name] op.set arg_name, value, match_image, flags end end op = op.build # get all required results result = [] required_output.each do |arg_name, flags| result << op.get(arg_name) end # fetch all optional ones optional_results = {} optional.each do |key, value| arg_name = key.to_s if optional_output.has_key? arg_name flags = optional_output[arg_name] optional_results[arg_name] = op.get arg_name end end result << optional_results if optional_results != {} if result.length == 1 result = result.first elsif result.length == 0 result = nil end GLib::logger.debug("Vips::Operation.call") {"result = #{result}"} Vips::vips_object_unref_outputs op return result end |
.find_inside(object, &block) ⇒ Object
search array for the first element to match a predicate ... search inside subarrays and sub-hashes
112 113 114 115 116 117 118 119 120 |
# File 'lib/vips/operation.rb', line 112 def self.find_inside object, &block return object if block.call object if object.is_a? Enumerable object.find {|value| block.call value, block} end return nil end |
.imageize(match_image, value) ⇒ Object
expand a constant into an image
123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/vips/operation.rb', line 123 def self.imageize match_image, value return value if value.is_a? Image # 2D array values become tiny 2D images # if there's nothing to match to, we also make a 2D image if (value.is_a?(Array) && value[0].is_a?(Array)) || match_image == nil return Image.new_from_array value else # we have a 1D array ... use that as a pixel constant and # expand to match match_image return match_image.new_from_image value end end |
Instance Method Details
#argument_map(&block) ⇒ Object
80 81 82 83 84 85 86 |
# File 'lib/vips/operation.rb', line 80 def argument_map &block fn = Proc.new do |op, pspec, argument_class, argument_instance, a, b| block.call pspec, argument_class, argument_instance end Vips::vips_argument_map self, fn, nil, nil end |
#build ⇒ Object
71 72 73 74 75 76 77 78 |
# File 'lib/vips/operation.rb', line 71 def build op = Vips::vips_cache_operation_build self if op == nil raise Vips::Error end return Operation.new op end |
#get_construct_args ⇒ Object
not quick! try to call this infrequently
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/vips/operation.rb', line 93 def get_construct_args args = [] argument_map do |pspec, argument_class, argument_instance| flags = argument_class[:flags] if (flags & ARGUMENT_CONSTRUCT) != 0 # names can include - as punctuation, but we always use _ in # Ruby name = pspec[:name].tr("-", "_") args << [name, flags] end end return args end |
#get_flags ⇒ Object
88 89 90 |
# File 'lib/vips/operation.rb', line 88 def get_flags Vips::vips_operation_get_flags self end |
#set(name, value, match_image = nil, flags = 0) ⇒ Object
set an operation argument, expanding constants and copying images as required
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/vips/operation.rb', line 140 def set name, value, match_image = nil, flags = 0 gtype = get_typeof name if gtype == IMAGE_TYPE value = Operation::imageize match_image, value if (flags & ARGUMENT_MODIFY) != 0 # make sure we have a unique copy value = value.copy.copy_memory end elsif gtype == ARRAY_IMAGE_TYPE value = value.map {|x| Operation::imageize match_image, x} end super name, value end |