ruby-vips 1.0.6 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +9 -12
- data/CHANGELOG.md +5 -1
- data/README.md +32 -115
- data/TODO +4 -6
- data/VERSION +1 -1
- data/example/inheritance_with_refcount.rb +286 -0
- data/lib/ruby-vips.rb +1 -0
- data/lib/vips.rb +425 -93
- data/lib/vips/access.rb +1 -4
- data/lib/vips/align.rb +2 -2
- data/lib/vips/angle.rb +2 -2
- data/lib/vips/angle45.rb +2 -2
- data/lib/vips/bandformat.rb +1 -1
- data/lib/vips/coding.rb +1 -1
- data/lib/vips/direction.rb +2 -2
- data/lib/vips/extend.rb +8 -13
- data/lib/vips/gobject.rb +121 -0
- data/lib/vips/gvalue.rb +251 -0
- data/lib/vips/image.rb +487 -585
- data/lib/vips/interesting.rb +1 -1
- data/lib/vips/interpolate.rb +31 -6
- data/lib/vips/interpretation.rb +1 -1
- data/lib/vips/kernel.rb +1 -1
- data/lib/vips/methods.rb +339 -334
- data/lib/vips/object.rb +204 -0
- data/lib/vips/operation.rb +358 -14
- data/lib/vips/operationboolean.rb +14 -0
- data/lib/vips/operationcomplex.rb +12 -0
- data/lib/vips/operationcomplex2.rb +10 -0
- data/lib/vips/operationcomplexget.rb +11 -0
- data/lib/vips/operationmath.rb +18 -0
- data/lib/vips/operationmath2.rb +10 -0
- data/lib/vips/operationrelational.rb +15 -0
- data/lib/vips/operationround.rb +11 -0
- data/lib/vips/size.rb +2 -1
- data/lib/vips/version.rb +1 -1
- data/ruby-vips.gemspec +2 -6
- metadata +19 -11
- data/lib/vips/argument.rb +0 -159
- data/lib/vips/call.rb +0 -370
- data/lib/vips/demandstyle.rb +0 -35
- data/lib/vips/error.rb +0 -30
- data/lib/vips/foreignflags.rb +0 -20
@@ -0,0 +1,14 @@
|
|
1
|
+
module Vips
|
2
|
+
|
3
|
+
# The type of boolean operation to perform on an image. See
|
4
|
+
# {Image#boolean}.
|
5
|
+
#
|
6
|
+
# * ':and' bitwise and
|
7
|
+
# * ':or' bitwise or
|
8
|
+
# * ':eor' bitwise eor
|
9
|
+
# * ':lshift' shift left n bits
|
10
|
+
# * ':rshift' shift right n bits
|
11
|
+
|
12
|
+
class OperationBoolean < Symbol
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Vips
|
2
|
+
|
3
|
+
# The type of complex operation to perform on an image. See
|
4
|
+
# {Image#complex}.
|
5
|
+
#
|
6
|
+
# * ':polar' to polar coordinates
|
7
|
+
# * ':rect' to rectangular coordinates
|
8
|
+
# * ':conj' complex conjugate
|
9
|
+
|
10
|
+
class OperationComplex < Symbol
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Vips
|
2
|
+
|
3
|
+
# The math operation to perform on an image. See {Image#math}.
|
4
|
+
#
|
5
|
+
# * ':sin' sin(), angles in degrees
|
6
|
+
# * ':cos' cos(), angles in degrees
|
7
|
+
# * ':tan' tan(), angles in degrees
|
8
|
+
# * ':asin' asin(), angles in degrees
|
9
|
+
# * ':acos' acos(), angles in degrees
|
10
|
+
# * ':atan' atan(), angles in degrees
|
11
|
+
# * ':log' log base e
|
12
|
+
# * ':log10' log base 10
|
13
|
+
# * ':exp' e to the something
|
14
|
+
# * ':exp10' 10 to the something
|
15
|
+
|
16
|
+
class OperationMath < Symbol
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Vips
|
2
|
+
|
3
|
+
# The type of relational operation to perform on an image. See
|
4
|
+
# {Image#relational}.
|
5
|
+
#
|
6
|
+
# * ':more' more than
|
7
|
+
# * ':less' less than
|
8
|
+
# * ':moreeq' more than or equal to
|
9
|
+
# * ':lesseq' less than or equal to
|
10
|
+
# * ':equal' equal to
|
11
|
+
# * ':noteq' not equal to
|
12
|
+
|
13
|
+
class OperationRelational < Symbol
|
14
|
+
end
|
15
|
+
end
|
data/lib/vips/size.rb
CHANGED
data/lib/vips/version.rb
CHANGED
data/ruby-vips.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.name = "ruby-vips"
|
9
9
|
spec.version = Vips::VERSION
|
10
10
|
spec.authors = ["John Cupitt"]
|
11
|
-
spec.date = "
|
11
|
+
spec.date = "2017-07-15"
|
12
12
|
spec.email = "jcupitt@gmail.com"
|
13
13
|
|
14
14
|
spec.summary = "Ruby extension for the vips image processing library."
|
@@ -16,10 +16,6 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.homepage = "http://github.com/jcupitt/ruby-vips"
|
17
17
|
spec.licenses = ["MIT"]
|
18
18
|
|
19
|
-
# gobject-introspection really needs 2.1, but it just about works on 2.0, the
|
20
|
-
# ruby that OS X is still bundling ... only ask for 2.0 to help OS X
|
21
|
-
spec.required_ruby_version = ">= 2.0"
|
22
|
-
spec.rubygems_version = "2.5.1"
|
23
19
|
spec.require_paths = ["lib"]
|
24
20
|
spec.extra_rdoc_files = [
|
25
21
|
"LICENSE.txt",
|
@@ -31,7 +27,7 @@ Gem::Specification.new do |spec|
|
|
31
27
|
f.match(%r{^(test|spec|features)/})
|
32
28
|
end
|
33
29
|
|
34
|
-
spec.add_runtime_dependency "
|
30
|
+
spec.add_runtime_dependency "ffi", ["~> 1.9"]
|
35
31
|
|
36
32
|
spec.add_development_dependency "rake", ["~> 11.0"]
|
37
33
|
spec.add_development_dependency "rspec", ["~> 3.3"]
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-vips
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Cupitt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-07-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: ffi
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.9'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '1.9'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -135,31 +135,39 @@ files:
|
|
135
135
|
- example/example3.rb
|
136
136
|
- example/example4.rb
|
137
137
|
- example/example5.rb
|
138
|
+
- example/inheritance_with_refcount.rb
|
138
139
|
- example/trim8.rb
|
139
140
|
- example/watermark.rb
|
140
141
|
- example/wobble.rb
|
141
142
|
- install-vips.sh
|
143
|
+
- lib/ruby-vips.rb
|
142
144
|
- lib/vips.rb
|
143
145
|
- lib/vips/access.rb
|
144
146
|
- lib/vips/align.rb
|
145
147
|
- lib/vips/angle.rb
|
146
148
|
- lib/vips/angle45.rb
|
147
|
-
- lib/vips/argument.rb
|
148
149
|
- lib/vips/bandformat.rb
|
149
|
-
- lib/vips/call.rb
|
150
150
|
- lib/vips/coding.rb
|
151
|
-
- lib/vips/demandstyle.rb
|
152
151
|
- lib/vips/direction.rb
|
153
|
-
- lib/vips/error.rb
|
154
152
|
- lib/vips/extend.rb
|
155
|
-
- lib/vips/
|
153
|
+
- lib/vips/gobject.rb
|
154
|
+
- lib/vips/gvalue.rb
|
156
155
|
- lib/vips/image.rb
|
157
156
|
- lib/vips/interesting.rb
|
158
157
|
- lib/vips/interpolate.rb
|
159
158
|
- lib/vips/interpretation.rb
|
160
159
|
- lib/vips/kernel.rb
|
161
160
|
- lib/vips/methods.rb
|
161
|
+
- lib/vips/object.rb
|
162
162
|
- lib/vips/operation.rb
|
163
|
+
- lib/vips/operationboolean.rb
|
164
|
+
- lib/vips/operationcomplex.rb
|
165
|
+
- lib/vips/operationcomplex2.rb
|
166
|
+
- lib/vips/operationcomplexget.rb
|
167
|
+
- lib/vips/operationmath.rb
|
168
|
+
- lib/vips/operationmath2.rb
|
169
|
+
- lib/vips/operationrelational.rb
|
170
|
+
- lib/vips/operationround.rb
|
163
171
|
- lib/vips/size.rb
|
164
172
|
- lib/vips/version.rb
|
165
173
|
- ruby-vips.gemspec
|
@@ -175,7 +183,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
175
183
|
requirements:
|
176
184
|
- - ">="
|
177
185
|
- !ruby/object:Gem::Version
|
178
|
-
version: '
|
186
|
+
version: '0'
|
179
187
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
180
188
|
requirements:
|
181
189
|
- - ">="
|
data/lib/vips/argument.rb
DELETED
@@ -1,159 +0,0 @@
|
|
1
|
-
|
2
|
-
module Vips
|
3
|
-
|
4
|
-
# This class is used internally to convert Ruby values to arguments to
|
5
|
-
# libvips operations.
|
6
|
-
# @private
|
7
|
-
class Argument
|
8
|
-
attr_reader :op, :name, :flags, :priority, :isset, :prop
|
9
|
-
attr_reader :blurb, :gtype, :type
|
10
|
-
|
11
|
-
# map gobject-introspection's ruby class names to ours
|
12
|
-
@@map_goi_to_vips = {
|
13
|
-
"TrueClass" => "Boolean",
|
14
|
-
"Vips::ArrayDouble" => "Array<Double>",
|
15
|
-
"Vips::ArrayInt" => "Array<Integer>",
|
16
|
-
"Vips::ArrayImage" => "Array<Image>",
|
17
|
-
"Vips::ArrayString" => "Array<String>",
|
18
|
-
}
|
19
|
-
|
20
|
-
def initialize(op, name)
|
21
|
-
@op = op
|
22
|
-
@name = name.tr '-', '_'
|
23
|
-
@prop = op.gtype.to_class.property name
|
24
|
-
@blurb = @prop.blurb
|
25
|
-
@gtype = prop.value_type
|
26
|
-
@flags = op.get_argument_flags name
|
27
|
-
@priority = op.get_argument_priority @name
|
28
|
-
@isset = op.argument_isset @name
|
29
|
-
|
30
|
-
type = GLib::Type[gtype.name].to_class.name
|
31
|
-
type = @@map_goi_to_vips[type] if @@map_goi_to_vips.include? type
|
32
|
-
@type = type
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def self.imageize match_image, value
|
38
|
-
return value if match_image == nil
|
39
|
-
return value if value.is_a? Vips::Image
|
40
|
-
|
41
|
-
# 2D array values become tiny 2D images
|
42
|
-
if value.is_a? Array and value[0].is_a? Array
|
43
|
-
return Vips::Image.new_from_array value
|
44
|
-
end
|
45
|
-
|
46
|
-
# if there's nothing to match to, we also make a 2D image
|
47
|
-
if match_image == nil
|
48
|
-
return Vips::Image.new_from_array value
|
49
|
-
end
|
50
|
-
|
51
|
-
# we have a 1D array ... use that as a pixel constant and expand
|
52
|
-
# to match match_image
|
53
|
-
match_image.new_from_image(value)
|
54
|
-
end
|
55
|
-
|
56
|
-
# @private
|
57
|
-
class ArrayImageConst < Vips::ArrayImage
|
58
|
-
def self.new(value)
|
59
|
-
if not value.is_a? Array
|
60
|
-
value = [value]
|
61
|
-
end
|
62
|
-
|
63
|
-
match_image = value.find {|x| x.is_a? Vips::Image}
|
64
|
-
if match_image == nil
|
65
|
-
raise Vips::Error,
|
66
|
-
"Argument must contain at least one image."
|
67
|
-
end
|
68
|
-
|
69
|
-
value = value.map {|x| Argument::imageize match_image, x}
|
70
|
-
|
71
|
-
# we'd like to just
|
72
|
-
# super(value)
|
73
|
-
# to construct, but the gobject-introspection gem does not
|
74
|
-
# support new from object array ... instead, we build in stages
|
75
|
-
array = Vips::ArrayImage.empty
|
76
|
-
value.each {|x| array = array.append(x)}
|
77
|
-
|
78
|
-
return array
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# if this gtype needs an array, try to transform the value into one
|
83
|
-
def self.arrayize(gtype, value)
|
84
|
-
arrayize_map = {
|
85
|
-
GLib::Type["VipsArrayDouble"] => Vips::ArrayDouble,
|
86
|
-
GLib::Type["VipsArrayInt"] => Vips::ArrayInt,
|
87
|
-
GLib::Type["VipsArrayImage"] => ArrayImageConst
|
88
|
-
}
|
89
|
-
|
90
|
-
if arrayize_map.has_key? gtype
|
91
|
-
if not value.is_a? Array
|
92
|
-
value = [value]
|
93
|
-
end
|
94
|
-
|
95
|
-
value = arrayize_map[gtype].new(value)
|
96
|
-
end
|
97
|
-
|
98
|
-
value
|
99
|
-
end
|
100
|
-
|
101
|
-
def self.unwrap value
|
102
|
-
[Vips::Blob, Vips::ArrayDouble, Vips::ArrayImage,
|
103
|
-
Vips::ArrayInt, Vips::RefString].each do |cls|
|
104
|
-
if value.is_a? cls
|
105
|
-
value = value.get
|
106
|
-
|
107
|
-
# blobs come from gobject-introspection as arrays ...
|
108
|
-
# repack as strings for convenience
|
109
|
-
if value and cls == Vips::Blob
|
110
|
-
value = value.pack("C*")
|
111
|
-
end
|
112
|
-
|
113
|
-
end
|
114
|
-
|
115
|
-
end
|
116
|
-
|
117
|
-
value
|
118
|
-
end
|
119
|
-
|
120
|
-
public
|
121
|
-
|
122
|
-
def set_value(match_image, value)
|
123
|
-
# array-ize
|
124
|
-
value = Argument::arrayize gtype, value
|
125
|
-
|
126
|
-
# blob-ize
|
127
|
-
if gtype.type_is_a? GLib::Type["VipsBlob"]
|
128
|
-
if not value.is_a? Vips::Blob
|
129
|
-
value = Vips::Blob.copy value
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
# image-ize
|
134
|
-
if gtype.type_is_a? GLib::Type["VipsImage"]
|
135
|
-
if not value.is_a? Vips::Image
|
136
|
-
value = Argument::imageize match_image, value
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
# MODIFY input images need to be copied before assigning them
|
141
|
-
if (flags & :modify) != 0
|
142
|
-
# don't use .copy(): we want to make a new pipeline with no
|
143
|
-
# reference back to the old stuff ... this way we can free the
|
144
|
-
# previous image earlier
|
145
|
-
new_image = Vips::Image.memory
|
146
|
-
value.write new_image
|
147
|
-
value = new_image
|
148
|
-
end
|
149
|
-
|
150
|
-
op.set_property @name, value
|
151
|
-
end
|
152
|
-
|
153
|
-
def get_value
|
154
|
-
Argument::unwrap @op.get_property(@name)
|
155
|
-
end
|
156
|
-
|
157
|
-
end
|
158
|
-
|
159
|
-
end
|
data/lib/vips/call.rb
DELETED
@@ -1,370 +0,0 @@
|
|
1
|
-
module Vips
|
2
|
-
|
3
|
-
# Call a vips operation.
|
4
|
-
#
|
5
|
-
# This will crash if there's a GC during the call, only use
|
6
|
-
# this via {Vips.call}.
|
7
|
-
private
|
8
|
-
class Call
|
9
|
-
attr_writer :instance, :option_string
|
10
|
-
|
11
|
-
def initialize(name, supplied_values)
|
12
|
-
@name = name
|
13
|
-
@supplied_values = supplied_values
|
14
|
-
@optional_values = {}
|
15
|
-
@instance = nil
|
16
|
-
@option_string = nil
|
17
|
-
|
18
|
-
if @supplied_values.last.is_a? Hash
|
19
|
-
@optional_values = @supplied_values.last
|
20
|
-
@supplied_values.delete_at(-1)
|
21
|
-
end
|
22
|
-
|
23
|
-
begin
|
24
|
-
@op = Vips::Operation.new @name
|
25
|
-
rescue
|
26
|
-
raise Vips::Error, "no operator '#{@name}'"
|
27
|
-
end
|
28
|
-
|
29
|
-
log "Vips::Call.init"
|
30
|
-
log "name = #{@name}"
|
31
|
-
log "supplied_values are:"
|
32
|
-
@supplied_values.each {|x| log " #{x}"}
|
33
|
-
log "optional_values are:"
|
34
|
-
@optional_values.each {|x| log " #{x}"}
|
35
|
-
end
|
36
|
-
|
37
|
-
# set any string options on the operation
|
38
|
-
def set_string_args
|
39
|
-
if @option_string
|
40
|
-
log "setting string options #{@option_string} ..."
|
41
|
-
|
42
|
-
if @op.set_from_string(@option_string) != 0
|
43
|
-
raise Error
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# set @match_image to be the image we build constants to match
|
49
|
-
def find_match_image
|
50
|
-
# the instance, if supplied, must be a vips image ... we use it for
|
51
|
-
# match_image, below
|
52
|
-
if @instance and not @instance.is_a? Vips::Image
|
53
|
-
raise Vips::Error, "@instance is not a Vips::Image."
|
54
|
-
end
|
55
|
-
|
56
|
-
# if the op needs images but the user supplies constants, we expand
|
57
|
-
# them to match the first input image argument ... find the first
|
58
|
-
# image
|
59
|
-
log "searching for first image argument ..."
|
60
|
-
match_image = @instance
|
61
|
-
if match_image == nil
|
62
|
-
match_image = @supplied_values.find {|x| x.is_a? Vips::Image}
|
63
|
-
end
|
64
|
-
if match_image == nil
|
65
|
-
match = @optional_values.find do |name, value|
|
66
|
-
value.is_a? Vips::Image
|
67
|
-
end
|
68
|
-
# if we found a match, it'll be [name, value]
|
69
|
-
if match
|
70
|
-
match_image = match[1]
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
return match_image
|
75
|
-
end
|
76
|
-
|
77
|
-
# look through the operation args and find required and optional
|
78
|
-
# input args
|
79
|
-
def find_input
|
80
|
-
all_args = @op.get_args
|
81
|
-
|
82
|
-
# find unassigned required input args
|
83
|
-
log "finding unassigned required input arguments ..."
|
84
|
-
required_input = all_args.select do |arg|
|
85
|
-
not arg.isset and
|
86
|
-
(arg.flags & :input) != 0 and
|
87
|
-
(arg.flags & :required) != 0
|
88
|
-
end
|
89
|
-
|
90
|
-
# find optional unassigned input args
|
91
|
-
log "finding optional unassigned input arguments ..."
|
92
|
-
optional_input = all_args.select do |arg|
|
93
|
-
not arg.isset and
|
94
|
-
(arg.flags & :input) != 0 and
|
95
|
-
(arg.flags & :required) == 0
|
96
|
-
end
|
97
|
-
|
98
|
-
# make a hash from name to arg for the options
|
99
|
-
optional_input = Hash[
|
100
|
-
optional_input.map(&:name).zip(optional_input)]
|
101
|
-
|
102
|
-
return required_input, optional_input
|
103
|
-
end
|
104
|
-
|
105
|
-
def find_optional_output
|
106
|
-
all_args = @op.get_args
|
107
|
-
|
108
|
-
log "finding optional output arguments ..."
|
109
|
-
optional_output = all_args.select do |arg|
|
110
|
-
(arg.flags & :output) != 0 and
|
111
|
-
(arg.flags & :required) == 0
|
112
|
-
end
|
113
|
-
optional_output = Hash[
|
114
|
-
optional_output.map(&:name).zip(optional_output)]
|
115
|
-
|
116
|
-
return optional_output
|
117
|
-
|
118
|
-
end
|
119
|
-
|
120
|
-
def set_required_input(match_image, required_input)
|
121
|
-
log "set_required_input: @instance = #{@instance}"
|
122
|
-
|
123
|
-
# do we have a non-nil instance? set the first image arg with this
|
124
|
-
if @instance != nil
|
125
|
-
log "BANANA"
|
126
|
-
log "setting first image arg with instance ..."
|
127
|
-
x = required_input.find do |arg|
|
128
|
-
gtype = GLib::Type["VipsImage"]
|
129
|
-
vtype = arg.prop.value_type
|
130
|
-
|
131
|
-
vtype.type_is_a? gtype
|
132
|
-
end
|
133
|
-
if x == nil
|
134
|
-
raise Vips::Error,
|
135
|
-
"No #{@instance.class} argument to #{@name}."
|
136
|
-
end
|
137
|
-
x.set_value match_image, @instance
|
138
|
-
required_input.delete x
|
139
|
-
end
|
140
|
-
|
141
|
-
if required_input.length != @supplied_values.length
|
142
|
-
raise Vips::Error,
|
143
|
-
"Wrong number of arguments. '#{@name}' requires " +
|
144
|
-
"#{required_input.length} arguments, you supplied " +
|
145
|
-
"#{@supplied_values.length}."
|
146
|
-
end
|
147
|
-
|
148
|
-
log "setting required input arguments ..."
|
149
|
-
required_input.zip(@supplied_values).each do |arg, value|
|
150
|
-
arg.set_value match_image, value
|
151
|
-
end
|
152
|
-
|
153
|
-
end
|
154
|
-
|
155
|
-
def set_optional_input(match_image, optional_input, optional_output)
|
156
|
-
log "setting optional input args ..."
|
157
|
-
@optional_values.each do |name, value|
|
158
|
-
# we are passed symbols as keys
|
159
|
-
name = name.to_s
|
160
|
-
if optional_input.has_key? name
|
161
|
-
log "setting #{name} to #{value}"
|
162
|
-
optional_input[name].set_value match_image, value
|
163
|
-
elsif optional_output.has_key? name and value != true
|
164
|
-
raise Vips::Error,
|
165
|
-
"Optional output argument #{name} must be true."
|
166
|
-
elsif not optional_output.has_key? name
|
167
|
-
raise Vips::Error, "No such option '#{name}',"
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
def build
|
173
|
-
log "building ..."
|
174
|
-
|
175
|
-
op2 = Vips::cache_operation_lookup @op
|
176
|
-
if op2
|
177
|
-
log "cache hit"
|
178
|
-
|
179
|
-
hit = true
|
180
|
-
@op = op2
|
181
|
-
else
|
182
|
-
log "cache miss ... building"
|
183
|
-
|
184
|
-
hit = false
|
185
|
-
if @op.build() != 0
|
186
|
-
raise Vips::Error
|
187
|
-
end
|
188
|
-
# showall
|
189
|
-
|
190
|
-
log "adding to cache ... "
|
191
|
-
Vips::cache_operation_add @op
|
192
|
-
end
|
193
|
-
|
194
|
-
return hit
|
195
|
-
end
|
196
|
-
|
197
|
-
def fetch_output(optional_output)
|
198
|
-
log "fetching outputs ..."
|
199
|
-
|
200
|
-
# gather output args
|
201
|
-
out = []
|
202
|
-
|
203
|
-
all_args = @op.get_args
|
204
|
-
all_args.each do |arg|
|
205
|
-
# required output
|
206
|
-
if (arg.flags & :output) != 0 and
|
207
|
-
(arg.flags & :required) != 0
|
208
|
-
log "fetching required output #{arg.name}"
|
209
|
-
out << arg.get_value
|
210
|
-
end
|
211
|
-
|
212
|
-
# modified input arg ... this will get the result of the
|
213
|
-
# copy() we did in Argument.set_value
|
214
|
-
if (arg.flags & :input) != 0 and
|
215
|
-
(arg.flags & :modify) != 0
|
216
|
-
log "fetching modified input arg ..."
|
217
|
-
out << arg.get_value
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
opts = {}
|
222
|
-
@optional_values.each do |name, value|
|
223
|
-
# we are passed symbols as keys
|
224
|
-
name = name.to_s
|
225
|
-
if optional_output.has_key? name
|
226
|
-
log "fetching optional output arg ..."
|
227
|
-
opts[name] = optional_output[name].get_value
|
228
|
-
end
|
229
|
-
end
|
230
|
-
out << opts if opts != {}
|
231
|
-
|
232
|
-
if out.length == 1
|
233
|
-
out = out[0]
|
234
|
-
elsif out.length == 0
|
235
|
-
out = nil
|
236
|
-
end
|
237
|
-
|
238
|
-
return out
|
239
|
-
|
240
|
-
end
|
241
|
-
|
242
|
-
def invoke
|
243
|
-
log "invoke starting ..."
|
244
|
-
log "invoke instance is #{@instance}"
|
245
|
-
set_string_args()
|
246
|
-
match_image = find_match_image()
|
247
|
-
required_input, optional_input = find_input()
|
248
|
-
optional_output = find_optional_output()
|
249
|
-
|
250
|
-
set_required_input(match_image, required_input)
|
251
|
-
set_optional_input(match_image, optional_input, optional_output)
|
252
|
-
|
253
|
-
hit = build()
|
254
|
-
|
255
|
-
# if there was a cache hit, we need to refind this since all the arg
|
256
|
-
# pointers will have changed
|
257
|
-
if hit
|
258
|
-
optional_output = find_optional_output()
|
259
|
-
end
|
260
|
-
out = fetch_output(optional_output)
|
261
|
-
|
262
|
-
log "unreffing outputs ..."
|
263
|
-
@op.unref_outputs()
|
264
|
-
@op = nil
|
265
|
-
# showall
|
266
|
-
|
267
|
-
log "success! #{@name}.out = #{out}"
|
268
|
-
|
269
|
-
return out
|
270
|
-
end
|
271
|
-
|
272
|
-
end
|
273
|
-
|
274
|
-
# full-fat call, with the GC disabled
|
275
|
-
private
|
276
|
-
def self.call_base(name, instance, option_string, supplied_values)
|
277
|
-
gc_was_enabled = GC.disable
|
278
|
-
begin
|
279
|
-
call = Call.new(name, supplied_values)
|
280
|
-
call.instance = instance
|
281
|
-
call.option_string = option_string
|
282
|
-
result = call.invoke
|
283
|
-
ensure
|
284
|
-
GC.enable if gc_was_enabled
|
285
|
-
end
|
286
|
-
|
287
|
-
return result
|
288
|
-
end
|
289
|
-
|
290
|
-
public
|
291
|
-
|
292
|
-
# This is the public entry point for the vips binding. {call} will run
|
293
|
-
# any vips operation, for example:
|
294
|
-
#
|
295
|
-
# ```ruby
|
296
|
-
# out = Vips::call "black", 100, 100, :bands => 12
|
297
|
-
# ```
|
298
|
-
#
|
299
|
-
# will call the C function
|
300
|
-
#
|
301
|
-
# ```C
|
302
|
-
# vips_black( &out, 100, 100, "bands", 12, NULL );
|
303
|
-
# ```
|
304
|
-
#
|
305
|
-
# There are {Image#method_missing} hooks which will run {call} for you
|
306
|
-
# on {Image} for undefined instance or class methods. So you can also
|
307
|
-
# write:
|
308
|
-
#
|
309
|
-
# ```ruby
|
310
|
-
# out = Vips::Image.black 100, 100, :bands => 12
|
311
|
-
# ```
|
312
|
-
#
|
313
|
-
# Or perhaps:
|
314
|
-
#
|
315
|
-
# ```ruby
|
316
|
-
# x = Vips::Image.black 100, 100
|
317
|
-
# y = x.invert
|
318
|
-
# ```
|
319
|
-
#
|
320
|
-
# to run the `vips_invert()` operator.
|
321
|
-
#
|
322
|
-
# There are also a set of operator overloads and some convenience functions,
|
323
|
-
# see {Image}.
|
324
|
-
#
|
325
|
-
# If the operator needs a vector constant, {call} will turn a scalar into a
|
326
|
-
# vector for you. So for `x.linear(a, b)`, which calculates
|
327
|
-
# `x * a + b` where `a` and `b` are vector constants, you can write:
|
328
|
-
#
|
329
|
-
# ```ruby
|
330
|
-
# x = Vips::Image.black 100, 100, :bands => 3
|
331
|
-
# y = x.linear(1, 2)
|
332
|
-
# y = x.linear([1], 4)
|
333
|
-
# y = x.linear([1, 2, 3], 4)
|
334
|
-
# ```
|
335
|
-
#
|
336
|
-
# or any other combination. The operator overloads use this facility to
|
337
|
-
# support all the variations on:
|
338
|
-
#
|
339
|
-
# ```ruby
|
340
|
-
# x = Vips::Image.black 100, 100, :bands => 3
|
341
|
-
# y = x * 2
|
342
|
-
# y = x + [1,2,3]
|
343
|
-
# y = x % [1]
|
344
|
-
# ```
|
345
|
-
#
|
346
|
-
# Similarly, wherever an image is required, you can use a constant. The
|
347
|
-
# constant will be expanded to an image matching the first input image
|
348
|
-
# argument. For example, you can write:
|
349
|
-
#
|
350
|
-
# ```
|
351
|
-
# x = Vips::Image.black 100, 100, :bands => 3
|
352
|
-
# y = x.bandjoin(255)
|
353
|
-
# ```
|
354
|
-
#
|
355
|
-
# to add an extra band to the image where each pixel in the new band has
|
356
|
-
# the constant value 255.
|
357
|
-
|
358
|
-
def self.call(name, *args)
|
359
|
-
gc_was_enabled = GC.disable
|
360
|
-
begin
|
361
|
-
call = Call.new(name, args)
|
362
|
-
result = call.invoke
|
363
|
-
ensure
|
364
|
-
GC.enable if gc_was_enabled
|
365
|
-
end
|
366
|
-
|
367
|
-
return result
|
368
|
-
end
|
369
|
-
|
370
|
-
end
|