ruby-vips 2.1.0 → 2.1.4
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/CHANGELOG.md +20 -0
- data/README.md +22 -16
- data/TODO +2 -3
- data/VERSION +1 -1
- data/example/inheritance_with_refcount.rb +11 -3
- data/lib/vips/image.rb +132 -26
- data/lib/vips/methods.rb +334 -218
- data/lib/vips/mutableimage.rb +23 -4
- data/lib/vips/object.rb +4 -10
- data/lib/vips/operation.rb +15 -1
- data/lib/vips/version.rb +1 -1
- data/lib/vips.rb +8 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff74e4e7a8b781e9fd56602fddc00adaa0355276532821a953bac3175e649534
|
4
|
+
data.tar.gz: 199957dacc1c47208a5d8a379080b76676fe3f98ba684a76fdbe5e08370d535b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d585d3440f75759e1c07cefd6d43371db62706e0c2e9ada3512f661870f7f4c410d6dbeed138c45e16438112cc8179bae2d4477c318ac6fcf9e31487822cb63
|
7
|
+
data.tar.gz: a62254d063cd35b521e74a86377d3e83d2b2345a10186e044b2e91992bc6ff49611d6bde916cd8c530d0b2ba4da7ba4a23ca10c922be99463ab71371538cf1cf
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,26 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## Version 2.1.4 (2021-10-28)
|
6
|
+
|
7
|
+
* `write_to_buffer` tries to use the new target API, then falls back to the old
|
8
|
+
buffer system [jcupitt]
|
9
|
+
* don't generate yard docs for deprecated args [jcupitt]
|
10
|
+
* add hyperbolic trig functions [jcupitt]
|
11
|
+
|
12
|
+
## Version 2.1.3 (2021-8-23)
|
13
|
+
|
14
|
+
* fix a gtype size error on win64 [danini-the-panini]
|
15
|
+
|
16
|
+
## Version 2.1.2 (2021-5-3)
|
17
|
+
|
18
|
+
* allow `FFI::Pointer` as an argument to `new_from_memory` etc. [sled]
|
19
|
+
|
20
|
+
## Version 2.1.1 (2021-5-3)
|
21
|
+
|
22
|
+
* fix "mutate" with libvips 8.9 [jcupitt]
|
23
|
+
* update autodocs for libvips 8.11 [jcupitt]
|
24
|
+
|
5
25
|
## Version 2.1.0 (2021-3-8)
|
6
26
|
|
7
27
|
* add "mutate" system [jcupitt]
|
data/README.md
CHANGED
@@ -6,12 +6,13 @@
|
|
6
6
|
This gem is a Ruby binding for the [libvips image processing
|
7
7
|
library](https://libvips.github.io/libvips).
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
image
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
libvips is a [demand-driven, horizontally
|
10
|
+
threaded](https://github.com/libvips/libvips/wiki/Why-is-libvips-quick)
|
11
|
+
image processing library. Compared to similar
|
12
|
+
libraries, [libvips runs quickly and uses little
|
13
|
+
memory](https://github.com/libvips/libvips/wiki/Speed-and-memory-use).
|
14
|
+
libvips is licensed under the [LGPL
|
15
|
+
2.1+](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html).
|
15
16
|
|
16
17
|
## Requirements
|
17
18
|
|
@@ -25,7 +26,7 @@ and because it doesn't need to keep entire images in memory, it's light.
|
|
25
26
|
|
26
27
|
## Install
|
27
28
|
|
28
|
-
|
29
|
+
[Install libvips](https://libvips.github.io/libvips/install.html), then:
|
29
30
|
|
30
31
|
```
|
31
32
|
$ gem install ruby-vips
|
@@ -40,7 +41,7 @@ gem "ruby-vips"
|
|
40
41
|
On Windows, you'll need to set the `RUBY_DLL_PATH` environment variable to
|
41
42
|
point to the libvips bin directory.
|
42
43
|
|
43
|
-
|
44
|
+
## Example
|
44
45
|
|
45
46
|
```ruby
|
46
47
|
require "vips"
|
@@ -67,19 +68,24 @@ im = im.conv mask, precision: :integer
|
|
67
68
|
im.write_to_file output_filename
|
68
69
|
```
|
69
70
|
|
70
|
-
|
71
|
+
## Documentation
|
72
|
+
|
73
|
+
There are [full API docs for ruby-vips on
|
74
|
+
rubydoc](https://www.rubydoc.info/gems/ruby-vips). This sometimes has issues
|
75
|
+
updating, so we have a [copy on the gh-pages for this site as
|
76
|
+
well](http://libvips.github.io/ruby-vips), which
|
77
|
+
should always work.
|
78
|
+
|
79
|
+
See the `Vips` section in the docs for a [tutorial introduction with
|
71
80
|
examples](https://www.rubydoc.info/gems/ruby-vips/Vips).
|
72
81
|
|
73
|
-
|
74
|
-
|
75
|
-
reference manual](https://libvips.github.io/libvips/API/current/) has a
|
76
|
-
complete explanation of every method.
|
82
|
+
The [libvips reference manual](https://libvips.github.io/libvips/API/current/)
|
83
|
+
has a complete explanation of every method.
|
77
84
|
|
78
|
-
The
|
79
|
-
[`example/`](https://github.com/libvips/ruby-vips/tree/master/example)
|
85
|
+
The [`example/`](https://github.com/libvips/ruby-vips/tree/master/example)
|
80
86
|
directory has some simple example programs.
|
81
87
|
|
82
|
-
|
88
|
+
## Benchmarks
|
83
89
|
|
84
90
|
The benchmark at [vips-benchmarks](https://github.com/jcupitt/vips-benchmarks)
|
85
91
|
loads a large image, crops, shrinks, sharpens and saves again, and repeats
|
data/TODO
CHANGED
@@ -37,9 +37,8 @@
|
|
37
37
|
|
38
38
|
- Push new gem to rubygems, tag repository with version.
|
39
39
|
|
40
|
-
|
40
|
+
gem signin --otp 111111
|
41
41
|
bundle exec rake release
|
42
42
|
|
43
|
-
|
44
|
-
press return and the upload should work.
|
43
|
+
The otp is from authy / google authenticator / etc.
|
45
44
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.1.
|
1
|
+
2.1.4
|
@@ -132,8 +132,12 @@ module GLib
|
|
132
132
|
end
|
133
133
|
end
|
134
134
|
|
135
|
-
#
|
136
|
-
|
135
|
+
# we can't just use ulong, windows has different int sizing rules
|
136
|
+
if FFI::Platform::ADDRESS_SIZE == 64
|
137
|
+
typedef :uint64, :GType
|
138
|
+
else
|
139
|
+
typedef :uint32, :GType
|
140
|
+
end
|
137
141
|
end
|
138
142
|
|
139
143
|
module Vips
|
@@ -144,7 +148,11 @@ module Vips
|
|
144
148
|
GLib.set_log_domain(LOG_DOMAIN)
|
145
149
|
|
146
150
|
# need to repeat this
|
147
|
-
|
151
|
+
if FFI::Platform::ADDRESS_SIZE == 64
|
152
|
+
typedef :uint64, :GType
|
153
|
+
else
|
154
|
+
typedef :uint32, :GType
|
155
|
+
end
|
148
156
|
|
149
157
|
attach_function :vips_init, [:string], :int
|
150
158
|
attach_function :vips_shutdown, [], :void
|
data/lib/vips/image.rb
CHANGED
@@ -78,6 +78,11 @@ module Vips
|
|
78
78
|
class Image < Vips::Object
|
79
79
|
alias_method :parent_get_typeof, :get_typeof
|
80
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
|
+
|
81
86
|
private
|
82
87
|
|
83
88
|
# the layout of the VipsImage struct
|
@@ -326,6 +331,24 @@ module Vips
|
|
326
331
|
# image.width, image.height, image.bands, image.format
|
327
332
|
# ```
|
328
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
|
+
#
|
329
352
|
# {new_from_memory} keeps a reference to the array of pixels you pass in
|
330
353
|
# to try to prevent that memory from being freed by the Ruby GC while it
|
331
354
|
# is being used.
|
@@ -340,13 +363,23 @@ module Vips
|
|
340
363
|
# @param format [Symbol] band format
|
341
364
|
# @return [Image] the loaded image
|
342
365
|
def self.new_from_memory data, width, height, bands, format
|
343
|
-
size = data.bytesize
|
344
|
-
|
345
366
|
# prevent data from being freed with JRuby FFI
|
346
367
|
if defined?(JRUBY_VERSION) && !data.is_a?(FFI::Pointer)
|
347
368
|
data = ::FFI::MemoryPointer.new(:char, data.bytesize).write_bytes data
|
348
369
|
end
|
349
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
|
+
|
350
383
|
format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format
|
351
384
|
vi = Vips.vips_image_new_from_memory data, size,
|
352
385
|
width, height, bands, format_number
|
@@ -373,7 +406,17 @@ module Vips
|
|
373
406
|
# @return [Image] the loaded image
|
374
407
|
def self.new_from_memory_copy data, width, height, bands, format
|
375
408
|
format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format
|
376
|
-
|
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,
|
377
420
|
width, height, bands, format_number
|
378
421
|
raise Vips::Error if vi.null?
|
379
422
|
new(vi)
|
@@ -506,7 +549,7 @@ module Vips
|
|
506
549
|
pixel = (Vips::Image.black(1, 1) + value).cast(format)
|
507
550
|
image = pixel.embed 0, 0, width, height, extend: :copy
|
508
551
|
image.copy interpretation: interpretation, xres: xres, yres: yres,
|
509
|
-
|
552
|
+
xoffset: xoffset, yoffset: yoffset
|
510
553
|
end
|
511
554
|
|
512
555
|
# Write this image to a file. Save options may be encoded in the
|
@@ -580,11 +623,27 @@ module Vips
|
|
580
623
|
raise Vips::Error, "filename is nil" if format_string.nil?
|
581
624
|
filename = Vips.p2str(Vips.vips_filename_get_filename(format_string))
|
582
625
|
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?
|
585
626
|
|
586
|
-
|
587
|
-
|
627
|
+
# try to save with the new target API first, only fall back to the old
|
628
|
+
# buffer API if there's no target save for this filetype
|
629
|
+
saver = nil
|
630
|
+
if Vips.at_least_libvips?(8, 9)
|
631
|
+
Vips.vips_error_freeze
|
632
|
+
saver = Vips.vips_foreign_find_save_target filename
|
633
|
+
Vips.vips_error_thaw
|
634
|
+
end
|
635
|
+
|
636
|
+
if !saver.nil?
|
637
|
+
target = Vips::Target.new_to_memory
|
638
|
+
Vips::Operation.call saver, [self, target], opts, option_string
|
639
|
+
buffer = target.get("blob")
|
640
|
+
else
|
641
|
+
saver = Vips.vips_foreign_find_save_buffer filename
|
642
|
+
raise Vips::Error if saver.nil?
|
643
|
+
|
644
|
+
buffer = Vips::Operation.call saver, [self], opts, option_string
|
645
|
+
raise Vips::Error if buffer.nil?
|
646
|
+
end
|
588
647
|
|
589
648
|
write_gc
|
590
649
|
|
@@ -1129,14 +1188,10 @@ module Vips
|
|
1129
1188
|
end
|
1130
1189
|
end
|
1131
1190
|
|
1132
|
-
# Convert to an
|
1191
|
+
# Convert to an Enumerator. Similar to `#to_a` but lazier.
|
1133
1192
|
#
|
1134
|
-
# @return [
|
1135
|
-
def
|
1136
|
-
# we render the image to a big string, then unpack
|
1137
|
-
# as a Ruby array of the correct type
|
1138
|
-
memory = write_to_memory
|
1139
|
-
|
1193
|
+
# @return [Enumerator] Enumerator of Enumerators of Arrays of Numerics
|
1194
|
+
def to_enum
|
1140
1195
|
# make the template for unpack
|
1141
1196
|
template = {
|
1142
1197
|
char: "c",
|
@@ -1151,14 +1206,22 @@ module Vips
|
|
1151
1206
|
dpcomplex: "d"
|
1152
1207
|
}[format] + "*"
|
1153
1208
|
|
1154
|
-
#
|
1155
|
-
array
|
1209
|
+
# we render the image to a big string, then unpack into
|
1210
|
+
# one-dimensional array as a Ruby array of the correct type
|
1211
|
+
array = write_to_memory.unpack template
|
1156
1212
|
|
1157
|
-
# gather
|
1158
|
-
pixel_array = array.each_slice
|
1213
|
+
# gather bands of a pixel together
|
1214
|
+
pixel_array = array.each_slice bands
|
1159
1215
|
|
1160
|
-
#
|
1161
|
-
pixel_array.each_slice
|
1216
|
+
# gather pixels of a row together
|
1217
|
+
pixel_array.each_slice width
|
1218
|
+
end
|
1219
|
+
|
1220
|
+
# Convert to an Array. This will be slow for large images.
|
1221
|
+
#
|
1222
|
+
# @return [Array] Array of Arrays of Arrays of Numerics
|
1223
|
+
def to_a
|
1224
|
+
to_enum.to_a
|
1162
1225
|
end
|
1163
1226
|
|
1164
1227
|
# Return the largest integral value not greater than the argument.
|
@@ -1387,6 +1450,48 @@ module Vips
|
|
1387
1450
|
math :atan
|
1388
1451
|
end
|
1389
1452
|
|
1453
|
+
# Return the hyperbolic sine of an image in radians.
|
1454
|
+
#
|
1455
|
+
# @return [Image] sine of each pixel
|
1456
|
+
def sinh
|
1457
|
+
math :sinh
|
1458
|
+
end
|
1459
|
+
|
1460
|
+
# Return the hyperbolic cosine of an image in radians.
|
1461
|
+
#
|
1462
|
+
# @return [Image] cosine of each pixel
|
1463
|
+
def cosh
|
1464
|
+
math :cosh
|
1465
|
+
end
|
1466
|
+
|
1467
|
+
# Return the hyperbolic tangent of an image in radians.
|
1468
|
+
#
|
1469
|
+
# @return [Image] tangent of each pixel
|
1470
|
+
def tanh
|
1471
|
+
math :tanh
|
1472
|
+
end
|
1473
|
+
|
1474
|
+
# Return the inverse hyperbolic sine of an image in radians.
|
1475
|
+
#
|
1476
|
+
# @return [Image] inverse sine of each pixel
|
1477
|
+
def asinh
|
1478
|
+
math :asinh
|
1479
|
+
end
|
1480
|
+
|
1481
|
+
# Return the inverse hyperbolic cosine of an image in radians.
|
1482
|
+
#
|
1483
|
+
# @return [Image] inverse cosine of each pixel
|
1484
|
+
def acosh
|
1485
|
+
math :acosh
|
1486
|
+
end
|
1487
|
+
|
1488
|
+
# Return the inverse hyperbolic tangent of an image in radians.
|
1489
|
+
#
|
1490
|
+
# @return [Image] inverse tangent of each pixel
|
1491
|
+
def atanh
|
1492
|
+
math :atanh
|
1493
|
+
end
|
1494
|
+
|
1390
1495
|
# Return the natural log of an image.
|
1391
1496
|
#
|
1392
1497
|
# @return [Image] natural log of each pixel
|
@@ -1569,8 +1674,8 @@ module Vips
|
|
1569
1674
|
|
1570
1675
|
method_args = introspect.method_args
|
1571
1676
|
required_output = introspect.required_output
|
1572
|
-
optional_input = introspect.
|
1573
|
-
optional_output = introspect.
|
1677
|
+
optional_input = introspect.doc_optional_input
|
1678
|
+
optional_output = introspect.doc_optional_output
|
1574
1679
|
|
1575
1680
|
print "# @!method "
|
1576
1681
|
print "self." unless introspect.member_x
|
@@ -1593,17 +1698,18 @@ module Vips
|
|
1593
1698
|
optional_input.each do |arg_name, details|
|
1594
1699
|
yard_name = details[:yard_name]
|
1595
1700
|
gtype = details[:gtype]
|
1701
|
+
rtype = gtype_to_ruby gtype
|
1596
1702
|
blurb = details[:blurb]
|
1597
1703
|
|
1598
|
-
puts "# @option opts [#{
|
1704
|
+
puts "# @option opts [#{rtype}] :#{yard_name} #{blurb}"
|
1599
1705
|
end
|
1600
1706
|
optional_output.each do |arg_name, details|
|
1601
1707
|
yard_name = details[:yard_name]
|
1602
1708
|
gtype = details[:gtype]
|
1709
|
+
rtype = gtype_to_ruby gtype
|
1603
1710
|
blurb = details[:blurb]
|
1604
1711
|
|
1605
|
-
|
1606
|
-
puts " Output #{blurb}"
|
1712
|
+
puts "# @option opts [#{rtype}] :#{yard_name} Output #{blurb}"
|
1607
1713
|
end
|
1608
1714
|
|
1609
1715
|
print "# @return ["
|