class Vips::Operation

Public Class Methods

call(name, supplied, optional = {}) click to toggle source

This is the public entry point for the vips binding. {call} will run any vips operation, for example:

“‘ruby out = Vips::Operation.call “black”, [100, 100], {:bands => 12} “`

will call the C function

“‘C 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:

“‘ruby out = Vips::Image.black 100, 100, bands: 12 “`

Or perhaps:

“‘ruby 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:

“‘ruby 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:

“‘ruby 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.

# File lib/vips/operation.rb, line 321
def self.call name, supplied, optional = {}, option_string = ""
  GLib::logger.debug("Vips::VipsOperation.call") {
    "name = #{name}, supplied = #{supplied}, " +
      "optional = #{optional}, option_string = #{option_string}"
  }

  introspect = Introspect.get name
  required_input = introspect.required_input
  required_output = introspect.required_output
  optional_input = introspect.optional_input
  optional_output = introspect.optional_output

  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

  # all supplied_optional keys should be 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 = flat_find(supplied) { |value| value.is_a? Image }

  op = Operation.new name

  # 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|
    details = required_input[i]
    arg_name = details[:arg_name]
    flags = details[:flags]
    gtype = details[:gtype]
    value = supplied[i]

    op.set arg_name, value, match_image, flags, gtype
  end

  # set all optional inputs
  optional.each do |key, value|
    next if value.nil?

    arg_name = key.to_s

    if optional_input.has_key? arg_name
      details = optional_input[arg_name]
      flags = details[:flags]
      gtype = details[:gtype]

      op.set arg_name, value, match_image, flags, gtype
    end
  end

  op = op.build

  # get all required results
  result = []
  required_output.each do |details|
    result << op.get(details[: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
      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
flat_find(object) { |object| ... } click to toggle source

Search an object for the first element to match a predicate. Search inside subarrays and sub-hashes. Equlvalent to x.flatten.find{}.

# File lib/vips/operation.rb, line 206
def self.flat_find object, &block
  if object.respond_to? :each
    object.each do |x| 
      result = flat_find x, &block 
      return result if result != nil
    end
  else
    return object if yield object
  end

  return nil
end
imageize(match_image, value) click to toggle source

expand a constant into an image

# File lib/vips/operation.rb, line 220
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
new(value) click to toggle source
Calls superclass method GObject::GObject::new
# File lib/vips/operation.rb, line 175
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.null?
  end

  super value
end

Public Instance Methods

argument_map(&block) click to toggle source
# File lib/vips/operation.rb, line 196
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() click to toggle source
# File lib/vips/operation.rb, line 186
def build
  op = Vips::vips_cache_operation_build self
  if op.null?
    Vips::vips_object_unref_outputs self
    raise Vips::Error
  end

  return Operation.new op
end
set(name, value, match_image, flags, gtype) click to toggle source

set an operation argument, expanding constants and copying images as required

Calls superclass method Vips::Object#set
# File lib/vips/operation.rb, line 237
def set name, value, match_image, flags, gtype
  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