ruby-vips 2.0.14 → 2.1.1
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/.github/ISSUE_TEMPLATE/bug_report.md +42 -0
- data/.github/workflows/test.yml +80 -0
- data/.standard.yml +17 -0
- data/.yardopts +0 -1
- data/CHANGELOG.md +41 -0
- data/Gemfile +3 -1
- data/README.md +42 -41
- data/Rakefile +13 -21
- data/TODO +18 -10
- data/VERSION +1 -1
- data/example/annotate.rb +6 -6
- data/example/connection.rb +26 -0
- data/example/daltonize8.rb +16 -18
- data/example/draw_lines.rb +30 -0
- data/example/example1.rb +5 -6
- data/example/example2.rb +6 -6
- data/example/example3.rb +5 -5
- data/example/example4.rb +4 -4
- data/example/example5.rb +6 -7
- data/example/inheritance_with_refcount.rb +36 -54
- data/example/progress.rb +30 -0
- data/example/thumb.rb +8 -10
- data/example/trim8.rb +5 -5
- data/example/watermark.rb +2 -2
- data/example/wobble.rb +1 -1
- data/lib/ruby-vips.rb +1 -1
- data/lib/vips.rb +199 -93
- data/lib/vips/align.rb +0 -1
- data/lib/vips/angle.rb +0 -1
- data/lib/vips/angle45.rb +0 -1
- data/lib/vips/bandformat.rb +0 -2
- data/lib/vips/blend_mode.rb +29 -27
- data/lib/vips/coding.rb +0 -1
- data/lib/vips/compass_direction.rb +0 -1
- data/lib/vips/connection.rb +46 -0
- data/lib/vips/direction.rb +0 -1
- data/lib/vips/extend.rb +0 -1
- data/lib/vips/gobject.rb +26 -15
- data/lib/vips/gvalue.rb +61 -55
- data/lib/vips/image.rb +455 -282
- data/lib/vips/interesting.rb +0 -1
- data/lib/vips/interpolate.rb +3 -7
- data/lib/vips/interpretation.rb +0 -1
- data/lib/vips/kernel.rb +0 -1
- data/lib/vips/methods.rb +791 -124
- data/lib/vips/mutableimage.rb +173 -0
- data/lib/vips/object.rb +178 -68
- data/lib/vips/operation.rb +277 -130
- data/lib/vips/operationboolean.rb +0 -1
- data/lib/vips/operationcomplex.rb +0 -1
- data/lib/vips/operationcomplex2.rb +0 -1
- data/lib/vips/operationcomplexget.rb +0 -1
- data/lib/vips/operationmath.rb +0 -1
- data/lib/vips/operationmath2.rb +0 -1
- data/lib/vips/operationrelational.rb +0 -1
- data/lib/vips/operationround.rb +0 -1
- data/lib/vips/region.rb +73 -0
- data/lib/vips/size.rb +0 -1
- data/lib/vips/source.rb +88 -0
- data/lib/vips/sourcecustom.rb +89 -0
- data/lib/vips/target.rb +86 -0
- data/lib/vips/targetcustom.rb +77 -0
- data/lib/vips/version.rb +1 -2
- data/ruby-vips.gemspec +26 -21
- metadata +39 -51
- data/.rubocop.yml +0 -10
- data/.rubocop_todo.yml +0 -730
- data/.travis.yml +0 -62
- data/install-vips.sh +0 -26
data/lib/vips/image.rb
CHANGED
@@ -4,16 +4,19 @@
|
|
4
4
|
# Author:: John Cupitt (mailto:jcupitt@gmail.com)
|
5
5
|
# License:: MIT
|
6
6
|
|
7
|
-
require
|
7
|
+
require "ffi"
|
8
8
|
|
9
9
|
module Vips
|
10
10
|
private
|
11
11
|
|
12
12
|
attach_function :vips_image_new_matrix_from_array,
|
13
|
-
|
13
|
+
[:int, :int, :pointer, :int], :pointer
|
14
14
|
|
15
15
|
attach_function :vips_image_copy_memory, [:pointer], :pointer
|
16
16
|
|
17
|
+
attach_function :vips_image_set_progress, [:pointer, :bool], :void
|
18
|
+
attach_function :vips_image_set_kill, [:pointer, :bool], :void
|
19
|
+
|
17
20
|
attach_function :vips_filename_get_filename, [:string], :pointer
|
18
21
|
attach_function :vips_filename_get_options, [:string], :pointer
|
19
22
|
|
@@ -22,30 +25,35 @@ module Vips
|
|
22
25
|
attach_function :vips_foreign_find_load_buffer, [:pointer, :size_t], :string
|
23
26
|
attach_function :vips_foreign_find_save_buffer, [:string], :string
|
24
27
|
|
28
|
+
if Vips.at_least_libvips?(8, 9)
|
29
|
+
attach_function :vips_foreign_find_load_source, [:pointer], :string
|
30
|
+
attach_function :vips_foreign_find_save_target, [:string], :string
|
31
|
+
end
|
32
|
+
|
25
33
|
attach_function :vips_image_write_to_memory,
|
26
|
-
|
34
|
+
[:pointer, SizeStruct.ptr], :pointer
|
27
35
|
|
28
36
|
attach_function :vips_image_get_typeof, [:pointer, :string], :GType
|
29
37
|
attach_function :vips_image_get,
|
30
|
-
|
38
|
+
[:pointer, :string, GObject::GValue.ptr], :int
|
31
39
|
|
32
|
-
|
33
|
-
|
40
|
+
attach_function :vips_image_get_width, [:pointer], :int
|
41
|
+
attach_function :vips_image_get_height, [:pointer], :int
|
42
|
+
attach_function :vips_image_get_bands, [:pointer], :int
|
43
|
+
|
44
|
+
if Vips.at_least_libvips?(8, 5)
|
34
45
|
attach_function :vips_image_get_fields, [:pointer], :pointer
|
35
|
-
|
36
|
-
nil
|
46
|
+
attach_function :vips_image_hasalpha, [:pointer], :int
|
37
47
|
end
|
38
48
|
|
39
|
-
|
40
|
-
if Vips::at_least_libvips?(8, 6)
|
49
|
+
if Vips.at_least_libvips?(8, 6)
|
41
50
|
attach_function :vips_addalpha, [:pointer, :pointer, :varargs], :int
|
42
51
|
end
|
43
|
-
if Vips::at_least_libvips?(8, 5)
|
44
|
-
attach_function :vips_image_hasalpha, [:pointer], :int
|
45
|
-
end
|
46
52
|
|
53
|
+
# move these three lines to mutableimage when we finally remove set and
|
54
|
+
# remove in this class
|
47
55
|
attach_function :vips_image_set,
|
48
|
-
|
56
|
+
[:pointer, :string, GObject::GValue.ptr], :void
|
49
57
|
attach_function :vips_image_remove, [:pointer, :string], :void
|
50
58
|
|
51
59
|
attach_function :vips_band_format_iscomplex, [:int], :int
|
@@ -53,6 +61,9 @@ module Vips
|
|
53
61
|
|
54
62
|
attach_function :nickname_find, :vips_nickname_find, [:GType], :string
|
55
63
|
|
64
|
+
attach_function :vips_image_new_from_memory, [:pointer, :size_t, :int, :int, :int, :int], :pointer
|
65
|
+
attach_function :vips_image_new_from_memory_copy, [:pointer, :size_t, :int, :int, :int, :int], :pointer
|
66
|
+
|
56
67
|
# turn a raw pointer that must be freed into a self-freeing Ruby string
|
57
68
|
def self.p2str(pointer)
|
58
69
|
pointer = FFI::AutoPointer.new(pointer, GLib::G_FREE)
|
@@ -81,12 +92,10 @@ module Vips
|
|
81
92
|
|
82
93
|
class Struct < Vips::Object::Struct
|
83
94
|
include ImageLayout
|
84
|
-
|
85
95
|
end
|
86
96
|
|
87
97
|
class ManagedStruct < Vips::Object::ManagedStruct
|
88
98
|
include ImageLayout
|
89
|
-
|
90
99
|
end
|
91
100
|
|
92
101
|
class GenericPtr < FFI::Struct
|
@@ -96,17 +105,17 @@ module Vips
|
|
96
105
|
# handy for overloads ... want to be able to apply a function to an
|
97
106
|
# array or to a scalar
|
98
107
|
def self.smap x, &block
|
99
|
-
x.is_a?(Array) ? x.map {|y| smap(y, &block)} : block.(x)
|
108
|
+
x.is_a?(Array) ? x.map { |y| smap(y, &block) } : block.call(x)
|
100
109
|
end
|
101
110
|
|
102
111
|
def self.complex? format
|
103
112
|
format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format
|
104
|
-
Vips
|
113
|
+
Vips.vips_band_format_iscomplex(format_number) != 0
|
105
114
|
end
|
106
115
|
|
107
116
|
def self.float? format
|
108
117
|
format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format
|
109
|
-
Vips
|
118
|
+
Vips.vips_band_format_isfloat(format_number) != 0
|
110
119
|
end
|
111
120
|
|
112
121
|
# run a complex operation on a complex image, or an image with an even
|
@@ -115,12 +124,12 @@ module Vips
|
|
115
124
|
def self.run_cmplx image, &block
|
116
125
|
original_format = image.format
|
117
126
|
|
118
|
-
unless Image
|
127
|
+
unless Image.complex? image.format
|
119
128
|
if image.bands % 2 != 0
|
120
|
-
raise Error, "not an even number of bands"
|
129
|
+
raise Vips::Error, "not an even number of bands"
|
121
130
|
end
|
122
131
|
|
123
|
-
unless Image
|
132
|
+
unless Image.float? image.format
|
124
133
|
image = image.cast :float
|
125
134
|
end
|
126
135
|
|
@@ -128,9 +137,9 @@ module Vips
|
|
128
137
|
image = image.copy format: new_format, bands: image.bands / 2
|
129
138
|
end
|
130
139
|
|
131
|
-
image = block.(image)
|
140
|
+
image = block.call(image)
|
132
141
|
|
133
|
-
unless Image
|
142
|
+
unless Image.complex? original_format
|
134
143
|
new_format = image.format == :dpcomplex ? :double : :float
|
135
144
|
image = image.copy format: new_format, bands: image.bands * 2
|
136
145
|
end
|
@@ -178,26 +187,30 @@ module Vips
|
|
178
187
|
public
|
179
188
|
|
180
189
|
def inspect
|
181
|
-
"#<Image #{width}x#{height} #{format}, #{bands} bands, "
|
182
|
-
"#{interpretation}>"
|
190
|
+
"#<Image #{width}x#{height} #{format}, #{bands} bands, #{interpretation}>"
|
183
191
|
end
|
184
192
|
|
185
193
|
def respond_to? name, include_all = false
|
186
194
|
# To support keyword args, we need to tell Ruby that final image
|
187
195
|
# arguments cannot be hashes of keywords.
|
188
196
|
#
|
189
|
-
# https://makandracards.com/makandra/
|
197
|
+
# https://makandracards.com/makandra/
|
198
|
+
# 36013-heads-up-ruby-implicitly-converts-a-hash-to-keyword-arguments
|
190
199
|
return false if name == :to_hash
|
191
200
|
|
201
|
+
super
|
202
|
+
end
|
203
|
+
|
204
|
+
def respond_to_missing? name, include_all = false
|
192
205
|
# respond to all vips operations by nickname
|
193
|
-
return true if Vips
|
206
|
+
return true if Vips.type_find("VipsOperation", name.to_s) != 0
|
194
207
|
|
195
208
|
super
|
196
209
|
end
|
197
210
|
|
198
|
-
def self.
|
211
|
+
def self.respond_to_missing? name, include_all = false
|
199
212
|
# respond to all vips operations by nickname
|
200
|
-
return true if Vips
|
213
|
+
return true if Vips.type_find("VipsOperation", name.to_s) != 0
|
201
214
|
|
202
215
|
super
|
203
216
|
end
|
@@ -221,13 +234,13 @@ module Vips
|
|
221
234
|
# load options, for example:
|
222
235
|
#
|
223
236
|
# ```
|
224
|
-
# image = Vips::new_from_file "fred.jpg[shrink=2]"
|
237
|
+
# image = Vips::Image.new_from_file "fred.jpg[shrink=2]"
|
225
238
|
# ```
|
226
239
|
#
|
227
240
|
# You can also supply options as a hash, for example:
|
228
241
|
#
|
229
242
|
# ```
|
230
|
-
# image = Vips::new_from_file "fred.jpg", shrink: 2
|
243
|
+
# image = Vips::Image.new_from_file "fred.jpg", shrink: 2
|
231
244
|
# ```
|
232
245
|
#
|
233
246
|
# The full set of options available depend upon the load operation that
|
@@ -255,18 +268,18 @@ module Vips
|
|
255
268
|
def self.new_from_file name, **opts
|
256
269
|
# very common, and Vips::vips_filename_get_filename will segv if we
|
257
270
|
# pass this
|
258
|
-
raise Vips::Error, "filename is nil" if name
|
271
|
+
raise Vips::Error, "filename is nil" if name.nil?
|
259
272
|
|
260
|
-
filename = Vips
|
261
|
-
option_string = Vips
|
262
|
-
loader = Vips
|
263
|
-
raise Vips::Error if loader
|
273
|
+
filename = Vips.p2str(Vips.vips_filename_get_filename(name))
|
274
|
+
option_string = Vips.p2str(Vips.vips_filename_get_options(name))
|
275
|
+
loader = Vips.vips_foreign_find_load filename
|
276
|
+
raise Vips::Error if loader.nil?
|
264
277
|
|
265
278
|
Operation.call loader, [filename], opts, option_string
|
266
279
|
end
|
267
280
|
|
268
|
-
# Create a new {Image} for an image encoded
|
269
|
-
# JPEG
|
281
|
+
# Create a new {Image} for an image encoded in a format such as
|
282
|
+
# JPEG in a binary string. Load options may be passed as
|
270
283
|
# strings or appended as a hash. For example:
|
271
284
|
#
|
272
285
|
# ```
|
@@ -297,17 +310,119 @@ module Vips
|
|
297
310
|
# @macro vips.loadopts
|
298
311
|
# @return [Image] the loaded image
|
299
312
|
def self.new_from_buffer data, option_string, **opts
|
300
|
-
loader = Vips
|
301
|
-
raise Vips::Error if loader
|
313
|
+
loader = Vips.vips_foreign_find_load_buffer data, data.bytesize
|
314
|
+
raise Vips::Error if loader.nil?
|
302
315
|
|
303
316
|
Vips::Operation.call loader, [data], opts, option_string
|
304
317
|
end
|
305
318
|
|
319
|
+
# Create a new {Image} from a C-style array held in memory. For example:
|
320
|
+
#
|
321
|
+
# ```
|
322
|
+
# image = Vips::Image.black(16, 16) + 128
|
323
|
+
# data = image.write_to_memory
|
324
|
+
#
|
325
|
+
# x = Vips::Image.new_from_memory data,
|
326
|
+
# image.width, image.height, image.bands, image.format
|
327
|
+
# ```
|
328
|
+
#
|
329
|
+
# {new_from_memory} keeps a reference to the array of pixels you pass in
|
330
|
+
# to try to prevent that memory from being freed by the Ruby GC while it
|
331
|
+
# is being used.
|
332
|
+
#
|
333
|
+
# See {new_from_memory_copy} for a version of this method which does not
|
334
|
+
# keep a reference.
|
335
|
+
#
|
336
|
+
# @param data [String, FFI::Pointer] the data to load from
|
337
|
+
# @param width [Integer] width in pixels
|
338
|
+
# @param height [Integer] height in pixels
|
339
|
+
# @param bands [Integer] number of bands
|
340
|
+
# @param format [Symbol] band format
|
341
|
+
# @return [Image] the loaded image
|
342
|
+
def self.new_from_memory data, width, height, bands, format
|
343
|
+
size = data.bytesize
|
344
|
+
|
345
|
+
# prevent data from being freed with JRuby FFI
|
346
|
+
if defined?(JRUBY_VERSION) && !data.is_a?(FFI::Pointer)
|
347
|
+
data = ::FFI::MemoryPointer.new(:char, data.bytesize).write_bytes data
|
348
|
+
end
|
349
|
+
|
350
|
+
format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format
|
351
|
+
vi = Vips.vips_image_new_from_memory data, size,
|
352
|
+
width, height, bands, format_number
|
353
|
+
raise Vips::Error if vi.null?
|
354
|
+
image = new(vi)
|
355
|
+
|
356
|
+
# keep a secret ref to the underlying object .. this reference will be
|
357
|
+
# inherited by things that in turn depend on us, so the memory we are
|
358
|
+
# using will not be freed
|
359
|
+
image.references << data
|
360
|
+
|
361
|
+
image
|
362
|
+
end
|
363
|
+
|
364
|
+
# Create a new {Image} from memory and copies the memory area. See
|
365
|
+
# {new_from_memory} for a version of this method which does not copy the
|
366
|
+
# memory area.
|
367
|
+
#
|
368
|
+
# @param data [String, FFI::Pointer] the data to load from
|
369
|
+
# @param width [Integer] width in pixels
|
370
|
+
# @param height [Integer] height in pixels
|
371
|
+
# @param bands [Integer] number of bands
|
372
|
+
# @param format [Symbol] band format
|
373
|
+
# @return [Image] the loaded image
|
374
|
+
def self.new_from_memory_copy data, width, height, bands, format
|
375
|
+
format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format
|
376
|
+
vi = Vips.vips_image_new_from_memory_copy data, data.bytesize,
|
377
|
+
width, height, bands, format_number
|
378
|
+
raise Vips::Error if vi.null?
|
379
|
+
new(vi)
|
380
|
+
end
|
381
|
+
|
382
|
+
# Create a new {Image} from a source. Load options may be passed as
|
383
|
+
# strings or appended as a hash. For example:
|
384
|
+
#
|
385
|
+
# ```
|
386
|
+
# source = Vips::Source.new_from_file("k2.jpg")
|
387
|
+
# image = Vips::Image.new_from_source source, "shrink=2"
|
388
|
+
# ```
|
389
|
+
#
|
390
|
+
# or alternatively:
|
391
|
+
#
|
392
|
+
# ```
|
393
|
+
# image = Vips::Image.new_from_source source, "", shrink: 2
|
394
|
+
# ```
|
395
|
+
#
|
396
|
+
# The options available depend on the file format. Try something like:
|
397
|
+
#
|
398
|
+
# ```
|
399
|
+
# $ vips jpegload_source
|
400
|
+
# ```
|
401
|
+
#
|
402
|
+
# at the command-line to see the available options. Not all loaders
|
403
|
+
# support load from source, but at least JPEG, PNG and
|
404
|
+
# TIFF images will work.
|
405
|
+
#
|
406
|
+
# Loading is fast: only enough data is read to be able to fill
|
407
|
+
# out the header. Pixels will only be read and decompressed when they are
|
408
|
+
# needed.
|
409
|
+
#
|
410
|
+
# @param source [Vips::Source] the source to load from
|
411
|
+
# @param option_string [String] load options as a string
|
412
|
+
# @macro vips.loadopts
|
413
|
+
# @return [Image] the loaded image
|
414
|
+
def self.new_from_source source, option_string, **opts
|
415
|
+
loader = Vips.vips_foreign_find_load_source source
|
416
|
+
raise Vips::Error if loader.nil?
|
417
|
+
|
418
|
+
Vips::Operation.call loader, [source], opts, option_string
|
419
|
+
end
|
420
|
+
|
306
421
|
def self.matrix_from_array width, height, array
|
307
422
|
ptr = FFI::MemoryPointer.new :double, array.length
|
308
423
|
ptr.write_array_of_double array
|
309
|
-
image = Vips
|
310
|
-
|
424
|
+
image = Vips.vips_image_new_matrix_from_array width, height,
|
425
|
+
ptr, array.length
|
311
426
|
Vips::Image.new image
|
312
427
|
end
|
313
428
|
|
@@ -319,13 +434,13 @@ module Vips
|
|
319
434
|
# For example:
|
320
435
|
#
|
321
436
|
# ```
|
322
|
-
# image = Vips::new_from_array [1, 2, 3]
|
437
|
+
# image = Vips::Image.new_from_array [1, 2, 3]
|
323
438
|
# ```
|
324
439
|
#
|
325
440
|
# or
|
326
441
|
#
|
327
442
|
# ```
|
328
|
-
# image = Vips::new_from_array [
|
443
|
+
# image = Vips::Image.new_from_array [
|
329
444
|
# [-1, -1, -1],
|
330
445
|
# [-1, 16, -1],
|
331
446
|
# [-1, -1, -1]], 8
|
@@ -347,30 +462,35 @@ module Vips
|
|
347
462
|
if array[0].is_a? Array
|
348
463
|
height = array.length
|
349
464
|
width = array[0].length
|
350
|
-
unless array.all? {|x| x.is_a? Array}
|
465
|
+
unless array.all? { |x| x.is_a? Array }
|
351
466
|
raise Vips::Error, "Not a 2D array."
|
352
467
|
end
|
353
|
-
unless array.all? {|x| x.length == width}
|
468
|
+
unless array.all? { |x| x.length == width }
|
354
469
|
raise Vips::Error, "Array not rectangular."
|
355
470
|
end
|
471
|
+
|
356
472
|
array = array.flatten
|
357
473
|
else
|
358
474
|
height = 1
|
359
475
|
width = array.length
|
360
476
|
end
|
361
477
|
|
362
|
-
unless array.
|
478
|
+
unless array.length == width * height
|
479
|
+
raise Vips::Error, "Bad array dimensions."
|
480
|
+
end
|
481
|
+
|
482
|
+
unless array.all? { |x| x.is_a? Numeric }
|
363
483
|
raise Vips::Error, "Not all array elements are Numeric."
|
364
484
|
end
|
365
485
|
|
366
486
|
image = Vips::Image.matrix_from_array width, height, array
|
367
|
-
raise Vips::Error if image
|
368
|
-
|
369
|
-
# be careful to set them as double
|
370
|
-
image.set_type GObject::GDOUBLE_TYPE, 'scale', scale.to_f
|
371
|
-
image.set_type GObject::GDOUBLE_TYPE, 'offset', offset.to_f
|
487
|
+
raise Vips::Error if image.nil?
|
372
488
|
|
373
|
-
|
489
|
+
image.mutate do |mutable|
|
490
|
+
# be careful to set them as double
|
491
|
+
mutable.set_type! GObject::GDOUBLE_TYPE, "scale", scale.to_f
|
492
|
+
mutable.set_type! GObject::GDOUBLE_TYPE, "offset", offset.to_f
|
493
|
+
end
|
374
494
|
end
|
375
495
|
|
376
496
|
# A new image is created with the same width, height, format,
|
@@ -385,8 +505,8 @@ module Vips
|
|
385
505
|
def new_from_image value
|
386
506
|
pixel = (Vips::Image.black(1, 1) + value).cast(format)
|
387
507
|
image = pixel.embed 0, 0, width, height, extend: :copy
|
388
|
-
image.copy interpretation: interpretation,
|
389
|
-
|
508
|
+
image.copy interpretation: interpretation, xres: xres, yres: yres,
|
509
|
+
xoffset: xoffset, yoffset: yoffset
|
390
510
|
end
|
391
511
|
|
392
512
|
# Write this image to a file. Save options may be encoded in the
|
@@ -419,12 +539,12 @@ module Vips
|
|
419
539
|
#
|
420
540
|
# @param name [String] filename to write to
|
421
541
|
def write_to_file name, **opts
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
542
|
+
raise Vips::Error, "filename is nil" if name.nil?
|
543
|
+
|
544
|
+
filename = Vips.p2str(Vips.vips_filename_get_filename(name))
|
545
|
+
option_string = Vips.p2str(Vips.vips_filename_get_options(name))
|
546
|
+
saver = Vips.vips_foreign_find_save filename
|
547
|
+
raise Vips::Error if saver.nil?
|
428
548
|
|
429
549
|
Vips::Operation.call saver, [self, filename], opts, option_string
|
430
550
|
|
@@ -457,21 +577,55 @@ module Vips
|
|
457
577
|
# @macro vips.saveopts
|
458
578
|
# @return [String] the image saved in the specified format
|
459
579
|
def write_to_buffer format_string, **opts
|
460
|
-
filename
|
461
|
-
|
462
|
-
option_string =
|
463
|
-
|
464
|
-
|
465
|
-
if saver == nil
|
466
|
-
raise Vips::Error, "No known saver for '#{filename}'."
|
467
|
-
end
|
580
|
+
raise Vips::Error, "filename is nil" if format_string.nil?
|
581
|
+
filename = Vips.p2str(Vips.vips_filename_get_filename(format_string))
|
582
|
+
option_string = Vips.p2str(Vips.vips_filename_get_options(format_string))
|
583
|
+
saver = Vips.vips_foreign_find_save_buffer filename
|
584
|
+
raise Vips::Error if saver.nil?
|
468
585
|
|
469
586
|
buffer = Vips::Operation.call saver, [self], opts, option_string
|
470
|
-
raise Vips::Error if buffer
|
587
|
+
raise Vips::Error if buffer.nil?
|
471
588
|
|
472
589
|
write_gc
|
473
590
|
|
474
|
-
|
591
|
+
buffer
|
592
|
+
end
|
593
|
+
|
594
|
+
# Write this image to a target. Save options may be encoded in
|
595
|
+
# the format_string or given as a hash. For example:
|
596
|
+
#
|
597
|
+
# ```ruby
|
598
|
+
# target = Vips::Target.new_to_file "k2.jpg"
|
599
|
+
# image.write_to_target target, ".jpg[Q=90]"
|
600
|
+
# ```
|
601
|
+
#
|
602
|
+
# or equivalently:
|
603
|
+
#
|
604
|
+
# ```ruby
|
605
|
+
# image.write_to_target target, ".jpg", Q: 90
|
606
|
+
# ```
|
607
|
+
#
|
608
|
+
# The full set of save options depend on the selected saver. Try
|
609
|
+
# something like:
|
610
|
+
#
|
611
|
+
# ```
|
612
|
+
# $ vips jpegsave_target
|
613
|
+
# ```
|
614
|
+
#
|
615
|
+
# to see all the available options for JPEG save.
|
616
|
+
#
|
617
|
+
# @param target [Vips::Target] the target to write to
|
618
|
+
# @param format_string [String] save format plus string options
|
619
|
+
# @macro vips.saveopts
|
620
|
+
def write_to_target target, format_string, **opts
|
621
|
+
raise Vips::Error, "filename is nil" if format_string.nil?
|
622
|
+
filename = Vips.p2str(Vips.vips_filename_get_filename(format_string))
|
623
|
+
option_string = Vips.p2str(Vips.vips_filename_get_options(format_string))
|
624
|
+
saver = Vips.vips_foreign_find_save_target filename
|
625
|
+
raise Vips::Error if saver.nil?
|
626
|
+
|
627
|
+
Vips::Operation.call saver, [self, target], opts, option_string
|
628
|
+
write_gc
|
475
629
|
end
|
476
630
|
|
477
631
|
# Write this image to a large memory buffer.
|
@@ -479,7 +633,8 @@ module Vips
|
|
479
633
|
# @return [String] the pixels as a huge binary string
|
480
634
|
def write_to_memory
|
481
635
|
len = Vips::SizeStruct.new
|
482
|
-
ptr = Vips
|
636
|
+
ptr = Vips.vips_image_write_to_memory self, len
|
637
|
+
raise Vips::Error if ptr.nil?
|
483
638
|
|
484
639
|
# wrap up as an autopointer
|
485
640
|
ptr = FFI::AutoPointer.new(ptr, GLib::G_FREE)
|
@@ -487,6 +642,28 @@ module Vips
|
|
487
642
|
ptr.get_bytes 0, len[:value]
|
488
643
|
end
|
489
644
|
|
645
|
+
# Turn progress signalling on and off.
|
646
|
+
#
|
647
|
+
# If this is on, the most-downstream image from this image will issue
|
648
|
+
# progress signals.
|
649
|
+
#
|
650
|
+
# @see Object#signal_connect
|
651
|
+
# @param state [Boolean] progress signalling state
|
652
|
+
def set_progress state
|
653
|
+
Vips.vips_image_set_progress self, state
|
654
|
+
end
|
655
|
+
|
656
|
+
# Kill computation of this time.
|
657
|
+
#
|
658
|
+
# Set true to stop computation of this image. You can call this from a
|
659
|
+
# progress handler, for example.
|
660
|
+
#
|
661
|
+
# @see Object#signal_connect
|
662
|
+
# @param kill [Boolean] stop computation
|
663
|
+
def set_kill kill
|
664
|
+
Vips.vips_image_set_kill self, kill
|
665
|
+
end
|
666
|
+
|
490
667
|
# Get the `GType` of a metadata field. The result is 0 if no such field
|
491
668
|
# exists.
|
492
669
|
#
|
@@ -496,12 +673,12 @@ module Vips
|
|
496
673
|
def get_typeof name
|
497
674
|
# on libvips before 8.5, property types must be searched first,
|
498
675
|
# since vips_image_get_typeof returned built-in enums as int
|
499
|
-
unless Vips
|
676
|
+
unless Vips.at_least_libvips?(8, 5)
|
500
677
|
gtype = parent_get_typeof name
|
501
678
|
return gtype if gtype != 0
|
502
679
|
end
|
503
680
|
|
504
|
-
Vips
|
681
|
+
Vips.vips_image_get_typeof self, name
|
505
682
|
end
|
506
683
|
|
507
684
|
# Get a metadata item from an image. Ruby types are constructed
|
@@ -520,15 +697,16 @@ module Vips
|
|
520
697
|
def get name
|
521
698
|
# with old libvips, we must fetch properties (as opposed to
|
522
699
|
# metadata) via VipsObject
|
523
|
-
unless Vips
|
700
|
+
unless Vips.at_least_libvips?(8, 5)
|
524
701
|
return super if parent_get_typeof(name) != 0
|
525
702
|
end
|
526
703
|
|
527
704
|
gvalue = GObject::GValue.alloc
|
528
|
-
|
529
|
-
|
705
|
+
raise Vips::Error if Vips.vips_image_get(self, name, gvalue) != 0
|
706
|
+
result = gvalue.get
|
707
|
+
gvalue.unset
|
530
708
|
|
531
|
-
|
709
|
+
result
|
532
710
|
end
|
533
711
|
|
534
712
|
# Get the names of all fields on an image. Use this to loop over all
|
@@ -539,66 +717,64 @@ module Vips
|
|
539
717
|
# vips_image_get_fields() was added in libvips 8.5
|
540
718
|
return [] unless Vips.respond_to? :vips_image_get_fields
|
541
719
|
|
542
|
-
array = Vips
|
720
|
+
array = Vips.vips_image_get_fields self
|
543
721
|
|
544
722
|
names = []
|
545
723
|
p = array
|
546
724
|
until (q = p.read_pointer).null?
|
547
725
|
names << q.read_string
|
548
|
-
GLib
|
726
|
+
GLib.g_free q
|
549
727
|
p += FFI::Type::POINTER.size
|
550
728
|
end
|
551
|
-
GLib
|
729
|
+
GLib.g_free array
|
552
730
|
|
553
731
|
names
|
554
732
|
end
|
555
733
|
|
556
|
-
#
|
557
|
-
#
|
734
|
+
# Mutate an image with a block. Inside the block, you can call methods
|
735
|
+
# which modify the image, such as setting or removing metadata, or
|
736
|
+
# modifying pixels.
|
558
737
|
#
|
559
|
-
# For example
|
738
|
+
# For example:
|
560
739
|
#
|
561
|
-
# ```
|
562
|
-
#
|
740
|
+
# ```ruby
|
741
|
+
# image = image.mutate do |x|
|
742
|
+
# (0 ... 1).step(0.01) do |i|
|
743
|
+
# x.draw_line! 255, x.width * i, 0, 0, x.height * (1 - i)
|
744
|
+
# end
|
745
|
+
# end
|
563
746
|
# ```
|
564
747
|
#
|
565
|
-
#
|
748
|
+
# See {MutableImage}.
|
749
|
+
def mutate
|
750
|
+
mutable = Vips::MutableImage.new self
|
751
|
+
yield mutable
|
752
|
+
mutable.image
|
753
|
+
end
|
754
|
+
|
755
|
+
# This method is deprecated.
|
566
756
|
#
|
567
|
-
#
|
568
|
-
# @param gtype [Integer] GType of item
|
569
|
-
# @param name [String] Metadata field to set
|
570
|
-
# @param value [Object] Value to set
|
757
|
+
# Please use {MutableImage#set_type!} instead.
|
571
758
|
def set_type gtype, name, value
|
572
759
|
gvalue = GObject::GValue.alloc
|
573
760
|
gvalue.init gtype
|
574
761
|
gvalue.set value
|
575
|
-
Vips
|
762
|
+
Vips.vips_image_set self, name, gvalue
|
763
|
+
gvalue.unset
|
576
764
|
end
|
577
765
|
|
578
|
-
#
|
579
|
-
# already exist. Ruby types are automatically transformed into the
|
580
|
-
# matching `GValue`, if possible.
|
766
|
+
# This method is deprecated.
|
581
767
|
#
|
582
|
-
#
|
583
|
-
#
|
584
|
-
# ```
|
585
|
-
# x = y.set "icc-profile-data", profile
|
586
|
-
# ```
|
587
|
-
#
|
588
|
-
# where `profile` is an ICC profile held as a binary string object.
|
589
|
-
#
|
590
|
-
# @see set_type
|
591
|
-
# @param name [String] Metadata field to set
|
592
|
-
# @param value [Object] Value to set
|
768
|
+
# Please use {MutableImage#set!} instead.
|
593
769
|
def set name, value
|
594
770
|
set_type get_typeof(name), name, value
|
595
771
|
end
|
596
772
|
|
597
|
-
#
|
773
|
+
# This method is deprecated.
|
598
774
|
#
|
599
|
-
#
|
775
|
+
# Please use {MutableImage#remove!} instead.
|
600
776
|
def remove name
|
601
|
-
Vips
|
777
|
+
Vips.vips_image_remove self, name
|
602
778
|
end
|
603
779
|
|
604
780
|
# compatibility: old name for get
|
@@ -606,7 +782,9 @@ module Vips
|
|
606
782
|
get name
|
607
783
|
end
|
608
784
|
|
609
|
-
#
|
785
|
+
# This method is deprecated.
|
786
|
+
#
|
787
|
+
# Please use {MutableImage#set!} instead.
|
610
788
|
def set_value name, value
|
611
789
|
set name, value
|
612
790
|
end
|
@@ -615,21 +793,21 @@ module Vips
|
|
615
793
|
#
|
616
794
|
# @return [Integer] image width, in pixels
|
617
795
|
def width
|
618
|
-
|
796
|
+
Vips.vips_image_get_width self
|
619
797
|
end
|
620
798
|
|
621
799
|
# Get image height, in pixels.
|
622
800
|
#
|
623
801
|
# @return [Integer] image height, in pixels
|
624
802
|
def height
|
625
|
-
|
803
|
+
Vips.vips_image_get_height self
|
626
804
|
end
|
627
805
|
|
628
806
|
# Get number of image bands.
|
629
807
|
#
|
630
808
|
# @return [Integer] number of image bands
|
631
809
|
def bands
|
632
|
-
|
810
|
+
Vips.vips_image_get_bands self
|
633
811
|
end
|
634
812
|
|
635
813
|
# Get image format.
|
@@ -713,23 +891,23 @@ module Vips
|
|
713
891
|
[width, height]
|
714
892
|
end
|
715
893
|
|
716
|
-
if Vips
|
894
|
+
if Vips.at_least_libvips?(8, 5)
|
717
895
|
# Detect if image has an alpha channel
|
718
896
|
#
|
719
897
|
# @return [Boolean] true if image has an alpha channel.
|
720
898
|
def has_alpha?
|
721
|
-
|
899
|
+
Vips.vips_image_hasalpha(self) != 0
|
722
900
|
end
|
723
901
|
end
|
724
902
|
|
725
903
|
# vips_addalpha was added in libvips 8.6
|
726
|
-
if Vips
|
904
|
+
if Vips.at_least_libvips?(8, 6)
|
727
905
|
# Append an alpha channel to an image.
|
728
906
|
#
|
729
907
|
# @return [Image] new image
|
730
908
|
def add_alpha
|
731
909
|
ptr = GenericPtr.new
|
732
|
-
result = Vips
|
910
|
+
result = Vips.vips_addalpha self, ptr
|
733
911
|
raise Vips::Error if result != 0
|
734
912
|
|
735
913
|
Vips::Image.new ptr[:value]
|
@@ -744,7 +922,7 @@ module Vips
|
|
744
922
|
#
|
745
923
|
# @return [Image] new memory image
|
746
924
|
def copy_memory
|
747
|
-
new_image = Vips
|
925
|
+
new_image = Vips.vips_image_copy_memory self
|
748
926
|
Vips::Image.new new_image
|
749
927
|
end
|
750
928
|
|
@@ -754,7 +932,7 @@ module Vips
|
|
754
932
|
#
|
755
933
|
# @return [Image] modified image
|
756
934
|
def draw_point ink, left, top, **opts
|
757
|
-
draw_rect ink, left, top, 1, 1, opts
|
935
|
+
draw_rect ink, left, top, 1, 1, **opts
|
758
936
|
end
|
759
937
|
|
760
938
|
# Add an image, constant or array.
|
@@ -772,7 +950,7 @@ module Vips
|
|
772
950
|
# @return [Image] result of subtraction
|
773
951
|
def - other
|
774
952
|
other.is_a?(Vips::Image) ?
|
775
|
-
subtract(other) : linear(1, Image
|
953
|
+
subtract(other) : linear(1, Image.smap(other) { |x| x * -1 })
|
776
954
|
end
|
777
955
|
|
778
956
|
# Multiply an image, constant or array.
|
@@ -790,7 +968,7 @@ module Vips
|
|
790
968
|
# @return [Image] result of division
|
791
969
|
def / other
|
792
970
|
other.is_a?(Vips::Image) ?
|
793
|
-
divide(other) : linear(Image
|
971
|
+
divide(other) : linear(Image.smap(other) { |x| 1.0 / x }, 0)
|
794
972
|
end
|
795
973
|
|
796
974
|
# Remainder after integer division with an image, constant or array.
|
@@ -916,7 +1094,7 @@ module Vips
|
|
916
1094
|
# @return [Image] result of equality
|
917
1095
|
def == other
|
918
1096
|
# for equality, we must allow tests against nil
|
919
|
-
if other
|
1097
|
+
if other.nil?
|
920
1098
|
false
|
921
1099
|
else
|
922
1100
|
call_enum "relational", other, :equal
|
@@ -929,7 +1107,7 @@ module Vips
|
|
929
1107
|
# @return [Image] result of inequality
|
930
1108
|
def != other
|
931
1109
|
# for equality, we must allow tests against nil
|
932
|
-
if other
|
1110
|
+
if other.nil?
|
933
1111
|
true
|
934
1112
|
else
|
935
1113
|
call_enum "relational", other, :noteq
|
@@ -951,38 +1129,40 @@ module Vips
|
|
951
1129
|
end
|
952
1130
|
end
|
953
1131
|
|
954
|
-
# Convert to an
|
1132
|
+
# Convert to an Enumerator. Similar to `#to_a` but lazier.
|
955
1133
|
#
|
956
|
-
# @return [
|
957
|
-
def
|
958
|
-
# we render the image to a big string, then unpack
|
959
|
-
# as a Ruby array of the correct type
|
960
|
-
memory = write_to_memory
|
961
|
-
|
1134
|
+
# @return [Enumerator] Enumerator of Enumerators of Arrays of Numerics
|
1135
|
+
def to_enum
|
962
1136
|
# make the template for unpack
|
963
1137
|
template = {
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
}[format] +
|
1138
|
+
char: "c",
|
1139
|
+
uchar: "C",
|
1140
|
+
short: "s_",
|
1141
|
+
ushort: "S_",
|
1142
|
+
int: "i_",
|
1143
|
+
uint: "I_",
|
1144
|
+
float: "f",
|
1145
|
+
double: "d",
|
1146
|
+
complex: "f",
|
1147
|
+
dpcomplex: "d"
|
1148
|
+
}[format] + "*"
|
975
1149
|
|
976
|
-
#
|
977
|
-
array
|
1150
|
+
# we render the image to a big string, then unpack into
|
1151
|
+
# one-dimensional array as a Ruby array of the correct type
|
1152
|
+
array = write_to_memory.unpack template
|
978
1153
|
|
979
|
-
# gather
|
980
|
-
pixel_array = array.each_slice
|
1154
|
+
# gather bands of a pixel together
|
1155
|
+
pixel_array = array.each_slice bands
|
981
1156
|
|
982
|
-
#
|
983
|
-
|
1157
|
+
# gather pixels of a row together
|
1158
|
+
pixel_array.each_slice width
|
1159
|
+
end
|
984
1160
|
|
985
|
-
|
1161
|
+
# Convert to an Array. This will be slow for large images.
|
1162
|
+
#
|
1163
|
+
# @return [Array] Array of Arrays of Arrays of Numerics
|
1164
|
+
def to_a
|
1165
|
+
to_enum.to_a
|
986
1166
|
end
|
987
1167
|
|
988
1168
|
# Return the largest integral value not greater than the argument.
|
@@ -1031,7 +1211,7 @@ module Vips
|
|
1031
1211
|
#
|
1032
1212
|
# @return [Array<Image>] Array of n one-band images
|
1033
1213
|
def bandsplit
|
1034
|
-
(0...bands).map {|i| extract_band i}
|
1214
|
+
(0...bands).map { |i| extract_band i }
|
1035
1215
|
end
|
1036
1216
|
|
1037
1217
|
# Join a set of images bandwise.
|
@@ -1044,7 +1224,7 @@ module Vips
|
|
1044
1224
|
end
|
1045
1225
|
|
1046
1226
|
# if other is just Numeric, we can use bandjoin_const
|
1047
|
-
not_all_real = !other.all?{|x| x.is_a? Numeric}
|
1227
|
+
not_all_real = !other.all? { |x| x.is_a? Numeric }
|
1048
1228
|
|
1049
1229
|
if not_all_real
|
1050
1230
|
Vips::Image.bandjoin([self] + other)
|
@@ -1058,7 +1238,10 @@ module Vips
|
|
1058
1238
|
# @param overlay [Image, Array<Image>] images to composite
|
1059
1239
|
# @param mode [BlendMode, Array<BlendMode>] blend modes to use
|
1060
1240
|
# @param opts [Hash] Set of options
|
1061
|
-
# @option opts [
|
1241
|
+
# @option opts [Array<Integer>] :x x positions of overlay
|
1242
|
+
# @option opts [Array<Integer>] :y y positions of overlay
|
1243
|
+
# @option opts [Vips::Interpretation] :compositing_space Composite images
|
1244
|
+
# in this colour space
|
1062
1245
|
# @option opts [Boolean] :premultiplied Images have premultiplied alpha
|
1063
1246
|
# @return [Image] blended image
|
1064
1247
|
def composite overlay, mode, **opts
|
@@ -1073,7 +1256,7 @@ module Vips
|
|
1073
1256
|
GObject::GValue.from_nick Vips::BLEND_MODE_TYPE, x
|
1074
1257
|
end
|
1075
1258
|
|
1076
|
-
Vips::Image.composite([self] + overlay, mode, opts)
|
1259
|
+
Vips::Image.composite([self] + overlay, mode, **opts)
|
1077
1260
|
end
|
1078
1261
|
|
1079
1262
|
# Return the coordinates of the image maximum.
|
@@ -1082,9 +1265,9 @@ module Vips
|
|
1082
1265
|
# coordinate of maximum
|
1083
1266
|
def maxpos
|
1084
1267
|
v, opts = max x: true, y: true
|
1085
|
-
x = opts[
|
1086
|
-
y = opts[
|
1087
|
-
|
1268
|
+
x = opts["x"]
|
1269
|
+
y = opts["y"]
|
1270
|
+
[v, x, y]
|
1088
1271
|
end
|
1089
1272
|
|
1090
1273
|
# Return the coordinates of the image minimum.
|
@@ -1093,9 +1276,9 @@ module Vips
|
|
1093
1276
|
# coordinate of minimum
|
1094
1277
|
def minpos
|
1095
1278
|
v, opts = min x: true, y: true
|
1096
|
-
x = opts[
|
1097
|
-
y = opts[
|
1098
|
-
|
1279
|
+
x = opts["x"]
|
1280
|
+
y = opts["y"]
|
1281
|
+
[v, x, y]
|
1099
1282
|
end
|
1100
1283
|
|
1101
1284
|
# a median filter
|
@@ -1103,7 +1286,7 @@ module Vips
|
|
1103
1286
|
# @param size [Integer] size of filter window
|
1104
1287
|
# @return [Image] result of median filter
|
1105
1288
|
def median size = 3
|
1106
|
-
rank size, size,
|
1289
|
+
rank size, size, size**2 / 2
|
1107
1290
|
end
|
1108
1291
|
|
1109
1292
|
# Return the real part of a complex image.
|
@@ -1130,7 +1313,7 @@ module Vips
|
|
1130
1313
|
# @see xyz
|
1131
1314
|
# @return [Image] image converted to polar coordinates
|
1132
1315
|
def polar
|
1133
|
-
Image
|
1316
|
+
Image.run_cmplx(self) { |x| x.complex :polar }
|
1134
1317
|
end
|
1135
1318
|
|
1136
1319
|
# Return an image with polar pixels converted to rectangular.
|
@@ -1143,7 +1326,7 @@ module Vips
|
|
1143
1326
|
# @see xyz
|
1144
1327
|
# @return [Image] image converted to rectangular coordinates
|
1145
1328
|
def rect
|
1146
|
-
Image
|
1329
|
+
Image.run_cmplx(self) { |x| x.complex :rect }
|
1147
1330
|
end
|
1148
1331
|
|
1149
1332
|
# Return the complex conjugate of an image.
|
@@ -1155,7 +1338,7 @@ module Vips
|
|
1155
1338
|
#
|
1156
1339
|
# @return [Image] complex conjugate
|
1157
1340
|
def conj
|
1158
|
-
Image
|
1341
|
+
Image.run_cmplx(self) { |x| x.complex :conj }
|
1159
1342
|
end
|
1160
1343
|
|
1161
1344
|
# Calculate the cross phase of two images.
|
@@ -1305,7 +1488,7 @@ module Vips
|
|
1305
1488
|
# @option opts [Boolean] :blend (false) Blend smoothly between th and el
|
1306
1489
|
# @return [Image] merged image
|
1307
1490
|
def ifthenelse(th, el, **opts)
|
1308
|
-
match_image = [th, el, self].find {|x| x.is_a? Vips::Image}
|
1491
|
+
match_image = [th, el, self].find { |x| x.is_a? Vips::Image }
|
1309
1492
|
|
1310
1493
|
unless th.is_a? Vips::Image
|
1311
1494
|
th = Operation.imageize match_image, th
|
@@ -1323,147 +1506,125 @@ module Vips
|
|
1323
1506
|
# @param opts [Hash] Set of options
|
1324
1507
|
# @return [Vips::Image] Output image
|
1325
1508
|
def scaleimage **opts
|
1326
|
-
Vips::Image.scale self, opts
|
1509
|
+
Vips::Image.scale self, **opts
|
1327
1510
|
end
|
1328
|
-
|
1329
1511
|
end
|
1330
1512
|
end
|
1331
1513
|
|
1332
1514
|
module Vips
|
1333
|
-
|
1334
|
-
# This method generates yard comments for all the dynamically bound
|
1515
|
+
# This module generates yard comments for all the dynamically bound
|
1335
1516
|
# vips operations.
|
1336
1517
|
#
|
1337
1518
|
# Regenerate with something like:
|
1338
1519
|
#
|
1339
1520
|
# ```
|
1340
1521
|
# $ ruby > methods.rb
|
1341
|
-
# require
|
1522
|
+
# require "vips"; Vips::Yard.generate
|
1342
1523
|
# ^D
|
1343
1524
|
# ```
|
1344
1525
|
|
1345
|
-
|
1346
|
-
# these have hand-written methods, see above
|
1347
|
-
no_generate = ["scale", "bandjoin", "composite", "ifthenelse"]
|
1348
|
-
|
1526
|
+
module Yard
|
1349
1527
|
# map gobject's type names to Ruby
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1528
|
+
MAP_GO_TO_RUBY = {
|
1529
|
+
"gboolean" => "Boolean",
|
1530
|
+
"gint" => "Integer",
|
1531
|
+
"gdouble" => "Float",
|
1532
|
+
"gfloat" => "Float",
|
1533
|
+
"gchararray" => "String",
|
1534
|
+
"VipsImage" => "Vips::Image",
|
1535
|
+
"VipsInterpolate" => "Vips::Interpolate",
|
1536
|
+
"VipsConnection" => "Vips::Connection",
|
1537
|
+
"VipsSource" => "Vips::Source",
|
1538
|
+
"VipsTarget" => "Vips::Target",
|
1539
|
+
"VipsSourceCustom" => "Vips::SourceCustom",
|
1540
|
+
"VipsTargetCustom" => "Vips::TargetCustom",
|
1541
|
+
"VipsArrayDouble" => "Array<Double>",
|
1542
|
+
"VipsArrayInt" => "Array<Integer>",
|
1543
|
+
"VipsArrayImage" => "Array<Image>",
|
1544
|
+
"VipsArrayString" => "Array<String>"
|
1362
1545
|
}
|
1363
1546
|
|
1364
|
-
|
1365
|
-
|
1366
|
-
return if (op_flags & OPERATION_DEPRECATED) != 0
|
1367
|
-
return if no_generate.include? nickname
|
1368
|
-
description = Vips::vips_object_get_description op
|
1369
|
-
|
1370
|
-
# find and classify all the arguments the operator can take
|
1371
|
-
required_input = []
|
1372
|
-
optional_input = []
|
1373
|
-
required_output = []
|
1374
|
-
optional_output = []
|
1375
|
-
member_x = nil
|
1376
|
-
op.argument_map do |pspec, argument_class, argument_instance|
|
1377
|
-
arg_flags = argument_class[:flags]
|
1378
|
-
next if (arg_flags & ARGUMENT_CONSTRUCT) == 0
|
1379
|
-
next if (arg_flags & ARGUMENT_DEPRECATED) != 0
|
1380
|
-
|
1381
|
-
name = pspec[:name].tr("-", "_")
|
1382
|
-
# 'in' as a param name confuses yard
|
1383
|
-
name = "im" if name == "in"
|
1384
|
-
gtype = pspec[:value_type]
|
1385
|
-
fundamental = GObject::g_type_fundamental gtype
|
1386
|
-
type_name = GObject::g_type_name gtype
|
1387
|
-
if map_go_to_ruby.include? type_name
|
1388
|
-
type_name = map_go_to_ruby[type_name]
|
1389
|
-
end
|
1390
|
-
if fundamental == GObject::GFLAGS_TYPE ||
|
1391
|
-
fundamental == GObject::GENUM_TYPE
|
1392
|
-
type_name = "Vips::" + type_name[/Vips(.*)/, 1]
|
1393
|
-
end
|
1394
|
-
blurb = GObject::g_param_spec_get_blurb pspec
|
1395
|
-
value = {:name => name,
|
1396
|
-
:flags => arg_flags,
|
1397
|
-
:gtype => gtype,
|
1398
|
-
:type_name => type_name,
|
1399
|
-
:blurb => blurb}
|
1400
|
-
|
1401
|
-
if (arg_flags & ARGUMENT_INPUT) != 0
|
1402
|
-
if (arg_flags & ARGUMENT_REQUIRED) != 0
|
1403
|
-
# note the first required input image, if any ... we
|
1404
|
-
# will be a method of this instance
|
1405
|
-
if !member_x && gtype == Vips::IMAGE_TYPE
|
1406
|
-
member_x = value
|
1407
|
-
else
|
1408
|
-
required_input << value
|
1409
|
-
end
|
1410
|
-
else
|
1411
|
-
optional_input << value
|
1412
|
-
end
|
1413
|
-
end
|
1547
|
+
# these have hand-written methods, see above
|
1548
|
+
NO_GENERATE = ["scale", "bandjoin", "composite", "ifthenelse"]
|
1414
1549
|
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1550
|
+
# these are aliased (appear under several names)
|
1551
|
+
ALIAS = ["crop"]
|
1552
|
+
|
1553
|
+
# turn a gtype into a ruby type name
|
1554
|
+
def self.gtype_to_ruby gtype
|
1555
|
+
fundamental = GObject.g_type_fundamental gtype
|
1556
|
+
type_name = GObject.g_type_name gtype
|
1557
|
+
|
1558
|
+
if MAP_GO_TO_RUBY.include? type_name
|
1559
|
+
type_name = MAP_GO_TO_RUBY[type_name]
|
1560
|
+
end
|
1425
1561
|
|
1562
|
+
if fundamental == GObject::GFLAGS_TYPE ||
|
1563
|
+
fundamental == GObject::GENUM_TYPE
|
1564
|
+
type_name = "Vips::" + type_name[/Vips(.*)/, 1]
|
1426
1565
|
end
|
1427
1566
|
|
1567
|
+
type_name
|
1568
|
+
end
|
1569
|
+
|
1570
|
+
def self.generate_operation introspect
|
1571
|
+
return if (introspect.flags & OPERATION_DEPRECATED) != 0
|
1572
|
+
return if NO_GENERATE.include? introspect.name
|
1573
|
+
|
1574
|
+
method_args = introspect.method_args
|
1575
|
+
required_output = introspect.required_output
|
1576
|
+
optional_input = introspect.optional_input
|
1577
|
+
optional_output = introspect.optional_output
|
1578
|
+
|
1428
1579
|
print "# @!method "
|
1429
|
-
print "self." unless member_x
|
1430
|
-
print "#{
|
1431
|
-
print
|
1432
|
-
print ", " if
|
1580
|
+
print "self." unless introspect.member_x
|
1581
|
+
print "#{introspect.name}("
|
1582
|
+
print method_args.map { |x| x[:yard_name] }.join(", ")
|
1583
|
+
print ", " if method_args.length > 0
|
1433
1584
|
puts "**opts)"
|
1434
1585
|
|
1435
|
-
puts "# #{description.capitalize}."
|
1586
|
+
puts "# #{introspect.description.capitalize}."
|
1587
|
+
|
1588
|
+
method_args.each do |details|
|
1589
|
+
yard_name = details[:yard_name]
|
1590
|
+
gtype = details[:gtype]
|
1591
|
+
blurb = details[:blurb]
|
1436
1592
|
|
1437
|
-
|
1438
|
-
puts "# @param #{arg[:name]} [#{arg[:type_name]}] " +
|
1439
|
-
"#{arg[:blurb]}"
|
1593
|
+
puts "# @param #{yard_name} [#{gtype_to_ruby(gtype)}] #{blurb}"
|
1440
1594
|
end
|
1441
1595
|
|
1442
1596
|
puts "# @param opts [Hash] Set of options"
|
1443
|
-
optional_input.each do |
|
1444
|
-
|
1445
|
-
|
1597
|
+
optional_input.each do |arg_name, details|
|
1598
|
+
yard_name = details[:yard_name]
|
1599
|
+
gtype = details[:gtype]
|
1600
|
+
blurb = details[:blurb]
|
1601
|
+
|
1602
|
+
puts "# @option opts [#{gtype_to_ruby(gtype)}] :#{yard_name} #{blurb}"
|
1446
1603
|
end
|
1447
|
-
optional_output.each do |
|
1448
|
-
|
1449
|
-
|
1604
|
+
optional_output.each do |arg_name, details|
|
1605
|
+
yard_name = details[:yard_name]
|
1606
|
+
gtype = details[:gtype]
|
1607
|
+
blurb = details[:blurb]
|
1608
|
+
|
1609
|
+
print "# @option opts [#{gtype_to_ruby(gtype)}] :#{yard_name}"
|
1610
|
+
puts " Output #{blurb}"
|
1450
1611
|
end
|
1451
1612
|
|
1452
1613
|
print "# @return ["
|
1453
1614
|
if required_output.length == 0
|
1454
1615
|
print "nil"
|
1455
1616
|
elsif required_output.length == 1
|
1456
|
-
print required_output.first[:
|
1457
|
-
|
1458
|
-
|
1459
|
-
print required_output.map{|x| x[:
|
1617
|
+
print gtype_to_ruby(required_output.first[:gtype])
|
1618
|
+
else
|
1619
|
+
print "Array<"
|
1620
|
+
print required_output.map { |x| gtype_to_ruby(x[:gtype]) }.join(", ")
|
1460
1621
|
print ">"
|
1461
1622
|
end
|
1462
1623
|
if optional_output.length > 0
|
1463
1624
|
print ", Hash<Symbol => Object>"
|
1464
1625
|
end
|
1465
1626
|
print "] "
|
1466
|
-
print required_output.map{|x| x[:blurb]}.join(", ")
|
1627
|
+
print required_output.map { |x| x[:blurb] }.join(", ")
|
1467
1628
|
if optional_output.length > 0
|
1468
1629
|
print ", " if required_output.length > 0
|
1469
1630
|
print "Hash of optional output items"
|
@@ -1473,30 +1634,42 @@ module Vips
|
|
1473
1634
|
puts ""
|
1474
1635
|
end
|
1475
1636
|
|
1476
|
-
|
1477
|
-
|
1637
|
+
def self.generate
|
1638
|
+
alias_gtypes = {}
|
1639
|
+
ALIAS.each do |name|
|
1640
|
+
gtype = Vips.type_find "VipsOperation", name
|
1641
|
+
alias_gtypes[gtype] = name
|
1642
|
+
end
|
1643
|
+
|
1644
|
+
generate_class = lambda do |gtype, _|
|
1645
|
+
name = if alias_gtypes.key? gtype
|
1646
|
+
alias_gtypes[gtype]
|
1647
|
+
else
|
1648
|
+
Vips.nickname_find gtype
|
1649
|
+
end
|
1478
1650
|
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1651
|
+
if name
|
1652
|
+
begin
|
1653
|
+
# can fail for abstract types
|
1654
|
+
introspect = Vips::Introspect.get_yard name
|
1655
|
+
rescue Vips::Error
|
1656
|
+
nil
|
1657
|
+
end
|
1658
|
+
|
1659
|
+
generate_operation(introspect) if introspect
|
1484
1660
|
end
|
1485
1661
|
|
1486
|
-
|
1662
|
+
Vips.vips_type_map gtype, generate_class, nil
|
1487
1663
|
end
|
1488
1664
|
|
1489
|
-
|
1490
|
-
|
1491
|
-
|
1492
|
-
puts "module Vips"
|
1493
|
-
puts " class Image"
|
1494
|
-
puts ""
|
1665
|
+
puts "module Vips"
|
1666
|
+
puts " class Image"
|
1667
|
+
puts ""
|
1495
1668
|
|
1496
|
-
|
1669
|
+
generate_class.call(GObject.g_type_from_name("VipsOperation"), nil)
|
1497
1670
|
|
1498
|
-
|
1499
|
-
|
1671
|
+
puts " end"
|
1672
|
+
puts "end"
|
1673
|
+
end
|
1500
1674
|
end
|
1501
|
-
|
1502
1675
|
end
|