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.
@@ -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,10 @@
1
+ module Vips
2
+
3
+ # The type of binary complex operation to perform on an image. See
4
+ # {Image#complex2}.
5
+ #
6
+ # * ':cross_phase' cross phase
7
+
8
+ class OperationComplex2 < Symbol
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module Vips
2
+
3
+ # The type of complex projection operation to perform on an image. See
4
+ # {Image#complexget}.
5
+ #
6
+ # * ':real' get real part
7
+ # * ':imag' get imaginary part
8
+
9
+ class OperationComplexget < Symbol
10
+ end
11
+ 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,10 @@
1
+ module Vips
2
+
3
+ # The binary math operation to perform on an image. See {Image#math2}.
4
+ #
5
+ # * ':pow' pow()
6
+ # * ':wop' pow(), but with the arguments reversed
7
+
8
+ class OperationMath2 < Symbol
9
+ end
10
+ 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
@@ -0,0 +1,11 @@
1
+ module Vips
2
+
3
+ # The type of rounding to perform on an image. See {Image#round}.
4
+ #
5
+ # * ':ceil' round up
6
+ # * ':floor' round down
7
+ # * ':rint' round to nearest integer
8
+
9
+ class OperationRound < Symbol
10
+ end
11
+ end
@@ -6,7 +6,8 @@ module Vips
6
6
  # * `:both` size both up and down
7
7
  # * `:up` only upsize
8
8
  # * `:down` only downsize
9
+ # * `:force` change aspect ratio
9
10
 
10
- class Size
11
+ class Size < Symbol
11
12
  end
12
13
  end
@@ -1,4 +1,4 @@
1
1
  module Vips
2
- VERSION = "1.0.6"
2
+ VERSION = "2.0.0"
3
3
  end
4
4
 
@@ -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 = "2016-06-07"
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 "gobject-introspection", ["~> 3.1"]
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: 1.0.6
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: 2016-06-07 00:00:00.000000000 Z
11
+ date: 2017-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: gobject-introspection
14
+ name: ffi
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '3.1'
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: '3.1'
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/foreignflags.rb
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: '2.0'
186
+ version: '0'
179
187
  required_rubygems_version: !ruby/object:Gem::Requirement
180
188
  requirements:
181
189
  - - ">="
@@ -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
@@ -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