ruby-vips 2.0.17 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.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 +13 -0
- data/Gemfile +3 -1
- data/README.md +4 -4
- data/Rakefile +13 -21
- data/TODO +3 -6
- 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 +35 -36
- 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 +121 -75
- 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 +232 -155
- data/lib/vips/interpolate.rb +3 -2
- data/lib/vips/methods.rb +165 -15
- data/lib/vips/mutableimage.rb +154 -0
- data/lib/vips/object.rb +84 -85
- 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 +28 -48
- 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)
|
@@ -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
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
|
@@ -189,15 +198,19 @@ module Vips
|
|
189
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
|
@@ -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,12 +310,75 @@ 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
|
313
|
+
loader = Vips.vips_foreign_find_load_buffer data, data.bytesize
|
301
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
|
+
|
306
382
|
# Create a new {Image} from a source. Load options may be passed as
|
307
383
|
# strings or appended as a hash. For example:
|
308
384
|
#
|
@@ -328,7 +404,7 @@ module Vips
|
|
328
404
|
# TIFF images will work.
|
329
405
|
#
|
330
406
|
# 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
|
407
|
+
# out the header. Pixels will only be read and decompressed when they are
|
332
408
|
# needed.
|
333
409
|
#
|
334
410
|
# @param source [Vips::Source] the source to load from
|
@@ -336,7 +412,7 @@ module Vips
|
|
336
412
|
# @macro vips.loadopts
|
337
413
|
# @return [Image] the loaded image
|
338
414
|
def self.new_from_source source, option_string, **opts
|
339
|
-
loader = Vips
|
415
|
+
loader = Vips.vips_foreign_find_load_source source
|
340
416
|
raise Vips::Error if loader.nil?
|
341
417
|
|
342
418
|
Vips::Operation.call loader, [source], opts, option_string
|
@@ -345,8 +421,8 @@ module Vips
|
|
345
421
|
def self.matrix_from_array width, height, array
|
346
422
|
ptr = FFI::MemoryPointer.new :double, array.length
|
347
423
|
ptr.write_array_of_double array
|
348
|
-
image = Vips
|
349
|
-
|
424
|
+
image = Vips.vips_image_new_matrix_from_array width, height,
|
425
|
+
ptr, array.length
|
350
426
|
Vips::Image.new image
|
351
427
|
end
|
352
428
|
|
@@ -399,18 +475,22 @@ module Vips
|
|
399
475
|
width = array.length
|
400
476
|
end
|
401
477
|
|
478
|
+
unless array.length == width * height
|
479
|
+
raise Vips::Error, "Bad array dimensions."
|
480
|
+
end
|
481
|
+
|
402
482
|
unless array.all? { |x| x.is_a? Numeric }
|
403
483
|
raise Vips::Error, "Not all array elements are Numeric."
|
404
484
|
end
|
405
485
|
|
406
486
|
image = Vips::Image.matrix_from_array width, height, array
|
407
|
-
raise Vips::Error if image
|
487
|
+
raise Vips::Error if image.nil?
|
408
488
|
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
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
|
414
494
|
end
|
415
495
|
|
416
496
|
# A new image is created with the same width, height, format,
|
@@ -426,7 +506,7 @@ module Vips
|
|
426
506
|
pixel = (Vips::Image.black(1, 1) + value).cast(format)
|
427
507
|
image = pixel.embed 0, 0, width, height, extend: :copy
|
428
508
|
image.copy interpretation: interpretation, xres: xres, yres: yres,
|
429
|
-
|
509
|
+
xoffset: xoffset, yoffset: yoffset
|
430
510
|
end
|
431
511
|
|
432
512
|
# Write this image to a file. Save options may be encoded in the
|
@@ -459,12 +539,12 @@ module Vips
|
|
459
539
|
#
|
460
540
|
# @param name [String] filename to write to
|
461
541
|
def write_to_file name, **opts
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
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?
|
468
548
|
|
469
549
|
Vips::Operation.call saver, [self, filename], opts, option_string
|
470
550
|
|
@@ -497,19 +577,18 @@ module Vips
|
|
497
577
|
# @macro vips.saveopts
|
498
578
|
# @return [String] the image saved in the specified format
|
499
579
|
def write_to_buffer format_string, **opts
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
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?
|
506
585
|
|
507
586
|
buffer = Vips::Operation.call saver, [self], opts, option_string
|
508
|
-
raise Vips::Error if buffer
|
587
|
+
raise Vips::Error if buffer.nil?
|
509
588
|
|
510
589
|
write_gc
|
511
590
|
|
512
|
-
|
591
|
+
buffer
|
513
592
|
end
|
514
593
|
|
515
594
|
# Write this image to a target. Save options may be encoded in
|
@@ -539,12 +618,11 @@ module Vips
|
|
539
618
|
# @param format_string [String] save format plus string options
|
540
619
|
# @macro vips.saveopts
|
541
620
|
def write_to_target target, format_string, **opts
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
end
|
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?
|
548
626
|
|
549
627
|
Vips::Operation.call saver, [self, target], opts, option_string
|
550
628
|
write_gc
|
@@ -555,8 +633,8 @@ module Vips
|
|
555
633
|
# @return [String] the pixels as a huge binary string
|
556
634
|
def write_to_memory
|
557
635
|
len = Vips::SizeStruct.new
|
558
|
-
ptr = Vips
|
559
|
-
raise Vips::Error if ptr
|
636
|
+
ptr = Vips.vips_image_write_to_memory self, len
|
637
|
+
raise Vips::Error if ptr.nil?
|
560
638
|
|
561
639
|
# wrap up as an autopointer
|
562
640
|
ptr = FFI::AutoPointer.new(ptr, GLib::G_FREE)
|
@@ -564,15 +642,15 @@ module Vips
|
|
564
642
|
ptr.get_bytes 0, len[:value]
|
565
643
|
end
|
566
644
|
|
567
|
-
# Turn progress signalling on and off.
|
645
|
+
# Turn progress signalling on and off.
|
568
646
|
#
|
569
647
|
# If this is on, the most-downstream image from this image will issue
|
570
|
-
# progress signals.
|
648
|
+
# progress signals.
|
571
649
|
#
|
572
650
|
# @see Object#signal_connect
|
573
651
|
# @param state [Boolean] progress signalling state
|
574
652
|
def set_progress state
|
575
|
-
Vips
|
653
|
+
Vips.vips_image_set_progress self, state
|
576
654
|
end
|
577
655
|
|
578
656
|
# Kill computation of this time.
|
@@ -583,7 +661,7 @@ module Vips
|
|
583
661
|
# @see Object#signal_connect
|
584
662
|
# @param kill [Boolean] stop computation
|
585
663
|
def set_kill kill
|
586
|
-
Vips
|
664
|
+
Vips.vips_image_set_kill self, kill
|
587
665
|
end
|
588
666
|
|
589
667
|
# Get the `GType` of a metadata field. The result is 0 if no such field
|
@@ -595,12 +673,12 @@ module Vips
|
|
595
673
|
def get_typeof name
|
596
674
|
# on libvips before 8.5, property types must be searched first,
|
597
675
|
# since vips_image_get_typeof returned built-in enums as int
|
598
|
-
unless Vips
|
676
|
+
unless Vips.at_least_libvips?(8, 5)
|
599
677
|
gtype = parent_get_typeof name
|
600
678
|
return gtype if gtype != 0
|
601
679
|
end
|
602
680
|
|
603
|
-
Vips
|
681
|
+
Vips.vips_image_get_typeof self, name
|
604
682
|
end
|
605
683
|
|
606
684
|
# Get a metadata item from an image. Ruby types are constructed
|
@@ -619,12 +697,12 @@ module Vips
|
|
619
697
|
def get name
|
620
698
|
# with old libvips, we must fetch properties (as opposed to
|
621
699
|
# metadata) via VipsObject
|
622
|
-
unless Vips
|
700
|
+
unless Vips.at_least_libvips?(8, 5)
|
623
701
|
return super if parent_get_typeof(name) != 0
|
624
702
|
end
|
625
703
|
|
626
704
|
gvalue = GObject::GValue.alloc
|
627
|
-
raise Vips::Error if Vips
|
705
|
+
raise Vips::Error if Vips.vips_image_get(self, name, gvalue) != 0
|
628
706
|
result = gvalue.get
|
629
707
|
gvalue.unset
|
630
708
|
|
@@ -639,67 +717,64 @@ module Vips
|
|
639
717
|
# vips_image_get_fields() was added in libvips 8.5
|
640
718
|
return [] unless Vips.respond_to? :vips_image_get_fields
|
641
719
|
|
642
|
-
array = Vips
|
720
|
+
array = Vips.vips_image_get_fields self
|
643
721
|
|
644
722
|
names = []
|
645
723
|
p = array
|
646
724
|
until (q = p.read_pointer).null?
|
647
725
|
names << q.read_string
|
648
|
-
GLib
|
726
|
+
GLib.g_free q
|
649
727
|
p += FFI::Type::POINTER.size
|
650
728
|
end
|
651
|
-
GLib
|
729
|
+
GLib.g_free array
|
652
730
|
|
653
731
|
names
|
654
732
|
end
|
655
733
|
|
656
|
-
#
|
657
|
-
#
|
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.
|
658
737
|
#
|
659
|
-
# For example
|
738
|
+
# For example:
|
660
739
|
#
|
661
|
-
# ```
|
662
|
-
#
|
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
|
663
746
|
# ```
|
664
747
|
#
|
665
|
-
#
|
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.
|
666
756
|
#
|
667
|
-
#
|
668
|
-
# @param gtype [Integer] GType of item
|
669
|
-
# @param name [String] Metadata field to set
|
670
|
-
# @param value [Object] Value to set
|
757
|
+
# Please use {MutableImage#set_type!} instead.
|
671
758
|
def set_type gtype, name, value
|
672
759
|
gvalue = GObject::GValue.alloc
|
673
760
|
gvalue.init gtype
|
674
761
|
gvalue.set value
|
675
|
-
Vips
|
762
|
+
Vips.vips_image_set self, name, gvalue
|
676
763
|
gvalue.unset
|
677
764
|
end
|
678
765
|
|
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:
|
766
|
+
# This method is deprecated.
|
684
767
|
#
|
685
|
-
#
|
686
|
-
# x = y.set "icc-profile-data", profile
|
687
|
-
# ```
|
688
|
-
#
|
689
|
-
# where `profile` is an ICC profile held as a binary string object.
|
690
|
-
#
|
691
|
-
# @see set_type
|
692
|
-
# @param name [String] Metadata field to set
|
693
|
-
# @param value [Object] Value to set
|
768
|
+
# Please use {MutableImage#set!} instead.
|
694
769
|
def set name, value
|
695
770
|
set_type get_typeof(name), name, value
|
696
771
|
end
|
697
772
|
|
698
|
-
#
|
773
|
+
# This method is deprecated.
|
699
774
|
#
|
700
|
-
#
|
775
|
+
# Please use {MutableImage#remove!} instead.
|
701
776
|
def remove name
|
702
|
-
Vips
|
777
|
+
Vips.vips_image_remove self, name
|
703
778
|
end
|
704
779
|
|
705
780
|
# compatibility: old name for get
|
@@ -707,7 +782,9 @@ module Vips
|
|
707
782
|
get name
|
708
783
|
end
|
709
784
|
|
710
|
-
#
|
785
|
+
# This method is deprecated.
|
786
|
+
#
|
787
|
+
# Please use {MutableImage#set!} instead.
|
711
788
|
def set_value name, value
|
712
789
|
set name, value
|
713
790
|
end
|
@@ -716,21 +793,21 @@ module Vips
|
|
716
793
|
#
|
717
794
|
# @return [Integer] image width, in pixels
|
718
795
|
def width
|
719
|
-
|
796
|
+
Vips.vips_image_get_width self
|
720
797
|
end
|
721
798
|
|
722
799
|
# Get image height, in pixels.
|
723
800
|
#
|
724
801
|
# @return [Integer] image height, in pixels
|
725
802
|
def height
|
726
|
-
|
803
|
+
Vips.vips_image_get_height self
|
727
804
|
end
|
728
805
|
|
729
806
|
# Get number of image bands.
|
730
807
|
#
|
731
808
|
# @return [Integer] number of image bands
|
732
809
|
def bands
|
733
|
-
|
810
|
+
Vips.vips_image_get_bands self
|
734
811
|
end
|
735
812
|
|
736
813
|
# Get image format.
|
@@ -814,23 +891,23 @@ module Vips
|
|
814
891
|
[width, height]
|
815
892
|
end
|
816
893
|
|
817
|
-
if Vips
|
894
|
+
if Vips.at_least_libvips?(8, 5)
|
818
895
|
# Detect if image has an alpha channel
|
819
896
|
#
|
820
897
|
# @return [Boolean] true if image has an alpha channel.
|
821
898
|
def has_alpha?
|
822
|
-
|
899
|
+
Vips.vips_image_hasalpha(self) != 0
|
823
900
|
end
|
824
901
|
end
|
825
902
|
|
826
903
|
# vips_addalpha was added in libvips 8.6
|
827
|
-
if Vips
|
904
|
+
if Vips.at_least_libvips?(8, 6)
|
828
905
|
# Append an alpha channel to an image.
|
829
906
|
#
|
830
907
|
# @return [Image] new image
|
831
908
|
def add_alpha
|
832
909
|
ptr = GenericPtr.new
|
833
|
-
result = Vips
|
910
|
+
result = Vips.vips_addalpha self, ptr
|
834
911
|
raise Vips::Error if result != 0
|
835
912
|
|
836
913
|
Vips::Image.new ptr[:value]
|
@@ -845,7 +922,7 @@ module Vips
|
|
845
922
|
#
|
846
923
|
# @return [Image] new memory image
|
847
924
|
def copy_memory
|
848
|
-
new_image = Vips
|
925
|
+
new_image = Vips.vips_image_copy_memory self
|
849
926
|
Vips::Image.new new_image
|
850
927
|
end
|
851
928
|
|
@@ -855,7 +932,7 @@ module Vips
|
|
855
932
|
#
|
856
933
|
# @return [Image] modified image
|
857
934
|
def draw_point ink, left, top, **opts
|
858
|
-
draw_rect ink, left, top, 1, 1, opts
|
935
|
+
draw_rect ink, left, top, 1, 1, **opts
|
859
936
|
end
|
860
937
|
|
861
938
|
# Add an image, constant or array.
|
@@ -873,7 +950,7 @@ module Vips
|
|
873
950
|
# @return [Image] result of subtraction
|
874
951
|
def - other
|
875
952
|
other.is_a?(Vips::Image) ?
|
876
|
-
subtract(other) : linear(1, Image
|
953
|
+
subtract(other) : linear(1, Image.smap(other) { |x| x * -1 })
|
877
954
|
end
|
878
955
|
|
879
956
|
# Multiply an image, constant or array.
|
@@ -891,7 +968,7 @@ module Vips
|
|
891
968
|
# @return [Image] result of division
|
892
969
|
def / other
|
893
970
|
other.is_a?(Vips::Image) ?
|
894
|
-
divide(other) : linear(Image
|
971
|
+
divide(other) : linear(Image.smap(other) { |x| 1.0 / x }, 0)
|
895
972
|
end
|
896
973
|
|
897
974
|
# Remainder after integer division with an image, constant or array.
|
@@ -1017,7 +1094,7 @@ module Vips
|
|
1017
1094
|
# @return [Image] result of equality
|
1018
1095
|
def == other
|
1019
1096
|
# for equality, we must allow tests against nil
|
1020
|
-
if other
|
1097
|
+
if other.nil?
|
1021
1098
|
false
|
1022
1099
|
else
|
1023
1100
|
call_enum "relational", other, :equal
|
@@ -1030,7 +1107,7 @@ module Vips
|
|
1030
1107
|
# @return [Image] result of inequality
|
1031
1108
|
def != other
|
1032
1109
|
# for equality, we must allow tests against nil
|
1033
|
-
if other
|
1110
|
+
if other.nil?
|
1034
1111
|
true
|
1035
1112
|
else
|
1036
1113
|
call_enum "relational", other, :noteq
|
@@ -1062,17 +1139,17 @@ module Vips
|
|
1062
1139
|
|
1063
1140
|
# make the template for unpack
|
1064
1141
|
template = {
|
1065
|
-
char:
|
1066
|
-
uchar:
|
1067
|
-
short:
|
1068
|
-
ushort:
|
1069
|
-
int:
|
1070
|
-
uint:
|
1071
|
-
float:
|
1072
|
-
double:
|
1073
|
-
complex:
|
1074
|
-
dpcomplex:
|
1075
|
-
}[format] +
|
1142
|
+
char: "c",
|
1143
|
+
uchar: "C",
|
1144
|
+
short: "s_",
|
1145
|
+
ushort: "S_",
|
1146
|
+
int: "i_",
|
1147
|
+
uint: "I_",
|
1148
|
+
float: "f",
|
1149
|
+
double: "d",
|
1150
|
+
complex: "f",
|
1151
|
+
dpcomplex: "d"
|
1152
|
+
}[format] + "*"
|
1076
1153
|
|
1077
1154
|
# and unpack into something like [1, 2, 3, 4 ..]
|
1078
1155
|
array = memory.unpack(template)
|
@@ -1081,9 +1158,7 @@ module Vips
|
|
1081
1158
|
pixel_array = array.each_slice(bands).to_a
|
1082
1159
|
|
1083
1160
|
# build rows
|
1084
|
-
|
1085
|
-
|
1086
|
-
return row_array
|
1161
|
+
pixel_array.each_slice(width).to_a
|
1087
1162
|
end
|
1088
1163
|
|
1089
1164
|
# Return the largest integral value not greater than the argument.
|
@@ -1159,7 +1234,10 @@ module Vips
|
|
1159
1234
|
# @param overlay [Image, Array<Image>] images to composite
|
1160
1235
|
# @param mode [BlendMode, Array<BlendMode>] blend modes to use
|
1161
1236
|
# @param opts [Hash] Set of options
|
1162
|
-
# @option opts [
|
1237
|
+
# @option opts [Array<Integer>] :x x positions of overlay
|
1238
|
+
# @option opts [Array<Integer>] :y y positions of overlay
|
1239
|
+
# @option opts [Vips::Interpretation] :compositing_space Composite images
|
1240
|
+
# in this colour space
|
1163
1241
|
# @option opts [Boolean] :premultiplied Images have premultiplied alpha
|
1164
1242
|
# @return [Image] blended image
|
1165
1243
|
def composite overlay, mode, **opts
|
@@ -1183,9 +1261,9 @@ module Vips
|
|
1183
1261
|
# coordinate of maximum
|
1184
1262
|
def maxpos
|
1185
1263
|
v, opts = max x: true, y: true
|
1186
|
-
x = opts[
|
1187
|
-
y = opts[
|
1188
|
-
|
1264
|
+
x = opts["x"]
|
1265
|
+
y = opts["y"]
|
1266
|
+
[v, x, y]
|
1189
1267
|
end
|
1190
1268
|
|
1191
1269
|
# Return the coordinates of the image minimum.
|
@@ -1194,9 +1272,9 @@ module Vips
|
|
1194
1272
|
# coordinate of minimum
|
1195
1273
|
def minpos
|
1196
1274
|
v, opts = min x: true, y: true
|
1197
|
-
x = opts[
|
1198
|
-
y = opts[
|
1199
|
-
|
1275
|
+
x = opts["x"]
|
1276
|
+
y = opts["y"]
|
1277
|
+
[v, x, y]
|
1200
1278
|
end
|
1201
1279
|
|
1202
1280
|
# a median filter
|
@@ -1204,7 +1282,7 @@ module Vips
|
|
1204
1282
|
# @param size [Integer] size of filter window
|
1205
1283
|
# @return [Image] result of median filter
|
1206
1284
|
def median size = 3
|
1207
|
-
rank size, size,
|
1285
|
+
rank size, size, size**2 / 2
|
1208
1286
|
end
|
1209
1287
|
|
1210
1288
|
# Return the real part of a complex image.
|
@@ -1231,7 +1309,7 @@ module Vips
|
|
1231
1309
|
# @see xyz
|
1232
1310
|
# @return [Image] image converted to polar coordinates
|
1233
1311
|
def polar
|
1234
|
-
Image
|
1312
|
+
Image.run_cmplx(self) { |x| x.complex :polar }
|
1235
1313
|
end
|
1236
1314
|
|
1237
1315
|
# Return an image with polar pixels converted to rectangular.
|
@@ -1244,7 +1322,7 @@ module Vips
|
|
1244
1322
|
# @see xyz
|
1245
1323
|
# @return [Image] image converted to rectangular coordinates
|
1246
1324
|
def rect
|
1247
|
-
Image
|
1325
|
+
Image.run_cmplx(self) { |x| x.complex :rect }
|
1248
1326
|
end
|
1249
1327
|
|
1250
1328
|
# Return the complex conjugate of an image.
|
@@ -1256,7 +1334,7 @@ module Vips
|
|
1256
1334
|
#
|
1257
1335
|
# @return [Image] complex conjugate
|
1258
1336
|
def conj
|
1259
|
-
Image
|
1337
|
+
Image.run_cmplx(self) { |x| x.complex :conj }
|
1260
1338
|
end
|
1261
1339
|
|
1262
1340
|
# Calculate the cross phase of two images.
|
@@ -1437,7 +1515,7 @@ module Vips
|
|
1437
1515
|
#
|
1438
1516
|
# ```
|
1439
1517
|
# $ ruby > methods.rb
|
1440
|
-
# require
|
1518
|
+
# require "vips"; Vips::Yard.generate
|
1441
1519
|
# ^D
|
1442
1520
|
# ```
|
1443
1521
|
|
@@ -1459,7 +1537,7 @@ module Vips
|
|
1459
1537
|
"VipsArrayDouble" => "Array<Double>",
|
1460
1538
|
"VipsArrayInt" => "Array<Integer>",
|
1461
1539
|
"VipsArrayImage" => "Array<Image>",
|
1462
|
-
"VipsArrayString" => "Array<String>"
|
1540
|
+
"VipsArrayString" => "Array<String>"
|
1463
1541
|
}
|
1464
1542
|
|
1465
1543
|
# these have hand-written methods, see above
|
@@ -1470,15 +1548,15 @@ module Vips
|
|
1470
1548
|
|
1471
1549
|
# turn a gtype into a ruby type name
|
1472
1550
|
def self.gtype_to_ruby gtype
|
1473
|
-
fundamental = GObject
|
1474
|
-
type_name = GObject
|
1551
|
+
fundamental = GObject.g_type_fundamental gtype
|
1552
|
+
type_name = GObject.g_type_name gtype
|
1475
1553
|
|
1476
1554
|
if MAP_GO_TO_RUBY.include? type_name
|
1477
1555
|
type_name = MAP_GO_TO_RUBY[type_name]
|
1478
1556
|
end
|
1479
1557
|
|
1480
1558
|
if fundamental == GObject::GFLAGS_TYPE ||
|
1481
|
-
|
1559
|
+
fundamental == GObject::GENUM_TYPE
|
1482
1560
|
type_name = "Vips::" + type_name[/Vips(.*)/, 1]
|
1483
1561
|
end
|
1484
1562
|
|
@@ -1497,7 +1575,7 @@ module Vips
|
|
1497
1575
|
print "# @!method "
|
1498
1576
|
print "self." unless introspect.member_x
|
1499
1577
|
print "#{introspect.name}("
|
1500
|
-
print method_args.map{ |x| x[:yard_name] }.join(", ")
|
1578
|
+
print method_args.map { |x| x[:yard_name] }.join(", ")
|
1501
1579
|
print ", " if method_args.length > 0
|
1502
1580
|
puts "**opts)"
|
1503
1581
|
|
@@ -1517,8 +1595,7 @@ module Vips
|
|
1517
1595
|
gtype = details[:gtype]
|
1518
1596
|
blurb = details[:blurb]
|
1519
1597
|
|
1520
|
-
puts "# @option opts [#{gtype_to_ruby(gtype)}] :#{yard_name} "
|
1521
|
-
"#{blurb}"
|
1598
|
+
puts "# @option opts [#{gtype_to_ruby(gtype)}] :#{yard_name} #{blurb}"
|
1522
1599
|
end
|
1523
1600
|
optional_output.each do |arg_name, details|
|
1524
1601
|
yard_name = details[:yard_name]
|
@@ -1536,14 +1613,14 @@ module Vips
|
|
1536
1613
|
print gtype_to_ruby(required_output.first[:gtype])
|
1537
1614
|
else
|
1538
1615
|
print "Array<"
|
1539
|
-
print required_output.map{ |x| gtype_to_ruby(x[:gtype]) }.join(", ")
|
1616
|
+
print required_output.map { |x| gtype_to_ruby(x[:gtype]) }.join(", ")
|
1540
1617
|
print ">"
|
1541
1618
|
end
|
1542
1619
|
if optional_output.length > 0
|
1543
1620
|
print ", Hash<Symbol => Object>"
|
1544
1621
|
end
|
1545
1622
|
print "] "
|
1546
|
-
print required_output.map{ |x| x[:blurb] }.join(", ")
|
1623
|
+
print required_output.map { |x| x[:blurb] }.join(", ")
|
1547
1624
|
if optional_output.length > 0
|
1548
1625
|
print ", " if required_output.length > 0
|
1549
1626
|
print "Hash of optional output items"
|
@@ -1555,16 +1632,16 @@ module Vips
|
|
1555
1632
|
|
1556
1633
|
def self.generate
|
1557
1634
|
alias_gtypes = {}
|
1558
|
-
ALIAS.each do |name|
|
1559
|
-
gtype = Vips
|
1560
|
-
alias_gtypes[gtype] = name
|
1635
|
+
ALIAS.each do |name|
|
1636
|
+
gtype = Vips.type_find "VipsOperation", name
|
1637
|
+
alias_gtypes[gtype] = name
|
1561
1638
|
end
|
1562
1639
|
|
1563
1640
|
generate_class = lambda do |gtype, _|
|
1564
|
-
if alias_gtypes.key? gtype
|
1565
|
-
|
1641
|
+
name = if alias_gtypes.key? gtype
|
1642
|
+
alias_gtypes[gtype]
|
1566
1643
|
else
|
1567
|
-
|
1644
|
+
Vips.nickname_find gtype
|
1568
1645
|
end
|
1569
1646
|
|
1570
1647
|
if name
|
@@ -1578,14 +1655,14 @@ module Vips
|
|
1578
1655
|
generate_operation(introspect) if introspect
|
1579
1656
|
end
|
1580
1657
|
|
1581
|
-
Vips
|
1658
|
+
Vips.vips_type_map gtype, generate_class, nil
|
1582
1659
|
end
|
1583
1660
|
|
1584
1661
|
puts "module Vips"
|
1585
1662
|
puts " class Image"
|
1586
1663
|
puts ""
|
1587
1664
|
|
1588
|
-
generate_class.(GObject
|
1665
|
+
generate_class.call(GObject.g_type_from_name("VipsOperation"), nil)
|
1589
1666
|
|
1590
1667
|
puts " end"
|
1591
1668
|
puts "end"
|