ruby-vips 2.0.17 → 2.1.3
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 +26 -0
- data/Gemfile +3 -1
- data/README.md +12 -11
- data/Rakefile +13 -21
- data/TODO +4 -8
- data/VERSION +1 -1
- data/example/annotate.rb +6 -6
- data/example/connection.rb +18 -9
- 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 +46 -39
- data/example/progress.rb +3 -3
- 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 +127 -76
- data/lib/vips/blend_mode.rb +29 -25
- data/lib/vips/connection.rb +4 -4
- data/lib/vips/gobject.rb +18 -11
- data/lib/vips/gvalue.rb +54 -54
- data/lib/vips/image.rb +289 -165
- data/lib/vips/interpolate.rb +3 -2
- data/lib/vips/methods.rb +484 -107
- data/lib/vips/mutableimage.rb +173 -0
- data/lib/vips/object.rb +86 -93
- data/lib/vips/operation.rb +161 -82
- data/lib/vips/region.rb +6 -6
- data/lib/vips/source.rb +11 -12
- data/lib/vips/sourcecustom.rb +7 -8
- data/lib/vips/target.rb +12 -13
- data/lib/vips/targetcustom.rb +9 -10
- data/lib/vips/version.rb +1 -1
- data/ruby-vips.gemspec +26 -22
- metadata +29 -49
- data/.rubocop.yml +0 -22
- data/.rubocop_todo.yml +0 -473
- data/.travis.yml +0 -57
- data/install-vips.sh +0 -26
data/lib/vips/image.rb
CHANGED
@@ -4,13 +4,13 @@
|
|
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
|
|
@@ -25,29 +25,35 @@ module Vips
|
|
25
25
|
attach_function :vips_foreign_find_load_buffer, [:pointer, :size_t], :string
|
26
26
|
attach_function :vips_foreign_find_save_buffer, [:string], :string
|
27
27
|
|
28
|
-
if Vips
|
28
|
+
if Vips.at_least_libvips?(8, 9)
|
29
29
|
attach_function :vips_foreign_find_load_source, [:pointer], :string
|
30
30
|
attach_function :vips_foreign_find_save_target, [:string], :string
|
31
31
|
end
|
32
32
|
|
33
33
|
attach_function :vips_image_write_to_memory,
|
34
|
-
|
34
|
+
[:pointer, SizeStruct.ptr], :pointer
|
35
35
|
|
36
36
|
attach_function :vips_image_get_typeof, [:pointer, :string], :GType
|
37
37
|
attach_function :vips_image_get,
|
38
|
-
|
38
|
+
[:pointer, :string, GObject::GValue.ptr], :int
|
39
39
|
|
40
|
-
|
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)
|
41
45
|
attach_function :vips_image_get_fields, [:pointer], :pointer
|
42
46
|
attach_function :vips_image_hasalpha, [:pointer], :int
|
43
47
|
end
|
44
48
|
|
45
|
-
if Vips
|
49
|
+
if Vips.at_least_libvips?(8, 6)
|
46
50
|
attach_function :vips_addalpha, [:pointer, :pointer, :varargs], :int
|
47
51
|
end
|
48
52
|
|
53
|
+
# move these three lines to mutableimage when we finally remove set and
|
54
|
+
# remove in this class
|
49
55
|
attach_function :vips_image_set,
|
50
|
-
|
56
|
+
[:pointer, :string, GObject::GValue.ptr], :void
|
51
57
|
attach_function :vips_image_remove, [:pointer, :string], :void
|
52
58
|
|
53
59
|
attach_function :vips_band_format_iscomplex, [:int], :int
|
@@ -55,6 +61,9 @@ module Vips
|
|
55
61
|
|
56
62
|
attach_function :nickname_find, :vips_nickname_find, [:GType], :string
|
57
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
|
+
|
58
67
|
# turn a raw pointer that must be freed into a self-freeing Ruby string
|
59
68
|
def self.p2str(pointer)
|
60
69
|
pointer = FFI::AutoPointer.new(pointer, GLib::G_FREE)
|
@@ -69,6 +78,11 @@ module Vips
|
|
69
78
|
class Image < Vips::Object
|
70
79
|
alias_method :parent_get_typeof, :get_typeof
|
71
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
|
+
|
72
86
|
private
|
73
87
|
|
74
88
|
# the layout of the VipsImage struct
|
@@ -96,17 +110,17 @@ module Vips
|
|
96
110
|
# handy for overloads ... want to be able to apply a function to an
|
97
111
|
# array or to a scalar
|
98
112
|
def self.smap x, &block
|
99
|
-
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)
|
100
114
|
end
|
101
115
|
|
102
116
|
def self.complex? format
|
103
117
|
format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format
|
104
|
-
Vips
|
118
|
+
Vips.vips_band_format_iscomplex(format_number) != 0
|
105
119
|
end
|
106
120
|
|
107
121
|
def self.float? format
|
108
122
|
format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format
|
109
|
-
Vips
|
123
|
+
Vips.vips_band_format_isfloat(format_number) != 0
|
110
124
|
end
|
111
125
|
|
112
126
|
# run a complex operation on a complex image, or an image with an even
|
@@ -115,12 +129,12 @@ module Vips
|
|
115
129
|
def self.run_cmplx image, &block
|
116
130
|
original_format = image.format
|
117
131
|
|
118
|
-
unless Image
|
132
|
+
unless Image.complex? image.format
|
119
133
|
if image.bands % 2 != 0
|
120
134
|
raise Vips::Error, "not an even number of bands"
|
121
135
|
end
|
122
136
|
|
123
|
-
unless Image
|
137
|
+
unless Image.float? image.format
|
124
138
|
image = image.cast :float
|
125
139
|
end
|
126
140
|
|
@@ -128,9 +142,9 @@ module Vips
|
|
128
142
|
image = image.copy format: new_format, bands: image.bands / 2
|
129
143
|
end
|
130
144
|
|
131
|
-
image = block.(image)
|
145
|
+
image = block.call(image)
|
132
146
|
|
133
|
-
unless Image
|
147
|
+
unless Image.complex? original_format
|
134
148
|
new_format = image.format == :dpcomplex ? :double : :float
|
135
149
|
image = image.copy format: new_format, bands: image.bands * 2
|
136
150
|
end
|
@@ -189,15 +203,19 @@ module Vips
|
|
189
203
|
# 36013-heads-up-ruby-implicitly-converts-a-hash-to-keyword-arguments
|
190
204
|
return false if name == :to_hash
|
191
205
|
|
206
|
+
super
|
207
|
+
end
|
208
|
+
|
209
|
+
def respond_to_missing? name, include_all = false
|
192
210
|
# respond to all vips operations by nickname
|
193
|
-
return true if Vips
|
211
|
+
return true if Vips.type_find("VipsOperation", name.to_s) != 0
|
194
212
|
|
195
213
|
super
|
196
214
|
end
|
197
215
|
|
198
|
-
def self.
|
216
|
+
def self.respond_to_missing? name, include_all = false
|
199
217
|
# respond to all vips operations by nickname
|
200
|
-
return true if Vips
|
218
|
+
return true if Vips.type_find("VipsOperation", name.to_s) != 0
|
201
219
|
|
202
220
|
super
|
203
221
|
end
|
@@ -255,18 +273,18 @@ module Vips
|
|
255
273
|
def self.new_from_file name, **opts
|
256
274
|
# very common, and Vips::vips_filename_get_filename will segv if we
|
257
275
|
# pass this
|
258
|
-
raise Vips::Error, "filename is nil" if name
|
276
|
+
raise Vips::Error, "filename is nil" if name.nil?
|
259
277
|
|
260
|
-
filename = Vips
|
261
|
-
option_string = Vips
|
262
|
-
loader = Vips
|
263
|
-
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?
|
264
282
|
|
265
283
|
Operation.call loader, [filename], opts, option_string
|
266
284
|
end
|
267
285
|
|
268
|
-
# Create a new {Image} for an image encoded
|
269
|
-
# 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
|
270
288
|
# strings or appended as a hash. For example:
|
271
289
|
#
|
272
290
|
# ```
|
@@ -297,12 +315,113 @@ module Vips
|
|
297
315
|
# @macro vips.loadopts
|
298
316
|
# @return [Image] the loaded image
|
299
317
|
def self.new_from_buffer data, option_string, **opts
|
300
|
-
loader = Vips
|
318
|
+
loader = Vips.vips_foreign_find_load_buffer data, data.bytesize
|
301
319
|
raise Vips::Error if loader.nil?
|
302
320
|
|
303
321
|
Vips::Operation.call loader, [data], opts, option_string
|
304
322
|
end
|
305
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
|
+
|
306
425
|
# Create a new {Image} from a source. Load options may be passed as
|
307
426
|
# strings or appended as a hash. For example:
|
308
427
|
#
|
@@ -328,7 +447,7 @@ module Vips
|
|
328
447
|
# TIFF images will work.
|
329
448
|
#
|
330
449
|
# Loading is fast: only enough data is read to be able to fill
|
331
|
-
# out the header. Pixels will only be read and decompressed when they are
|
450
|
+
# out the header. Pixels will only be read and decompressed when they are
|
332
451
|
# needed.
|
333
452
|
#
|
334
453
|
# @param source [Vips::Source] the source to load from
|
@@ -336,7 +455,7 @@ module Vips
|
|
336
455
|
# @macro vips.loadopts
|
337
456
|
# @return [Image] the loaded image
|
338
457
|
def self.new_from_source source, option_string, **opts
|
339
|
-
loader = Vips
|
458
|
+
loader = Vips.vips_foreign_find_load_source source
|
340
459
|
raise Vips::Error if loader.nil?
|
341
460
|
|
342
461
|
Vips::Operation.call loader, [source], opts, option_string
|
@@ -345,8 +464,8 @@ module Vips
|
|
345
464
|
def self.matrix_from_array width, height, array
|
346
465
|
ptr = FFI::MemoryPointer.new :double, array.length
|
347
466
|
ptr.write_array_of_double array
|
348
|
-
image = Vips
|
349
|
-
|
467
|
+
image = Vips.vips_image_new_matrix_from_array width, height,
|
468
|
+
ptr, array.length
|
350
469
|
Vips::Image.new image
|
351
470
|
end
|
352
471
|
|
@@ -399,18 +518,22 @@ module Vips
|
|
399
518
|
width = array.length
|
400
519
|
end
|
401
520
|
|
521
|
+
unless array.length == width * height
|
522
|
+
raise Vips::Error, "Bad array dimensions."
|
523
|
+
end
|
524
|
+
|
402
525
|
unless array.all? { |x| x.is_a? Numeric }
|
403
526
|
raise Vips::Error, "Not all array elements are Numeric."
|
404
527
|
end
|
405
528
|
|
406
529
|
image = Vips::Image.matrix_from_array width, height, array
|
407
|
-
raise Vips::Error if image
|
408
|
-
|
409
|
-
# be careful to set them as double
|
410
|
-
image.set_type GObject::GDOUBLE_TYPE, 'scale', scale.to_f
|
411
|
-
image.set_type GObject::GDOUBLE_TYPE, 'offset', offset.to_f
|
530
|
+
raise Vips::Error if image.nil?
|
412
531
|
|
413
|
-
|
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
|
414
537
|
end
|
415
538
|
|
416
539
|
# A new image is created with the same width, height, format,
|
@@ -459,12 +582,12 @@ module Vips
|
|
459
582
|
#
|
460
583
|
# @param name [String] filename to write to
|
461
584
|
def write_to_file name, **opts
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
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?
|
468
591
|
|
469
592
|
Vips::Operation.call saver, [self, filename], opts, option_string
|
470
593
|
|
@@ -497,19 +620,18 @@ module Vips
|
|
497
620
|
# @macro vips.saveopts
|
498
621
|
# @return [String] the image saved in the specified format
|
499
622
|
def write_to_buffer format_string, **opts
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
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?
|
506
628
|
|
507
629
|
buffer = Vips::Operation.call saver, [self], opts, option_string
|
508
|
-
raise Vips::Error if buffer
|
630
|
+
raise Vips::Error if buffer.nil?
|
509
631
|
|
510
632
|
write_gc
|
511
633
|
|
512
|
-
|
634
|
+
buffer
|
513
635
|
end
|
514
636
|
|
515
637
|
# Write this image to a target. Save options may be encoded in
|
@@ -539,12 +661,11 @@ module Vips
|
|
539
661
|
# @param format_string [String] save format plus string options
|
540
662
|
# @macro vips.saveopts
|
541
663
|
def write_to_target target, format_string, **opts
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
end
|
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?
|
548
669
|
|
549
670
|
Vips::Operation.call saver, [self, target], opts, option_string
|
550
671
|
write_gc
|
@@ -555,8 +676,8 @@ module Vips
|
|
555
676
|
# @return [String] the pixels as a huge binary string
|
556
677
|
def write_to_memory
|
557
678
|
len = Vips::SizeStruct.new
|
558
|
-
ptr = Vips
|
559
|
-
raise Vips::Error if ptr
|
679
|
+
ptr = Vips.vips_image_write_to_memory self, len
|
680
|
+
raise Vips::Error if ptr.nil?
|
560
681
|
|
561
682
|
# wrap up as an autopointer
|
562
683
|
ptr = FFI::AutoPointer.new(ptr, GLib::G_FREE)
|
@@ -564,15 +685,15 @@ module Vips
|
|
564
685
|
ptr.get_bytes 0, len[:value]
|
565
686
|
end
|
566
687
|
|
567
|
-
# Turn progress signalling on and off.
|
688
|
+
# Turn progress signalling on and off.
|
568
689
|
#
|
569
690
|
# If this is on, the most-downstream image from this image will issue
|
570
|
-
# progress signals.
|
691
|
+
# progress signals.
|
571
692
|
#
|
572
693
|
# @see Object#signal_connect
|
573
694
|
# @param state [Boolean] progress signalling state
|
574
695
|
def set_progress state
|
575
|
-
Vips
|
696
|
+
Vips.vips_image_set_progress self, state
|
576
697
|
end
|
577
698
|
|
578
699
|
# Kill computation of this time.
|
@@ -583,7 +704,7 @@ module Vips
|
|
583
704
|
# @see Object#signal_connect
|
584
705
|
# @param kill [Boolean] stop computation
|
585
706
|
def set_kill kill
|
586
|
-
Vips
|
707
|
+
Vips.vips_image_set_kill self, kill
|
587
708
|
end
|
588
709
|
|
589
710
|
# Get the `GType` of a metadata field. The result is 0 if no such field
|
@@ -595,12 +716,12 @@ module Vips
|
|
595
716
|
def get_typeof name
|
596
717
|
# on libvips before 8.5, property types must be searched first,
|
597
718
|
# since vips_image_get_typeof returned built-in enums as int
|
598
|
-
unless Vips
|
719
|
+
unless Vips.at_least_libvips?(8, 5)
|
599
720
|
gtype = parent_get_typeof name
|
600
721
|
return gtype if gtype != 0
|
601
722
|
end
|
602
723
|
|
603
|
-
Vips
|
724
|
+
Vips.vips_image_get_typeof self, name
|
604
725
|
end
|
605
726
|
|
606
727
|
# Get a metadata item from an image. Ruby types are constructed
|
@@ -619,12 +740,12 @@ module Vips
|
|
619
740
|
def get name
|
620
741
|
# with old libvips, we must fetch properties (as opposed to
|
621
742
|
# metadata) via VipsObject
|
622
|
-
unless Vips
|
743
|
+
unless Vips.at_least_libvips?(8, 5)
|
623
744
|
return super if parent_get_typeof(name) != 0
|
624
745
|
end
|
625
746
|
|
626
747
|
gvalue = GObject::GValue.alloc
|
627
|
-
raise Vips::Error if Vips
|
748
|
+
raise Vips::Error if Vips.vips_image_get(self, name, gvalue) != 0
|
628
749
|
result = gvalue.get
|
629
750
|
gvalue.unset
|
630
751
|
|
@@ -639,67 +760,64 @@ module Vips
|
|
639
760
|
# vips_image_get_fields() was added in libvips 8.5
|
640
761
|
return [] unless Vips.respond_to? :vips_image_get_fields
|
641
762
|
|
642
|
-
array = Vips
|
763
|
+
array = Vips.vips_image_get_fields self
|
643
764
|
|
644
765
|
names = []
|
645
766
|
p = array
|
646
767
|
until (q = p.read_pointer).null?
|
647
768
|
names << q.read_string
|
648
|
-
GLib
|
769
|
+
GLib.g_free q
|
649
770
|
p += FFI::Type::POINTER.size
|
650
771
|
end
|
651
|
-
GLib
|
772
|
+
GLib.g_free array
|
652
773
|
|
653
774
|
names
|
654
775
|
end
|
655
776
|
|
656
|
-
#
|
657
|
-
#
|
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.
|
658
780
|
#
|
659
|
-
# For example
|
781
|
+
# For example:
|
660
782
|
#
|
661
|
-
# ```
|
662
|
-
#
|
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
|
663
789
|
# ```
|
664
790
|
#
|
665
|
-
#
|
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.
|
666
799
|
#
|
667
|
-
#
|
668
|
-
# @param gtype [Integer] GType of item
|
669
|
-
# @param name [String] Metadata field to set
|
670
|
-
# @param value [Object] Value to set
|
800
|
+
# Please use {MutableImage#set_type!} instead.
|
671
801
|
def set_type gtype, name, value
|
672
802
|
gvalue = GObject::GValue.alloc
|
673
803
|
gvalue.init gtype
|
674
804
|
gvalue.set value
|
675
|
-
Vips
|
805
|
+
Vips.vips_image_set self, name, gvalue
|
676
806
|
gvalue.unset
|
677
807
|
end
|
678
808
|
|
679
|
-
#
|
680
|
-
# already exist. Ruby types are automatically transformed into the
|
681
|
-
# matching `GValue`, if possible.
|
682
|
-
#
|
683
|
-
# For example, you can use this to set an image's ICC profile:
|
684
|
-
#
|
685
|
-
# ```
|
686
|
-
# x = y.set "icc-profile-data", profile
|
687
|
-
# ```
|
688
|
-
#
|
689
|
-
# where `profile` is an ICC profile held as a binary string object.
|
809
|
+
# This method is deprecated.
|
690
810
|
#
|
691
|
-
#
|
692
|
-
# @param name [String] Metadata field to set
|
693
|
-
# @param value [Object] Value to set
|
811
|
+
# Please use {MutableImage#set!} instead.
|
694
812
|
def set name, value
|
695
813
|
set_type get_typeof(name), name, value
|
696
814
|
end
|
697
815
|
|
698
|
-
#
|
816
|
+
# This method is deprecated.
|
699
817
|
#
|
700
|
-
#
|
818
|
+
# Please use {MutableImage#remove!} instead.
|
701
819
|
def remove name
|
702
|
-
Vips
|
820
|
+
Vips.vips_image_remove self, name
|
703
821
|
end
|
704
822
|
|
705
823
|
# compatibility: old name for get
|
@@ -707,7 +825,9 @@ module Vips
|
|
707
825
|
get name
|
708
826
|
end
|
709
827
|
|
710
|
-
#
|
828
|
+
# This method is deprecated.
|
829
|
+
#
|
830
|
+
# Please use {MutableImage#set!} instead.
|
711
831
|
def set_value name, value
|
712
832
|
set name, value
|
713
833
|
end
|
@@ -716,21 +836,21 @@ module Vips
|
|
716
836
|
#
|
717
837
|
# @return [Integer] image width, in pixels
|
718
838
|
def width
|
719
|
-
|
839
|
+
Vips.vips_image_get_width self
|
720
840
|
end
|
721
841
|
|
722
842
|
# Get image height, in pixels.
|
723
843
|
#
|
724
844
|
# @return [Integer] image height, in pixels
|
725
845
|
def height
|
726
|
-
|
846
|
+
Vips.vips_image_get_height self
|
727
847
|
end
|
728
848
|
|
729
849
|
# Get number of image bands.
|
730
850
|
#
|
731
851
|
# @return [Integer] number of image bands
|
732
852
|
def bands
|
733
|
-
|
853
|
+
Vips.vips_image_get_bands self
|
734
854
|
end
|
735
855
|
|
736
856
|
# Get image format.
|
@@ -814,23 +934,23 @@ module Vips
|
|
814
934
|
[width, height]
|
815
935
|
end
|
816
936
|
|
817
|
-
if Vips
|
937
|
+
if Vips.at_least_libvips?(8, 5)
|
818
938
|
# Detect if image has an alpha channel
|
819
939
|
#
|
820
940
|
# @return [Boolean] true if image has an alpha channel.
|
821
941
|
def has_alpha?
|
822
|
-
|
942
|
+
Vips.vips_image_hasalpha(self) != 0
|
823
943
|
end
|
824
944
|
end
|
825
945
|
|
826
946
|
# vips_addalpha was added in libvips 8.6
|
827
|
-
if Vips
|
947
|
+
if Vips.at_least_libvips?(8, 6)
|
828
948
|
# Append an alpha channel to an image.
|
829
949
|
#
|
830
950
|
# @return [Image] new image
|
831
951
|
def add_alpha
|
832
952
|
ptr = GenericPtr.new
|
833
|
-
result = Vips
|
953
|
+
result = Vips.vips_addalpha self, ptr
|
834
954
|
raise Vips::Error if result != 0
|
835
955
|
|
836
956
|
Vips::Image.new ptr[:value]
|
@@ -845,7 +965,7 @@ module Vips
|
|
845
965
|
#
|
846
966
|
# @return [Image] new memory image
|
847
967
|
def copy_memory
|
848
|
-
new_image = Vips
|
968
|
+
new_image = Vips.vips_image_copy_memory self
|
849
969
|
Vips::Image.new new_image
|
850
970
|
end
|
851
971
|
|
@@ -855,7 +975,7 @@ module Vips
|
|
855
975
|
#
|
856
976
|
# @return [Image] modified image
|
857
977
|
def draw_point ink, left, top, **opts
|
858
|
-
draw_rect ink, left, top, 1, 1, opts
|
978
|
+
draw_rect ink, left, top, 1, 1, **opts
|
859
979
|
end
|
860
980
|
|
861
981
|
# Add an image, constant or array.
|
@@ -873,7 +993,7 @@ module Vips
|
|
873
993
|
# @return [Image] result of subtraction
|
874
994
|
def - other
|
875
995
|
other.is_a?(Vips::Image) ?
|
876
|
-
subtract(other) : linear(1, Image
|
996
|
+
subtract(other) : linear(1, Image.smap(other) { |x| x * -1 })
|
877
997
|
end
|
878
998
|
|
879
999
|
# Multiply an image, constant or array.
|
@@ -891,7 +1011,7 @@ module Vips
|
|
891
1011
|
# @return [Image] result of division
|
892
1012
|
def / other
|
893
1013
|
other.is_a?(Vips::Image) ?
|
894
|
-
divide(other) : linear(Image
|
1014
|
+
divide(other) : linear(Image.smap(other) { |x| 1.0 / x }, 0)
|
895
1015
|
end
|
896
1016
|
|
897
1017
|
# Remainder after integer division with an image, constant or array.
|
@@ -1017,7 +1137,7 @@ module Vips
|
|
1017
1137
|
# @return [Image] result of equality
|
1018
1138
|
def == other
|
1019
1139
|
# for equality, we must allow tests against nil
|
1020
|
-
if other
|
1140
|
+
if other.nil?
|
1021
1141
|
false
|
1022
1142
|
else
|
1023
1143
|
call_enum "relational", other, :equal
|
@@ -1030,7 +1150,7 @@ module Vips
|
|
1030
1150
|
# @return [Image] result of inequality
|
1031
1151
|
def != other
|
1032
1152
|
# for equality, we must allow tests against nil
|
1033
|
-
if other
|
1153
|
+
if other.nil?
|
1034
1154
|
true
|
1035
1155
|
else
|
1036
1156
|
call_enum "relational", other, :noteq
|
@@ -1052,38 +1172,40 @@ module Vips
|
|
1052
1172
|
end
|
1053
1173
|
end
|
1054
1174
|
|
1055
|
-
# Convert to an
|
1175
|
+
# Convert to an Enumerator. Similar to `#to_a` but lazier.
|
1056
1176
|
#
|
1057
|
-
# @return [
|
1058
|
-
def
|
1059
|
-
# we render the image to a big string, then unpack
|
1060
|
-
# as a Ruby array of the correct type
|
1061
|
-
memory = write_to_memory
|
1062
|
-
|
1177
|
+
# @return [Enumerator] Enumerator of Enumerators of Arrays of Numerics
|
1178
|
+
def to_enum
|
1063
1179
|
# make the template for unpack
|
1064
1180
|
template = {
|
1065
|
-
char:
|
1066
|
-
uchar:
|
1067
|
-
short:
|
1068
|
-
ushort:
|
1069
|
-
int:
|
1070
|
-
uint:
|
1071
|
-
float:
|
1072
|
-
double:
|
1073
|
-
complex:
|
1074
|
-
dpcomplex:
|
1075
|
-
}[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] + "*"
|
1076
1192
|
|
1077
|
-
#
|
1078
|
-
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
|
1079
1196
|
|
1080
|
-
# gather
|
1081
|
-
pixel_array = array.each_slice
|
1197
|
+
# gather bands of a pixel together
|
1198
|
+
pixel_array = array.each_slice bands
|
1082
1199
|
|
1083
|
-
#
|
1084
|
-
|
1200
|
+
# gather pixels of a row together
|
1201
|
+
pixel_array.each_slice width
|
1202
|
+
end
|
1085
1203
|
|
1086
|
-
|
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
|
1087
1209
|
end
|
1088
1210
|
|
1089
1211
|
# Return the largest integral value not greater than the argument.
|
@@ -1159,7 +1281,10 @@ module Vips
|
|
1159
1281
|
# @param overlay [Image, Array<Image>] images to composite
|
1160
1282
|
# @param mode [BlendMode, Array<BlendMode>] blend modes to use
|
1161
1283
|
# @param opts [Hash] Set of options
|
1162
|
-
# @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
|
1163
1288
|
# @option opts [Boolean] :premultiplied Images have premultiplied alpha
|
1164
1289
|
# @return [Image] blended image
|
1165
1290
|
def composite overlay, mode, **opts
|
@@ -1183,9 +1308,9 @@ module Vips
|
|
1183
1308
|
# coordinate of maximum
|
1184
1309
|
def maxpos
|
1185
1310
|
v, opts = max x: true, y: true
|
1186
|
-
x = opts[
|
1187
|
-
y = opts[
|
1188
|
-
|
1311
|
+
x = opts["x"]
|
1312
|
+
y = opts["y"]
|
1313
|
+
[v, x, y]
|
1189
1314
|
end
|
1190
1315
|
|
1191
1316
|
# Return the coordinates of the image minimum.
|
@@ -1194,9 +1319,9 @@ module Vips
|
|
1194
1319
|
# coordinate of minimum
|
1195
1320
|
def minpos
|
1196
1321
|
v, opts = min x: true, y: true
|
1197
|
-
x = opts[
|
1198
|
-
y = opts[
|
1199
|
-
|
1322
|
+
x = opts["x"]
|
1323
|
+
y = opts["y"]
|
1324
|
+
[v, x, y]
|
1200
1325
|
end
|
1201
1326
|
|
1202
1327
|
# a median filter
|
@@ -1204,7 +1329,7 @@ module Vips
|
|
1204
1329
|
# @param size [Integer] size of filter window
|
1205
1330
|
# @return [Image] result of median filter
|
1206
1331
|
def median size = 3
|
1207
|
-
rank size, size,
|
1332
|
+
rank size, size, size**2 / 2
|
1208
1333
|
end
|
1209
1334
|
|
1210
1335
|
# Return the real part of a complex image.
|
@@ -1231,7 +1356,7 @@ module Vips
|
|
1231
1356
|
# @see xyz
|
1232
1357
|
# @return [Image] image converted to polar coordinates
|
1233
1358
|
def polar
|
1234
|
-
Image
|
1359
|
+
Image.run_cmplx(self) { |x| x.complex :polar }
|
1235
1360
|
end
|
1236
1361
|
|
1237
1362
|
# Return an image with polar pixels converted to rectangular.
|
@@ -1244,7 +1369,7 @@ module Vips
|
|
1244
1369
|
# @see xyz
|
1245
1370
|
# @return [Image] image converted to rectangular coordinates
|
1246
1371
|
def rect
|
1247
|
-
Image
|
1372
|
+
Image.run_cmplx(self) { |x| x.complex :rect }
|
1248
1373
|
end
|
1249
1374
|
|
1250
1375
|
# Return the complex conjugate of an image.
|
@@ -1256,7 +1381,7 @@ module Vips
|
|
1256
1381
|
#
|
1257
1382
|
# @return [Image] complex conjugate
|
1258
1383
|
def conj
|
1259
|
-
Image
|
1384
|
+
Image.run_cmplx(self) { |x| x.complex :conj }
|
1260
1385
|
end
|
1261
1386
|
|
1262
1387
|
# Calculate the cross phase of two images.
|
@@ -1437,7 +1562,7 @@ module Vips
|
|
1437
1562
|
#
|
1438
1563
|
# ```
|
1439
1564
|
# $ ruby > methods.rb
|
1440
|
-
# require
|
1565
|
+
# require "vips"; Vips::Yard.generate
|
1441
1566
|
# ^D
|
1442
1567
|
# ```
|
1443
1568
|
|
@@ -1459,7 +1584,7 @@ module Vips
|
|
1459
1584
|
"VipsArrayDouble" => "Array<Double>",
|
1460
1585
|
"VipsArrayInt" => "Array<Integer>",
|
1461
1586
|
"VipsArrayImage" => "Array<Image>",
|
1462
|
-
"VipsArrayString" => "Array<String>"
|
1587
|
+
"VipsArrayString" => "Array<String>"
|
1463
1588
|
}
|
1464
1589
|
|
1465
1590
|
# these have hand-written methods, see above
|
@@ -1470,15 +1595,15 @@ module Vips
|
|
1470
1595
|
|
1471
1596
|
# turn a gtype into a ruby type name
|
1472
1597
|
def self.gtype_to_ruby gtype
|
1473
|
-
fundamental = GObject
|
1474
|
-
type_name = GObject
|
1598
|
+
fundamental = GObject.g_type_fundamental gtype
|
1599
|
+
type_name = GObject.g_type_name gtype
|
1475
1600
|
|
1476
1601
|
if MAP_GO_TO_RUBY.include? type_name
|
1477
1602
|
type_name = MAP_GO_TO_RUBY[type_name]
|
1478
1603
|
end
|
1479
1604
|
|
1480
1605
|
if fundamental == GObject::GFLAGS_TYPE ||
|
1481
|
-
|
1606
|
+
fundamental == GObject::GENUM_TYPE
|
1482
1607
|
type_name = "Vips::" + type_name[/Vips(.*)/, 1]
|
1483
1608
|
end
|
1484
1609
|
|
@@ -1497,7 +1622,7 @@ module Vips
|
|
1497
1622
|
print "# @!method "
|
1498
1623
|
print "self." unless introspect.member_x
|
1499
1624
|
print "#{introspect.name}("
|
1500
|
-
print method_args.map{ |x| x[:yard_name] }.join(", ")
|
1625
|
+
print method_args.map { |x| x[:yard_name] }.join(", ")
|
1501
1626
|
print ", " if method_args.length > 0
|
1502
1627
|
puts "**opts)"
|
1503
1628
|
|
@@ -1517,8 +1642,7 @@ module Vips
|
|
1517
1642
|
gtype = details[:gtype]
|
1518
1643
|
blurb = details[:blurb]
|
1519
1644
|
|
1520
|
-
puts "# @option opts [#{gtype_to_ruby(gtype)}] :#{yard_name} "
|
1521
|
-
"#{blurb}"
|
1645
|
+
puts "# @option opts [#{gtype_to_ruby(gtype)}] :#{yard_name} #{blurb}"
|
1522
1646
|
end
|
1523
1647
|
optional_output.each do |arg_name, details|
|
1524
1648
|
yard_name = details[:yard_name]
|
@@ -1536,14 +1660,14 @@ module Vips
|
|
1536
1660
|
print gtype_to_ruby(required_output.first[:gtype])
|
1537
1661
|
else
|
1538
1662
|
print "Array<"
|
1539
|
-
print required_output.map{ |x| gtype_to_ruby(x[:gtype]) }.join(", ")
|
1663
|
+
print required_output.map { |x| gtype_to_ruby(x[:gtype]) }.join(", ")
|
1540
1664
|
print ">"
|
1541
1665
|
end
|
1542
1666
|
if optional_output.length > 0
|
1543
1667
|
print ", Hash<Symbol => Object>"
|
1544
1668
|
end
|
1545
1669
|
print "] "
|
1546
|
-
print required_output.map{ |x| x[:blurb] }.join(", ")
|
1670
|
+
print required_output.map { |x| x[:blurb] }.join(", ")
|
1547
1671
|
if optional_output.length > 0
|
1548
1672
|
print ", " if required_output.length > 0
|
1549
1673
|
print "Hash of optional output items"
|
@@ -1555,16 +1679,16 @@ module Vips
|
|
1555
1679
|
|
1556
1680
|
def self.generate
|
1557
1681
|
alias_gtypes = {}
|
1558
|
-
ALIAS.each do |name|
|
1559
|
-
gtype = Vips
|
1560
|
-
alias_gtypes[gtype] = name
|
1682
|
+
ALIAS.each do |name|
|
1683
|
+
gtype = Vips.type_find "VipsOperation", name
|
1684
|
+
alias_gtypes[gtype] = name
|
1561
1685
|
end
|
1562
1686
|
|
1563
1687
|
generate_class = lambda do |gtype, _|
|
1564
|
-
if alias_gtypes.key? gtype
|
1565
|
-
|
1688
|
+
name = if alias_gtypes.key? gtype
|
1689
|
+
alias_gtypes[gtype]
|
1566
1690
|
else
|
1567
|
-
|
1691
|
+
Vips.nickname_find gtype
|
1568
1692
|
end
|
1569
1693
|
|
1570
1694
|
if name
|
@@ -1578,14 +1702,14 @@ module Vips
|
|
1578
1702
|
generate_operation(introspect) if introspect
|
1579
1703
|
end
|
1580
1704
|
|
1581
|
-
Vips
|
1705
|
+
Vips.vips_type_map gtype, generate_class, nil
|
1582
1706
|
end
|
1583
1707
|
|
1584
1708
|
puts "module Vips"
|
1585
1709
|
puts " class Image"
|
1586
1710
|
puts ""
|
1587
1711
|
|
1588
|
-
generate_class.(GObject
|
1712
|
+
generate_class.call(GObject.g_type_from_name("VipsOperation"), nil)
|
1589
1713
|
|
1590
1714
|
puts " end"
|
1591
1715
|
puts "end"
|