ruby-vips 2.0.15 → 2.1.2
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 +39 -0
- data/Gemfile +3 -1
- data/README.md +42 -41
- data/Rakefile +13 -21
- data/TODO +14 -14
- data/VERSION +1 -1
- data/example/annotate.rb +6 -6
- data/example/connection.rb +26 -0
- data/example/daltonize8.rb +6 -6
- data/example/draw_lines.rb +30 -0
- data/example/example1.rb +4 -4
- data/example/example2.rb +6 -6
- data/example/example3.rb +5 -5
- data/example/example4.rb +2 -2
- data/example/example5.rb +4 -4
- data/example/inheritance_with_refcount.rb +35 -36
- data/example/progress.rb +30 -0
- data/example/thumb.rb +6 -6
- data/example/trim8.rb +1 -1
- data/example/watermark.rb +2 -2
- data/example/wobble.rb +1 -1
- data/lib/ruby-vips.rb +1 -1
- data/lib/vips.rb +191 -79
- data/lib/vips/blend_mode.rb +29 -25
- data/lib/vips/connection.rb +46 -0
- data/lib/vips/gobject.rb +27 -12
- data/lib/vips/gvalue.rb +62 -50
- data/lib/vips/image.rb +475 -256
- data/lib/vips/interpolate.rb +3 -2
- data/lib/vips/methods.rb +788 -121
- data/lib/vips/mutableimage.rb +173 -0
- data/lib/vips/object.rb +171 -54
- data/lib/vips/operation.rb +272 -117
- data/lib/vips/region.rb +73 -0
- 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 -1
- data/ruby-vips.gemspec +26 -20
- metadata +39 -50
- data/.rubocop.yml +0 -22
- data/.rubocop_todo.yml +0 -515
- 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)
|
@@ -67,6 +78,11 @@ module Vips
|
|
67
78
|
class Image < Vips::Object
|
68
79
|
alias_method :parent_get_typeof, :get_typeof
|
69
80
|
|
81
|
+
# FFI sets a pointer's size to this magic value if the size of the memory
|
82
|
+
# chunk the pointer points to is unknown to FFI.
|
83
|
+
UNKNOWN_POINTER_SIZE = FFI::Pointer.new(1).size
|
84
|
+
private_constant :UNKNOWN_POINTER_SIZE
|
85
|
+
|
70
86
|
private
|
71
87
|
|
72
88
|
# the layout of the VipsImage struct
|
@@ -94,17 +110,17 @@ module Vips
|
|
94
110
|
# handy for overloads ... want to be able to apply a function to an
|
95
111
|
# array or to a scalar
|
96
112
|
def self.smap x, &block
|
97
|
-
x.is_a?(Array) ? x.map { |y| smap(y, &block) } : block.(x)
|
113
|
+
x.is_a?(Array) ? x.map { |y| smap(y, &block) } : block.call(x)
|
98
114
|
end
|
99
115
|
|
100
116
|
def self.complex? format
|
101
117
|
format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format
|
102
|
-
Vips
|
118
|
+
Vips.vips_band_format_iscomplex(format_number) != 0
|
103
119
|
end
|
104
120
|
|
105
121
|
def self.float? format
|
106
122
|
format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format
|
107
|
-
Vips
|
123
|
+
Vips.vips_band_format_isfloat(format_number) != 0
|
108
124
|
end
|
109
125
|
|
110
126
|
# run a complex operation on a complex image, or an image with an even
|
@@ -113,12 +129,12 @@ module Vips
|
|
113
129
|
def self.run_cmplx image, &block
|
114
130
|
original_format = image.format
|
115
131
|
|
116
|
-
unless Image
|
132
|
+
unless Image.complex? image.format
|
117
133
|
if image.bands % 2 != 0
|
118
|
-
raise Error, "not an even number of bands"
|
134
|
+
raise Vips::Error, "not an even number of bands"
|
119
135
|
end
|
120
136
|
|
121
|
-
unless Image
|
137
|
+
unless Image.float? image.format
|
122
138
|
image = image.cast :float
|
123
139
|
end
|
124
140
|
|
@@ -126,9 +142,9 @@ module Vips
|
|
126
142
|
image = image.copy format: new_format, bands: image.bands / 2
|
127
143
|
end
|
128
144
|
|
129
|
-
image = block.(image)
|
145
|
+
image = block.call(image)
|
130
146
|
|
131
|
-
unless Image
|
147
|
+
unless Image.complex? original_format
|
132
148
|
new_format = image.format == :dpcomplex ? :double : :float
|
133
149
|
image = image.copy format: new_format, bands: image.bands * 2
|
134
150
|
end
|
@@ -187,15 +203,19 @@ module Vips
|
|
187
203
|
# 36013-heads-up-ruby-implicitly-converts-a-hash-to-keyword-arguments
|
188
204
|
return false if name == :to_hash
|
189
205
|
|
206
|
+
super
|
207
|
+
end
|
208
|
+
|
209
|
+
def respond_to_missing? name, include_all = false
|
190
210
|
# respond to all vips operations by nickname
|
191
|
-
return true if Vips
|
211
|
+
return true if Vips.type_find("VipsOperation", name.to_s) != 0
|
192
212
|
|
193
213
|
super
|
194
214
|
end
|
195
215
|
|
196
|
-
def self.
|
216
|
+
def self.respond_to_missing? name, include_all = false
|
197
217
|
# respond to all vips operations by nickname
|
198
|
-
return true if Vips
|
218
|
+
return true if Vips.type_find("VipsOperation", name.to_s) != 0
|
199
219
|
|
200
220
|
super
|
201
221
|
end
|
@@ -219,13 +239,13 @@ module Vips
|
|
219
239
|
# load options, for example:
|
220
240
|
#
|
221
241
|
# ```
|
222
|
-
# image = Vips::new_from_file "fred.jpg[shrink=2]"
|
242
|
+
# image = Vips::Image.new_from_file "fred.jpg[shrink=2]"
|
223
243
|
# ```
|
224
244
|
#
|
225
245
|
# You can also supply options as a hash, for example:
|
226
246
|
#
|
227
247
|
# ```
|
228
|
-
# image = Vips::new_from_file "fred.jpg", shrink: 2
|
248
|
+
# image = Vips::Image.new_from_file "fred.jpg", shrink: 2
|
229
249
|
# ```
|
230
250
|
#
|
231
251
|
# The full set of options available depend upon the load operation that
|
@@ -253,18 +273,18 @@ module Vips
|
|
253
273
|
def self.new_from_file name, **opts
|
254
274
|
# very common, and Vips::vips_filename_get_filename will segv if we
|
255
275
|
# pass this
|
256
|
-
raise Vips::Error, "filename is nil" if name
|
276
|
+
raise Vips::Error, "filename is nil" if name.nil?
|
257
277
|
|
258
|
-
filename = Vips
|
259
|
-
option_string = Vips
|
260
|
-
loader = Vips
|
261
|
-
raise Vips::Error if loader
|
278
|
+
filename = Vips.p2str(Vips.vips_filename_get_filename(name))
|
279
|
+
option_string = Vips.p2str(Vips.vips_filename_get_options(name))
|
280
|
+
loader = Vips.vips_foreign_find_load filename
|
281
|
+
raise Vips::Error if loader.nil?
|
262
282
|
|
263
283
|
Operation.call loader, [filename], opts, option_string
|
264
284
|
end
|
265
285
|
|
266
|
-
# Create a new {Image} for an image encoded
|
267
|
-
# JPEG
|
286
|
+
# Create a new {Image} for an image encoded in a format such as
|
287
|
+
# JPEG in a binary string. Load options may be passed as
|
268
288
|
# strings or appended as a hash. For example:
|
269
289
|
#
|
270
290
|
# ```
|
@@ -295,17 +315,157 @@ module Vips
|
|
295
315
|
# @macro vips.loadopts
|
296
316
|
# @return [Image] the loaded image
|
297
317
|
def self.new_from_buffer data, option_string, **opts
|
298
|
-
loader = Vips
|
299
|
-
raise Vips::Error if loader
|
318
|
+
loader = Vips.vips_foreign_find_load_buffer data, data.bytesize
|
319
|
+
raise Vips::Error if loader.nil?
|
300
320
|
|
301
321
|
Vips::Operation.call loader, [data], opts, option_string
|
302
322
|
end
|
303
323
|
|
324
|
+
# Create a new {Image} from a C-style array held in memory. For example:
|
325
|
+
#
|
326
|
+
# ```
|
327
|
+
# image = Vips::Image.black(16, 16) + 128
|
328
|
+
# data = image.write_to_memory
|
329
|
+
#
|
330
|
+
# x = Vips::Image.new_from_memory data,
|
331
|
+
# image.width, image.height, image.bands, image.format
|
332
|
+
# ```
|
333
|
+
#
|
334
|
+
# Creating a new image from a memory pointer:
|
335
|
+
#
|
336
|
+
# ```
|
337
|
+
# ptr = FFI::MemoryPointer.new(:uchar, 10*10)
|
338
|
+
# # => #<FFI::MemoryPointer address=0x00007fc236db31d0 size=100>
|
339
|
+
# x = Vips::Image.new_from_memory(ptr, 10, 10, 1, :uchar)
|
340
|
+
# ```
|
341
|
+
#
|
342
|
+
# Creating a new image from an address only pointer:
|
343
|
+
#
|
344
|
+
# ```
|
345
|
+
# ptr = call_to_external_c_library(w: 10, h: 10)
|
346
|
+
# # => #<FFI::Pointer address=0x00007f9780813a00>
|
347
|
+
# ptr_slice = ptr.slice(0, 10*10)
|
348
|
+
# # => #<FFI::Pointer address=0x00007f9780813a00 size=100>
|
349
|
+
# x = Vips::Image.new_from_memory(ptr_slice, 10, 10, 1, :uchar)
|
350
|
+
# ```
|
351
|
+
#
|
352
|
+
# {new_from_memory} keeps a reference to the array of pixels you pass in
|
353
|
+
# to try to prevent that memory from being freed by the Ruby GC while it
|
354
|
+
# is being used.
|
355
|
+
#
|
356
|
+
# See {new_from_memory_copy} for a version of this method which does not
|
357
|
+
# keep a reference.
|
358
|
+
#
|
359
|
+
# @param data [String, FFI::Pointer] the data to load from
|
360
|
+
# @param width [Integer] width in pixels
|
361
|
+
# @param height [Integer] height in pixels
|
362
|
+
# @param bands [Integer] number of bands
|
363
|
+
# @param format [Symbol] band format
|
364
|
+
# @return [Image] the loaded image
|
365
|
+
def self.new_from_memory data, width, height, bands, format
|
366
|
+
# prevent data from being freed with JRuby FFI
|
367
|
+
if defined?(JRUBY_VERSION) && !data.is_a?(FFI::Pointer)
|
368
|
+
data = ::FFI::MemoryPointer.new(:char, data.bytesize).write_bytes data
|
369
|
+
end
|
370
|
+
|
371
|
+
if data.is_a?(FFI::Pointer)
|
372
|
+
# A pointer needs to know about the size of the memory it points to.
|
373
|
+
# If you have an address-only pointer, use the .slice method to wrap
|
374
|
+
# the pointer in a size aware pointer.
|
375
|
+
if data.size == UNKNOWN_POINTER_SIZE
|
376
|
+
raise Vips::Error, "size of memory is unknown"
|
377
|
+
end
|
378
|
+
size = data.size
|
379
|
+
else
|
380
|
+
size = data.bytesize
|
381
|
+
end
|
382
|
+
|
383
|
+
format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format
|
384
|
+
vi = Vips.vips_image_new_from_memory data, size,
|
385
|
+
width, height, bands, format_number
|
386
|
+
raise Vips::Error if vi.null?
|
387
|
+
image = new(vi)
|
388
|
+
|
389
|
+
# keep a secret ref to the underlying object .. this reference will be
|
390
|
+
# inherited by things that in turn depend on us, so the memory we are
|
391
|
+
# using will not be freed
|
392
|
+
image.references << data
|
393
|
+
|
394
|
+
image
|
395
|
+
end
|
396
|
+
|
397
|
+
# Create a new {Image} from memory and copies the memory area. See
|
398
|
+
# {new_from_memory} for a version of this method which does not copy the
|
399
|
+
# memory area.
|
400
|
+
#
|
401
|
+
# @param data [String, FFI::Pointer] the data to load from
|
402
|
+
# @param width [Integer] width in pixels
|
403
|
+
# @param height [Integer] height in pixels
|
404
|
+
# @param bands [Integer] number of bands
|
405
|
+
# @param format [Symbol] band format
|
406
|
+
# @return [Image] the loaded image
|
407
|
+
def self.new_from_memory_copy data, width, height, bands, format
|
408
|
+
format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format
|
409
|
+
|
410
|
+
if data.is_a?(FFI::Pointer)
|
411
|
+
if data.size == UNKNOWN_POINTER_SIZE
|
412
|
+
raise Vips::Error, "size of memory is unknown"
|
413
|
+
end
|
414
|
+
size = data.size
|
415
|
+
else
|
416
|
+
size = data.bytesize
|
417
|
+
end
|
418
|
+
|
419
|
+
vi = Vips.vips_image_new_from_memory_copy data, size,
|
420
|
+
width, height, bands, format_number
|
421
|
+
raise Vips::Error if vi.null?
|
422
|
+
new(vi)
|
423
|
+
end
|
424
|
+
|
425
|
+
# Create a new {Image} from a source. Load options may be passed as
|
426
|
+
# strings or appended as a hash. For example:
|
427
|
+
#
|
428
|
+
# ```
|
429
|
+
# source = Vips::Source.new_from_file("k2.jpg")
|
430
|
+
# image = Vips::Image.new_from_source source, "shrink=2"
|
431
|
+
# ```
|
432
|
+
#
|
433
|
+
# or alternatively:
|
434
|
+
#
|
435
|
+
# ```
|
436
|
+
# image = Vips::Image.new_from_source source, "", shrink: 2
|
437
|
+
# ```
|
438
|
+
#
|
439
|
+
# The options available depend on the file format. Try something like:
|
440
|
+
#
|
441
|
+
# ```
|
442
|
+
# $ vips jpegload_source
|
443
|
+
# ```
|
444
|
+
#
|
445
|
+
# at the command-line to see the available options. Not all loaders
|
446
|
+
# support load from source, but at least JPEG, PNG and
|
447
|
+
# TIFF images will work.
|
448
|
+
#
|
449
|
+
# Loading is fast: only enough data is read to be able to fill
|
450
|
+
# out the header. Pixels will only be read and decompressed when they are
|
451
|
+
# needed.
|
452
|
+
#
|
453
|
+
# @param source [Vips::Source] the source to load from
|
454
|
+
# @param option_string [String] load options as a string
|
455
|
+
# @macro vips.loadopts
|
456
|
+
# @return [Image] the loaded image
|
457
|
+
def self.new_from_source source, option_string, **opts
|
458
|
+
loader = Vips.vips_foreign_find_load_source source
|
459
|
+
raise Vips::Error if loader.nil?
|
460
|
+
|
461
|
+
Vips::Operation.call loader, [source], opts, option_string
|
462
|
+
end
|
463
|
+
|
304
464
|
def self.matrix_from_array width, height, array
|
305
465
|
ptr = FFI::MemoryPointer.new :double, array.length
|
306
466
|
ptr.write_array_of_double array
|
307
|
-
image = Vips
|
308
|
-
|
467
|
+
image = Vips.vips_image_new_matrix_from_array width, height,
|
468
|
+
ptr, array.length
|
309
469
|
Vips::Image.new image
|
310
470
|
end
|
311
471
|
|
@@ -317,13 +477,13 @@ module Vips
|
|
317
477
|
# For example:
|
318
478
|
#
|
319
479
|
# ```
|
320
|
-
# image = Vips::new_from_array [1, 2, 3]
|
480
|
+
# image = Vips::Image.new_from_array [1, 2, 3]
|
321
481
|
# ```
|
322
482
|
#
|
323
483
|
# or
|
324
484
|
#
|
325
485
|
# ```
|
326
|
-
# image = Vips::new_from_array [
|
486
|
+
# image = Vips::Image.new_from_array [
|
327
487
|
# [-1, -1, -1],
|
328
488
|
# [-1, 16, -1],
|
329
489
|
# [-1, -1, -1]], 8
|
@@ -358,18 +518,22 @@ module Vips
|
|
358
518
|
width = array.length
|
359
519
|
end
|
360
520
|
|
521
|
+
unless array.length == width * height
|
522
|
+
raise Vips::Error, "Bad array dimensions."
|
523
|
+
end
|
524
|
+
|
361
525
|
unless array.all? { |x| x.is_a? Numeric }
|
362
526
|
raise Vips::Error, "Not all array elements are Numeric."
|
363
527
|
end
|
364
528
|
|
365
529
|
image = Vips::Image.matrix_from_array width, height, array
|
366
|
-
raise Vips::Error if image
|
367
|
-
|
368
|
-
# be careful to set them as double
|
369
|
-
image.set_type GObject::GDOUBLE_TYPE, 'scale', scale.to_f
|
370
|
-
image.set_type GObject::GDOUBLE_TYPE, 'offset', offset.to_f
|
530
|
+
raise Vips::Error if image.nil?
|
371
531
|
|
372
|
-
|
532
|
+
image.mutate do |mutable|
|
533
|
+
# be careful to set them as double
|
534
|
+
mutable.set_type! GObject::GDOUBLE_TYPE, "scale", scale.to_f
|
535
|
+
mutable.set_type! GObject::GDOUBLE_TYPE, "offset", offset.to_f
|
536
|
+
end
|
373
537
|
end
|
374
538
|
|
375
539
|
# A new image is created with the same width, height, format,
|
@@ -385,7 +549,7 @@ module Vips
|
|
385
549
|
pixel = (Vips::Image.black(1, 1) + value).cast(format)
|
386
550
|
image = pixel.embed 0, 0, width, height, extend: :copy
|
387
551
|
image.copy interpretation: interpretation, xres: xres, yres: yres,
|
388
|
-
|
552
|
+
xoffset: xoffset, yoffset: yoffset
|
389
553
|
end
|
390
554
|
|
391
555
|
# Write this image to a file. Save options may be encoded in the
|
@@ -418,12 +582,12 @@ module Vips
|
|
418
582
|
#
|
419
583
|
# @param name [String] filename to write to
|
420
584
|
def write_to_file name, **opts
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
585
|
+
raise Vips::Error, "filename is nil" if name.nil?
|
586
|
+
|
587
|
+
filename = Vips.p2str(Vips.vips_filename_get_filename(name))
|
588
|
+
option_string = Vips.p2str(Vips.vips_filename_get_options(name))
|
589
|
+
saver = Vips.vips_foreign_find_save filename
|
590
|
+
raise Vips::Error if saver.nil?
|
427
591
|
|
428
592
|
Vips::Operation.call saver, [self, filename], opts, option_string
|
429
593
|
|
@@ -456,19 +620,55 @@ module Vips
|
|
456
620
|
# @macro vips.saveopts
|
457
621
|
# @return [String] the image saved in the specified format
|
458
622
|
def write_to_buffer format_string, **opts
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
end
|
623
|
+
raise Vips::Error, "filename is nil" if format_string.nil?
|
624
|
+
filename = Vips.p2str(Vips.vips_filename_get_filename(format_string))
|
625
|
+
option_string = Vips.p2str(Vips.vips_filename_get_options(format_string))
|
626
|
+
saver = Vips.vips_foreign_find_save_buffer filename
|
627
|
+
raise Vips::Error if saver.nil?
|
465
628
|
|
466
629
|
buffer = Vips::Operation.call saver, [self], opts, option_string
|
467
|
-
raise Vips::Error if buffer
|
630
|
+
raise Vips::Error if buffer.nil?
|
468
631
|
|
469
632
|
write_gc
|
470
633
|
|
471
|
-
|
634
|
+
buffer
|
635
|
+
end
|
636
|
+
|
637
|
+
# Write this image to a target. Save options may be encoded in
|
638
|
+
# the format_string or given as a hash. For example:
|
639
|
+
#
|
640
|
+
# ```ruby
|
641
|
+
# target = Vips::Target.new_to_file "k2.jpg"
|
642
|
+
# image.write_to_target target, ".jpg[Q=90]"
|
643
|
+
# ```
|
644
|
+
#
|
645
|
+
# or equivalently:
|
646
|
+
#
|
647
|
+
# ```ruby
|
648
|
+
# image.write_to_target target, ".jpg", Q: 90
|
649
|
+
# ```
|
650
|
+
#
|
651
|
+
# The full set of save options depend on the selected saver. Try
|
652
|
+
# something like:
|
653
|
+
#
|
654
|
+
# ```
|
655
|
+
# $ vips jpegsave_target
|
656
|
+
# ```
|
657
|
+
#
|
658
|
+
# to see all the available options for JPEG save.
|
659
|
+
#
|
660
|
+
# @param target [Vips::Target] the target to write to
|
661
|
+
# @param format_string [String] save format plus string options
|
662
|
+
# @macro vips.saveopts
|
663
|
+
def write_to_target target, format_string, **opts
|
664
|
+
raise Vips::Error, "filename is nil" if format_string.nil?
|
665
|
+
filename = Vips.p2str(Vips.vips_filename_get_filename(format_string))
|
666
|
+
option_string = Vips.p2str(Vips.vips_filename_get_options(format_string))
|
667
|
+
saver = Vips.vips_foreign_find_save_target filename
|
668
|
+
raise Vips::Error if saver.nil?
|
669
|
+
|
670
|
+
Vips::Operation.call saver, [self, target], opts, option_string
|
671
|
+
write_gc
|
472
672
|
end
|
473
673
|
|
474
674
|
# Write this image to a large memory buffer.
|
@@ -476,8 +676,8 @@ module Vips
|
|
476
676
|
# @return [String] the pixels as a huge binary string
|
477
677
|
def write_to_memory
|
478
678
|
len = Vips::SizeStruct.new
|
479
|
-
ptr = Vips
|
480
|
-
raise Vips::Error if ptr
|
679
|
+
ptr = Vips.vips_image_write_to_memory self, len
|
680
|
+
raise Vips::Error if ptr.nil?
|
481
681
|
|
482
682
|
# wrap up as an autopointer
|
483
683
|
ptr = FFI::AutoPointer.new(ptr, GLib::G_FREE)
|
@@ -485,6 +685,28 @@ module Vips
|
|
485
685
|
ptr.get_bytes 0, len[:value]
|
486
686
|
end
|
487
687
|
|
688
|
+
# Turn progress signalling on and off.
|
689
|
+
#
|
690
|
+
# If this is on, the most-downstream image from this image will issue
|
691
|
+
# progress signals.
|
692
|
+
#
|
693
|
+
# @see Object#signal_connect
|
694
|
+
# @param state [Boolean] progress signalling state
|
695
|
+
def set_progress state
|
696
|
+
Vips.vips_image_set_progress self, state
|
697
|
+
end
|
698
|
+
|
699
|
+
# Kill computation of this time.
|
700
|
+
#
|
701
|
+
# Set true to stop computation of this image. You can call this from a
|
702
|
+
# progress handler, for example.
|
703
|
+
#
|
704
|
+
# @see Object#signal_connect
|
705
|
+
# @param kill [Boolean] stop computation
|
706
|
+
def set_kill kill
|
707
|
+
Vips.vips_image_set_kill self, kill
|
708
|
+
end
|
709
|
+
|
488
710
|
# Get the `GType` of a metadata field. The result is 0 if no such field
|
489
711
|
# exists.
|
490
712
|
#
|
@@ -494,12 +716,12 @@ module Vips
|
|
494
716
|
def get_typeof name
|
495
717
|
# on libvips before 8.5, property types must be searched first,
|
496
718
|
# since vips_image_get_typeof returned built-in enums as int
|
497
|
-
unless Vips
|
719
|
+
unless Vips.at_least_libvips?(8, 5)
|
498
720
|
gtype = parent_get_typeof name
|
499
721
|
return gtype if gtype != 0
|
500
722
|
end
|
501
723
|
|
502
|
-
Vips
|
724
|
+
Vips.vips_image_get_typeof self, name
|
503
725
|
end
|
504
726
|
|
505
727
|
# Get a metadata item from an image. Ruby types are constructed
|
@@ -518,15 +740,16 @@ module Vips
|
|
518
740
|
def get name
|
519
741
|
# with old libvips, we must fetch properties (as opposed to
|
520
742
|
# metadata) via VipsObject
|
521
|
-
unless Vips
|
743
|
+
unless Vips.at_least_libvips?(8, 5)
|
522
744
|
return super if parent_get_typeof(name) != 0
|
523
745
|
end
|
524
746
|
|
525
747
|
gvalue = GObject::GValue.alloc
|
526
|
-
|
527
|
-
|
748
|
+
raise Vips::Error if Vips.vips_image_get(self, name, gvalue) != 0
|
749
|
+
result = gvalue.get
|
750
|
+
gvalue.unset
|
528
751
|
|
529
|
-
|
752
|
+
result
|
530
753
|
end
|
531
754
|
|
532
755
|
# Get the names of all fields on an image. Use this to loop over all
|
@@ -537,66 +760,64 @@ module Vips
|
|
537
760
|
# vips_image_get_fields() was added in libvips 8.5
|
538
761
|
return [] unless Vips.respond_to? :vips_image_get_fields
|
539
762
|
|
540
|
-
array = Vips
|
763
|
+
array = Vips.vips_image_get_fields self
|
541
764
|
|
542
765
|
names = []
|
543
766
|
p = array
|
544
767
|
until (q = p.read_pointer).null?
|
545
768
|
names << q.read_string
|
546
|
-
GLib
|
769
|
+
GLib.g_free q
|
547
770
|
p += FFI::Type::POINTER.size
|
548
771
|
end
|
549
|
-
GLib
|
772
|
+
GLib.g_free array
|
550
773
|
|
551
774
|
names
|
552
775
|
end
|
553
776
|
|
554
|
-
#
|
555
|
-
#
|
777
|
+
# Mutate an image with a block. Inside the block, you can call methods
|
778
|
+
# which modify the image, such as setting or removing metadata, or
|
779
|
+
# modifying pixels.
|
556
780
|
#
|
557
|
-
# For example
|
781
|
+
# For example:
|
558
782
|
#
|
559
|
-
# ```
|
560
|
-
#
|
783
|
+
# ```ruby
|
784
|
+
# image = image.mutate do |x|
|
785
|
+
# (0 ... 1).step(0.01) do |i|
|
786
|
+
# x.draw_line! 255, x.width * i, 0, 0, x.height * (1 - i)
|
787
|
+
# end
|
788
|
+
# end
|
561
789
|
# ```
|
562
790
|
#
|
563
|
-
#
|
791
|
+
# See {MutableImage}.
|
792
|
+
def mutate
|
793
|
+
mutable = Vips::MutableImage.new self
|
794
|
+
yield mutable
|
795
|
+
mutable.image
|
796
|
+
end
|
797
|
+
|
798
|
+
# This method is deprecated.
|
564
799
|
#
|
565
|
-
#
|
566
|
-
# @param gtype [Integer] GType of item
|
567
|
-
# @param name [String] Metadata field to set
|
568
|
-
# @param value [Object] Value to set
|
800
|
+
# Please use {MutableImage#set_type!} instead.
|
569
801
|
def set_type gtype, name, value
|
570
802
|
gvalue = GObject::GValue.alloc
|
571
803
|
gvalue.init gtype
|
572
804
|
gvalue.set value
|
573
|
-
Vips
|
805
|
+
Vips.vips_image_set self, name, gvalue
|
806
|
+
gvalue.unset
|
574
807
|
end
|
575
808
|
|
576
|
-
#
|
577
|
-
# already exist. Ruby types are automatically transformed into the
|
578
|
-
# matching `GValue`, if possible.
|
579
|
-
#
|
580
|
-
# For example, you can use this to set an image's ICC profile:
|
581
|
-
#
|
582
|
-
# ```
|
583
|
-
# x = y.set "icc-profile-data", profile
|
584
|
-
# ```
|
585
|
-
#
|
586
|
-
# where `profile` is an ICC profile held as a binary string object.
|
809
|
+
# This method is deprecated.
|
587
810
|
#
|
588
|
-
#
|
589
|
-
# @param name [String] Metadata field to set
|
590
|
-
# @param value [Object] Value to set
|
811
|
+
# Please use {MutableImage#set!} instead.
|
591
812
|
def set name, value
|
592
813
|
set_type get_typeof(name), name, value
|
593
814
|
end
|
594
815
|
|
595
|
-
#
|
816
|
+
# This method is deprecated.
|
596
817
|
#
|
597
|
-
#
|
818
|
+
# Please use {MutableImage#remove!} instead.
|
598
819
|
def remove name
|
599
|
-
Vips
|
820
|
+
Vips.vips_image_remove self, name
|
600
821
|
end
|
601
822
|
|
602
823
|
# compatibility: old name for get
|
@@ -604,7 +825,9 @@ module Vips
|
|
604
825
|
get name
|
605
826
|
end
|
606
827
|
|
607
|
-
#
|
828
|
+
# This method is deprecated.
|
829
|
+
#
|
830
|
+
# Please use {MutableImage#set!} instead.
|
608
831
|
def set_value name, value
|
609
832
|
set name, value
|
610
833
|
end
|
@@ -613,21 +836,21 @@ module Vips
|
|
613
836
|
#
|
614
837
|
# @return [Integer] image width, in pixels
|
615
838
|
def width
|
616
|
-
|
839
|
+
Vips.vips_image_get_width self
|
617
840
|
end
|
618
841
|
|
619
842
|
# Get image height, in pixels.
|
620
843
|
#
|
621
844
|
# @return [Integer] image height, in pixels
|
622
845
|
def height
|
623
|
-
|
846
|
+
Vips.vips_image_get_height self
|
624
847
|
end
|
625
848
|
|
626
849
|
# Get number of image bands.
|
627
850
|
#
|
628
851
|
# @return [Integer] number of image bands
|
629
852
|
def bands
|
630
|
-
|
853
|
+
Vips.vips_image_get_bands self
|
631
854
|
end
|
632
855
|
|
633
856
|
# Get image format.
|
@@ -711,23 +934,23 @@ module Vips
|
|
711
934
|
[width, height]
|
712
935
|
end
|
713
936
|
|
714
|
-
if Vips
|
937
|
+
if Vips.at_least_libvips?(8, 5)
|
715
938
|
# Detect if image has an alpha channel
|
716
939
|
#
|
717
940
|
# @return [Boolean] true if image has an alpha channel.
|
718
941
|
def has_alpha?
|
719
|
-
|
942
|
+
Vips.vips_image_hasalpha(self) != 0
|
720
943
|
end
|
721
944
|
end
|
722
945
|
|
723
946
|
# vips_addalpha was added in libvips 8.6
|
724
|
-
if Vips
|
947
|
+
if Vips.at_least_libvips?(8, 6)
|
725
948
|
# Append an alpha channel to an image.
|
726
949
|
#
|
727
950
|
# @return [Image] new image
|
728
951
|
def add_alpha
|
729
952
|
ptr = GenericPtr.new
|
730
|
-
result = Vips
|
953
|
+
result = Vips.vips_addalpha self, ptr
|
731
954
|
raise Vips::Error if result != 0
|
732
955
|
|
733
956
|
Vips::Image.new ptr[:value]
|
@@ -742,7 +965,7 @@ module Vips
|
|
742
965
|
#
|
743
966
|
# @return [Image] new memory image
|
744
967
|
def copy_memory
|
745
|
-
new_image = Vips
|
968
|
+
new_image = Vips.vips_image_copy_memory self
|
746
969
|
Vips::Image.new new_image
|
747
970
|
end
|
748
971
|
|
@@ -752,7 +975,7 @@ module Vips
|
|
752
975
|
#
|
753
976
|
# @return [Image] modified image
|
754
977
|
def draw_point ink, left, top, **opts
|
755
|
-
draw_rect ink, left, top, 1, 1, opts
|
978
|
+
draw_rect ink, left, top, 1, 1, **opts
|
756
979
|
end
|
757
980
|
|
758
981
|
# Add an image, constant or array.
|
@@ -770,7 +993,7 @@ module Vips
|
|
770
993
|
# @return [Image] result of subtraction
|
771
994
|
def - other
|
772
995
|
other.is_a?(Vips::Image) ?
|
773
|
-
subtract(other) : linear(1, Image
|
996
|
+
subtract(other) : linear(1, Image.smap(other) { |x| x * -1 })
|
774
997
|
end
|
775
998
|
|
776
999
|
# Multiply an image, constant or array.
|
@@ -788,7 +1011,7 @@ module Vips
|
|
788
1011
|
# @return [Image] result of division
|
789
1012
|
def / other
|
790
1013
|
other.is_a?(Vips::Image) ?
|
791
|
-
divide(other) : linear(Image
|
1014
|
+
divide(other) : linear(Image.smap(other) { |x| 1.0 / x }, 0)
|
792
1015
|
end
|
793
1016
|
|
794
1017
|
# Remainder after integer division with an image, constant or array.
|
@@ -914,7 +1137,7 @@ module Vips
|
|
914
1137
|
# @return [Image] result of equality
|
915
1138
|
def == other
|
916
1139
|
# for equality, we must allow tests against nil
|
917
|
-
if other
|
1140
|
+
if other.nil?
|
918
1141
|
false
|
919
1142
|
else
|
920
1143
|
call_enum "relational", other, :equal
|
@@ -927,7 +1150,7 @@ module Vips
|
|
927
1150
|
# @return [Image] result of inequality
|
928
1151
|
def != other
|
929
1152
|
# for equality, we must allow tests against nil
|
930
|
-
if other
|
1153
|
+
if other.nil?
|
931
1154
|
true
|
932
1155
|
else
|
933
1156
|
call_enum "relational", other, :noteq
|
@@ -949,38 +1172,40 @@ module Vips
|
|
949
1172
|
end
|
950
1173
|
end
|
951
1174
|
|
952
|
-
# Convert to an
|
1175
|
+
# Convert to an Enumerator. Similar to `#to_a` but lazier.
|
953
1176
|
#
|
954
|
-
# @return [
|
955
|
-
def
|
956
|
-
# we render the image to a big string, then unpack
|
957
|
-
# as a Ruby array of the correct type
|
958
|
-
memory = write_to_memory
|
959
|
-
|
1177
|
+
# @return [Enumerator] Enumerator of Enumerators of Arrays of Numerics
|
1178
|
+
def to_enum
|
960
1179
|
# make the template for unpack
|
961
1180
|
template = {
|
962
|
-
char:
|
963
|
-
uchar:
|
964
|
-
short:
|
965
|
-
ushort:
|
966
|
-
int:
|
967
|
-
uint:
|
968
|
-
float:
|
969
|
-
double:
|
970
|
-
complex:
|
971
|
-
dpcomplex:
|
972
|
-
}[format] +
|
1181
|
+
char: "c",
|
1182
|
+
uchar: "C",
|
1183
|
+
short: "s_",
|
1184
|
+
ushort: "S_",
|
1185
|
+
int: "i_",
|
1186
|
+
uint: "I_",
|
1187
|
+
float: "f",
|
1188
|
+
double: "d",
|
1189
|
+
complex: "f",
|
1190
|
+
dpcomplex: "d"
|
1191
|
+
}[format] + "*"
|
973
1192
|
|
974
|
-
#
|
975
|
-
array
|
1193
|
+
# we render the image to a big string, then unpack into
|
1194
|
+
# one-dimensional array as a Ruby array of the correct type
|
1195
|
+
array = write_to_memory.unpack template
|
976
1196
|
|
977
|
-
# gather
|
978
|
-
pixel_array = array.each_slice
|
1197
|
+
# gather bands of a pixel together
|
1198
|
+
pixel_array = array.each_slice bands
|
979
1199
|
|
980
|
-
#
|
981
|
-
|
1200
|
+
# gather pixels of a row together
|
1201
|
+
pixel_array.each_slice width
|
1202
|
+
end
|
982
1203
|
|
983
|
-
|
1204
|
+
# Convert to an Array. This will be slow for large images.
|
1205
|
+
#
|
1206
|
+
# @return [Array] Array of Arrays of Arrays of Numerics
|
1207
|
+
def to_a
|
1208
|
+
to_enum.to_a
|
984
1209
|
end
|
985
1210
|
|
986
1211
|
# Return the largest integral value not greater than the argument.
|
@@ -1056,7 +1281,10 @@ module Vips
|
|
1056
1281
|
# @param overlay [Image, Array<Image>] images to composite
|
1057
1282
|
# @param mode [BlendMode, Array<BlendMode>] blend modes to use
|
1058
1283
|
# @param opts [Hash] Set of options
|
1059
|
-
# @option opts [
|
1284
|
+
# @option opts [Array<Integer>] :x x positions of overlay
|
1285
|
+
# @option opts [Array<Integer>] :y y positions of overlay
|
1286
|
+
# @option opts [Vips::Interpretation] :compositing_space Composite images
|
1287
|
+
# in this colour space
|
1060
1288
|
# @option opts [Boolean] :premultiplied Images have premultiplied alpha
|
1061
1289
|
# @return [Image] blended image
|
1062
1290
|
def composite overlay, mode, **opts
|
@@ -1071,7 +1299,7 @@ module Vips
|
|
1071
1299
|
GObject::GValue.from_nick Vips::BLEND_MODE_TYPE, x
|
1072
1300
|
end
|
1073
1301
|
|
1074
|
-
Vips::Image.composite([self] + overlay, mode, opts)
|
1302
|
+
Vips::Image.composite([self] + overlay, mode, **opts)
|
1075
1303
|
end
|
1076
1304
|
|
1077
1305
|
# Return the coordinates of the image maximum.
|
@@ -1080,9 +1308,9 @@ module Vips
|
|
1080
1308
|
# coordinate of maximum
|
1081
1309
|
def maxpos
|
1082
1310
|
v, opts = max x: true, y: true
|
1083
|
-
x = opts[
|
1084
|
-
y = opts[
|
1085
|
-
|
1311
|
+
x = opts["x"]
|
1312
|
+
y = opts["y"]
|
1313
|
+
[v, x, y]
|
1086
1314
|
end
|
1087
1315
|
|
1088
1316
|
# Return the coordinates of the image minimum.
|
@@ -1091,9 +1319,9 @@ module Vips
|
|
1091
1319
|
# coordinate of minimum
|
1092
1320
|
def minpos
|
1093
1321
|
v, opts = min x: true, y: true
|
1094
|
-
x = opts[
|
1095
|
-
y = opts[
|
1096
|
-
|
1322
|
+
x = opts["x"]
|
1323
|
+
y = opts["y"]
|
1324
|
+
[v, x, y]
|
1097
1325
|
end
|
1098
1326
|
|
1099
1327
|
# a median filter
|
@@ -1101,7 +1329,7 @@ module Vips
|
|
1101
1329
|
# @param size [Integer] size of filter window
|
1102
1330
|
# @return [Image] result of median filter
|
1103
1331
|
def median size = 3
|
1104
|
-
rank size, size,
|
1332
|
+
rank size, size, size**2 / 2
|
1105
1333
|
end
|
1106
1334
|
|
1107
1335
|
# Return the real part of a complex image.
|
@@ -1128,7 +1356,7 @@ module Vips
|
|
1128
1356
|
# @see xyz
|
1129
1357
|
# @return [Image] image converted to polar coordinates
|
1130
1358
|
def polar
|
1131
|
-
Image
|
1359
|
+
Image.run_cmplx(self) { |x| x.complex :polar }
|
1132
1360
|
end
|
1133
1361
|
|
1134
1362
|
# Return an image with polar pixels converted to rectangular.
|
@@ -1141,7 +1369,7 @@ module Vips
|
|
1141
1369
|
# @see xyz
|
1142
1370
|
# @return [Image] image converted to rectangular coordinates
|
1143
1371
|
def rect
|
1144
|
-
Image
|
1372
|
+
Image.run_cmplx(self) { |x| x.complex :rect }
|
1145
1373
|
end
|
1146
1374
|
|
1147
1375
|
# Return the complex conjugate of an image.
|
@@ -1153,7 +1381,7 @@ module Vips
|
|
1153
1381
|
#
|
1154
1382
|
# @return [Image] complex conjugate
|
1155
1383
|
def conj
|
1156
|
-
Image
|
1384
|
+
Image.run_cmplx(self) { |x| x.complex :conj }
|
1157
1385
|
end
|
1158
1386
|
|
1159
1387
|
# Calculate the cross phase of two images.
|
@@ -1321,29 +1549,26 @@ module Vips
|
|
1321
1549
|
# @param opts [Hash] Set of options
|
1322
1550
|
# @return [Vips::Image] Output image
|
1323
1551
|
def scaleimage **opts
|
1324
|
-
Vips::Image.scale self, opts
|
1552
|
+
Vips::Image.scale self, **opts
|
1325
1553
|
end
|
1326
1554
|
end
|
1327
1555
|
end
|
1328
1556
|
|
1329
1557
|
module Vips
|
1330
|
-
# This
|
1558
|
+
# This module generates yard comments for all the dynamically bound
|
1331
1559
|
# vips operations.
|
1332
1560
|
#
|
1333
1561
|
# Regenerate with something like:
|
1334
1562
|
#
|
1335
1563
|
# ```
|
1336
1564
|
# $ ruby > methods.rb
|
1337
|
-
# require
|
1565
|
+
# require "vips"; Vips::Yard.generate
|
1338
1566
|
# ^D
|
1339
1567
|
# ```
|
1340
1568
|
|
1341
|
-
|
1342
|
-
# these have hand-written methods, see above
|
1343
|
-
no_generate = ["scale", "bandjoin", "composite", "ifthenelse"]
|
1344
|
-
|
1569
|
+
module Yard
|
1345
1570
|
# map gobject's type names to Ruby
|
1346
|
-
|
1571
|
+
MAP_GO_TO_RUBY = {
|
1347
1572
|
"gboolean" => "Boolean",
|
1348
1573
|
"gint" => "Integer",
|
1349
1574
|
"gdouble" => "Float",
|
@@ -1351,109 +1576,91 @@ module Vips
|
|
1351
1576
|
"gchararray" => "String",
|
1352
1577
|
"VipsImage" => "Vips::Image",
|
1353
1578
|
"VipsInterpolate" => "Vips::Interpolate",
|
1579
|
+
"VipsConnection" => "Vips::Connection",
|
1580
|
+
"VipsSource" => "Vips::Source",
|
1581
|
+
"VipsTarget" => "Vips::Target",
|
1582
|
+
"VipsSourceCustom" => "Vips::SourceCustom",
|
1583
|
+
"VipsTargetCustom" => "Vips::TargetCustom",
|
1354
1584
|
"VipsArrayDouble" => "Array<Double>",
|
1355
1585
|
"VipsArrayInt" => "Array<Integer>",
|
1356
1586
|
"VipsArrayImage" => "Array<Image>",
|
1357
|
-
"VipsArrayString" => "Array<String>"
|
1587
|
+
"VipsArrayString" => "Array<String>"
|
1358
1588
|
}
|
1359
1589
|
|
1360
|
-
|
1361
|
-
|
1362
|
-
return if (op_flags & OPERATION_DEPRECATED) != 0
|
1363
|
-
return if no_generate.include? nickname
|
1364
|
-
|
1365
|
-
description = Vips::vips_object_get_description op
|
1366
|
-
|
1367
|
-
# find and classify all the arguments the operator can take
|
1368
|
-
required_input = []
|
1369
|
-
optional_input = []
|
1370
|
-
required_output = []
|
1371
|
-
optional_output = []
|
1372
|
-
member_x = nil
|
1373
|
-
op.argument_map do |pspec, argument_class, _argument_instance|
|
1374
|
-
arg_flags = argument_class[:flags]
|
1375
|
-
next if (arg_flags & ARGUMENT_CONSTRUCT) == 0
|
1376
|
-
next if (arg_flags & ARGUMENT_DEPRECATED) != 0
|
1377
|
-
|
1378
|
-
name = pspec[:name].tr("-", "_")
|
1379
|
-
# 'in' as a param name confuses yard
|
1380
|
-
name = "im" if name == "in"
|
1381
|
-
gtype = pspec[:value_type]
|
1382
|
-
fundamental = GObject::g_type_fundamental gtype
|
1383
|
-
type_name = GObject::g_type_name gtype
|
1384
|
-
if map_go_to_ruby.include? type_name
|
1385
|
-
type_name = map_go_to_ruby[type_name]
|
1386
|
-
end
|
1387
|
-
if fundamental == GObject::GFLAGS_TYPE ||
|
1388
|
-
fundamental == GObject::GENUM_TYPE
|
1389
|
-
type_name = "Vips::" + type_name[/Vips(.*)/, 1]
|
1390
|
-
end
|
1391
|
-
blurb = GObject::g_param_spec_get_blurb pspec
|
1392
|
-
value = {
|
1393
|
-
name: name,
|
1394
|
-
flags: arg_flags,
|
1395
|
-
gtype: gtype,
|
1396
|
-
type_name: type_name,
|
1397
|
-
blurb: blurb
|
1398
|
-
}
|
1399
|
-
|
1400
|
-
if (arg_flags & ARGUMENT_INPUT) != 0
|
1401
|
-
if (arg_flags & ARGUMENT_REQUIRED) != 0
|
1402
|
-
# note the first required input image, if any ... we
|
1403
|
-
# will be a method of this instance
|
1404
|
-
if !member_x && gtype == Vips::IMAGE_TYPE
|
1405
|
-
member_x = value
|
1406
|
-
else
|
1407
|
-
required_input << value
|
1408
|
-
end
|
1409
|
-
else
|
1410
|
-
optional_input << value
|
1411
|
-
end
|
1412
|
-
end
|
1590
|
+
# these have hand-written methods, see above
|
1591
|
+
NO_GENERATE = ["scale", "bandjoin", "composite", "ifthenelse"]
|
1413
1592
|
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1593
|
+
# these are aliased (appear under several names)
|
1594
|
+
ALIAS = ["crop"]
|
1595
|
+
|
1596
|
+
# turn a gtype into a ruby type name
|
1597
|
+
def self.gtype_to_ruby gtype
|
1598
|
+
fundamental = GObject.g_type_fundamental gtype
|
1599
|
+
type_name = GObject.g_type_name gtype
|
1600
|
+
|
1601
|
+
if MAP_GO_TO_RUBY.include? type_name
|
1602
|
+
type_name = MAP_GO_TO_RUBY[type_name]
|
1603
|
+
end
|
1604
|
+
|
1605
|
+
if fundamental == GObject::GFLAGS_TYPE ||
|
1606
|
+
fundamental == GObject::GENUM_TYPE
|
1607
|
+
type_name = "Vips::" + type_name[/Vips(.*)/, 1]
|
1424
1608
|
end
|
1425
1609
|
|
1610
|
+
type_name
|
1611
|
+
end
|
1612
|
+
|
1613
|
+
def self.generate_operation introspect
|
1614
|
+
return if (introspect.flags & OPERATION_DEPRECATED) != 0
|
1615
|
+
return if NO_GENERATE.include? introspect.name
|
1616
|
+
|
1617
|
+
method_args = introspect.method_args
|
1618
|
+
required_output = introspect.required_output
|
1619
|
+
optional_input = introspect.optional_input
|
1620
|
+
optional_output = introspect.optional_output
|
1621
|
+
|
1426
1622
|
print "# @!method "
|
1427
|
-
print "self." unless member_x
|
1428
|
-
print "#{
|
1429
|
-
print
|
1430
|
-
print ", " if
|
1623
|
+
print "self." unless introspect.member_x
|
1624
|
+
print "#{introspect.name}("
|
1625
|
+
print method_args.map { |x| x[:yard_name] }.join(", ")
|
1626
|
+
print ", " if method_args.length > 0
|
1431
1627
|
puts "**opts)"
|
1432
1628
|
|
1433
|
-
puts "# #{description.capitalize}."
|
1629
|
+
puts "# #{introspect.description.capitalize}."
|
1630
|
+
|
1631
|
+
method_args.each do |details|
|
1632
|
+
yard_name = details[:yard_name]
|
1633
|
+
gtype = details[:gtype]
|
1634
|
+
blurb = details[:blurb]
|
1434
1635
|
|
1435
|
-
|
1436
|
-
puts "# @param #{arg[:name]} [#{arg[:type_name]}] #{arg[:blurb]}"
|
1636
|
+
puts "# @param #{yard_name} [#{gtype_to_ruby(gtype)}] #{blurb}"
|
1437
1637
|
end
|
1438
1638
|
|
1439
1639
|
puts "# @param opts [Hash] Set of options"
|
1440
|
-
optional_input.each do |
|
1441
|
-
|
1442
|
-
|
1640
|
+
optional_input.each do |arg_name, details|
|
1641
|
+
yard_name = details[:yard_name]
|
1642
|
+
gtype = details[:gtype]
|
1643
|
+
blurb = details[:blurb]
|
1644
|
+
|
1645
|
+
puts "# @option opts [#{gtype_to_ruby(gtype)}] :#{yard_name} #{blurb}"
|
1443
1646
|
end
|
1444
|
-
optional_output.each do |
|
1445
|
-
|
1446
|
-
|
1647
|
+
optional_output.each do |arg_name, details|
|
1648
|
+
yard_name = details[:yard_name]
|
1649
|
+
gtype = details[:gtype]
|
1650
|
+
blurb = details[:blurb]
|
1651
|
+
|
1652
|
+
print "# @option opts [#{gtype_to_ruby(gtype)}] :#{yard_name}"
|
1653
|
+
puts " Output #{blurb}"
|
1447
1654
|
end
|
1448
1655
|
|
1449
1656
|
print "# @return ["
|
1450
1657
|
if required_output.length == 0
|
1451
1658
|
print "nil"
|
1452
1659
|
elsif required_output.length == 1
|
1453
|
-
print required_output.first[:
|
1660
|
+
print gtype_to_ruby(required_output.first[:gtype])
|
1454
1661
|
else
|
1455
1662
|
print "Array<"
|
1456
|
-
print required_output.map { |x| x[:
|
1663
|
+
print required_output.map { |x| gtype_to_ruby(x[:gtype]) }.join(", ")
|
1457
1664
|
print ">"
|
1458
1665
|
end
|
1459
1666
|
if optional_output.length > 0
|
@@ -1470,30 +1677,42 @@ module Vips
|
|
1470
1677
|
puts ""
|
1471
1678
|
end
|
1472
1679
|
|
1473
|
-
|
1474
|
-
|
1680
|
+
def self.generate
|
1681
|
+
alias_gtypes = {}
|
1682
|
+
ALIAS.each do |name|
|
1683
|
+
gtype = Vips.type_find "VipsOperation", name
|
1684
|
+
alias_gtypes[gtype] = name
|
1685
|
+
end
|
1475
1686
|
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
nil
|
1687
|
+
generate_class = lambda do |gtype, _|
|
1688
|
+
name = if alias_gtypes.key? gtype
|
1689
|
+
alias_gtypes[gtype]
|
1690
|
+
else
|
1691
|
+
Vips.nickname_find gtype
|
1482
1692
|
end
|
1483
1693
|
|
1484
|
-
|
1485
|
-
|
1694
|
+
if name
|
1695
|
+
begin
|
1696
|
+
# can fail for abstract types
|
1697
|
+
introspect = Vips::Introspect.get_yard name
|
1698
|
+
rescue Vips::Error
|
1699
|
+
nil
|
1700
|
+
end
|
1486
1701
|
|
1487
|
-
|
1488
|
-
|
1702
|
+
generate_operation(introspect) if introspect
|
1703
|
+
end
|
1489
1704
|
|
1490
|
-
|
1491
|
-
|
1492
|
-
|
1705
|
+
Vips.vips_type_map gtype, generate_class, nil
|
1706
|
+
end
|
1707
|
+
|
1708
|
+
puts "module Vips"
|
1709
|
+
puts " class Image"
|
1710
|
+
puts ""
|
1493
1711
|
|
1494
|
-
|
1712
|
+
generate_class.call(GObject.g_type_from_name("VipsOperation"), nil)
|
1495
1713
|
|
1496
|
-
|
1497
|
-
|
1714
|
+
puts " end"
|
1715
|
+
puts "end"
|
1716
|
+
end
|
1498
1717
|
end
|
1499
1718
|
end
|