ruby-vips 2.0.16 → 2.0.17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +1 -1
- data/.travis.yml +1 -6
- data/CHANGELOG.md +11 -0
- data/README.md +38 -37
- data/TODO +1 -1
- data/VERSION +1 -1
- data/example/connection.rb +17 -0
- data/example/progress.rb +30 -0
- data/lib/vips.rb +64 -4
- data/lib/vips/connection.rb +46 -0
- data/lib/vips/gobject.rb +9 -1
- data/lib/vips/gvalue.rb +13 -4
- data/lib/vips/image.rb +213 -112
- data/lib/vips/methods.rb +330 -40
- data/lib/vips/object.rb +123 -5
- data/lib/vips/operation.rb +156 -80
- data/lib/vips/region.rb +2 -2
- data/lib/vips/source.rb +89 -0
- data/lib/vips/sourcecustom.rb +90 -0
- data/lib/vips/target.rb +87 -0
- data/lib/vips/targetcustom.rb +78 -0
- data/lib/vips/version.rb +1 -1
- data/ruby-vips.gemspec +3 -1
- metadata +14 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e63754294a1cbf0c65135dca3b377085616a6e386fb75d6442937fccb9c4c5a
|
4
|
+
data.tar.gz: d885bef5779402c0fbdc100635d8f26794d4d7394c97ac4eb1829343aaa5d636
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c52c6e54dc34dba9d01eb39dafc9e8d4132f3242d0a30ec89ea661c0b6d1be424ba6287398f13e697069e3a3d0f07e175f28f2f0f0b51caaed9cea8dc21aeee
|
7
|
+
data.tar.gz: 72e1116ca589860cbe30a3f6b89a7ca07a9d594b2be972a1cedad779a255a8d9418c5f9d472c90c1be63e76e518972d2ad48c73d31472aa8cf070ce668f29050
|
data/.rubocop_todo.yml
CHANGED
data/.travis.yml
CHANGED
@@ -45,6 +45,7 @@ rvm:
|
|
45
45
|
- 2.4
|
46
46
|
- 2.5
|
47
47
|
- 2.6
|
48
|
+
- 2.7
|
48
49
|
|
49
50
|
script: bundle exec rake spec
|
50
51
|
|
@@ -54,9 +55,3 @@ gemfile:
|
|
54
55
|
before_install:
|
55
56
|
- uname -a
|
56
57
|
- bash install-vips.sh
|
57
|
-
|
58
|
-
jobs:
|
59
|
-
include:
|
60
|
-
- stage: Lint
|
61
|
-
rvm: 2.6
|
62
|
-
script: bundle exec rake rubocop
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,17 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## Version 2.0.17 (2019-10-29)
|
6
|
+
|
7
|
+
* install msys2 libvips on Windows [larskanis]
|
8
|
+
* better `-` to `_` conversion [Nakilon]
|
9
|
+
* fix `GValue#set` for stricter metadata rules in 8.9 [jcupitt]
|
10
|
+
* fix a ref leak on operation build error [jcupitt]
|
11
|
+
* faster operation call [jcupitt]
|
12
|
+
* add support for VipsConnection [jcupitt]
|
13
|
+
* add `signal_connect` [jcupitt]
|
14
|
+
* add `Image#set_kill` for progress termination [jcupitt]
|
15
|
+
|
5
16
|
## Version 2.0.16 (2019-9-21)
|
6
17
|
|
7
18
|
* better library name generation [renchap]
|
data/README.md
CHANGED
@@ -3,35 +3,15 @@
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/ruby-vips.svg)](https://badge.fury.io/rb/ruby-vips)
|
4
4
|
[![Build Status](https://travis-ci.org/libvips/ruby-vips.svg?branch=master)](https://travis-ci.org/libvips/ruby-vips)
|
5
5
|
|
6
|
-
This gem
|
6
|
+
This gem is a Ruby binding for the [libvips image processing
|
7
7
|
library](https://libvips.github.io/libvips).
|
8
8
|
|
9
|
-
Programs that use `ruby-vips` don't
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
Because `ruby-vips` is parallel, it's quick, and because it doesn't need to
|
16
|
-
keep entire images in memory, it's light. For example, the benchmark at
|
17
|
-
[vips-benchmarks](https://github.com/jcupitt/vips-benchmarks) loads a
|
18
|
-
large image, crops, shrinks, sharpens and saves again, and repeats 10 times.
|
19
|
-
|
20
|
-
```text
|
21
|
-
real time in seconds, fastest of five runs
|
22
|
-
benchmark tiff jpeg
|
23
|
-
ruby-vips.rb 0.85 0.78
|
24
|
-
image-magick 2.03 2.44
|
25
|
-
rmagick.rb 3.87 3.89
|
26
|
-
|
27
|
-
peak memory use in kb
|
28
|
-
benchmark peak RES
|
29
|
-
ruby-vips.rb 43864
|
30
|
-
rmagick.rb 788768
|
31
|
-
```
|
32
|
-
|
33
|
-
See also [benchmarks at the official libvips
|
34
|
-
website](https://github.com/libvips/libvips/wiki/Speed-and-memory-use).
|
9
|
+
Programs that use `ruby-vips` don't manipulate images directly, instead
|
10
|
+
they create pipelines of image processing operations building on a source
|
11
|
+
image. When the end of the pipe is connected to a destination, the whole
|
12
|
+
pipeline executes at once, streaming the image in parallel from source to
|
13
|
+
destination a section at a time. Because `ruby-vips` is parallel, it's quick,
|
14
|
+
and because it doesn't need to keep entire images in memory, it's light.
|
35
15
|
|
36
16
|
## Requirements
|
37
17
|
|
@@ -60,9 +40,6 @@ gem 'ruby-vips'
|
|
60
40
|
On Windows, you'll need to set the `RUBY_DLL_PATH` environment variable to
|
61
41
|
point to the libvips bin directory.
|
62
42
|
|
63
|
-
Take a look in `examples/`. There is [full API
|
64
|
-
documentation](http://www.rubydoc.info/gems/ruby-vips).
|
65
|
-
|
66
43
|
# Example
|
67
44
|
|
68
45
|
```ruby
|
@@ -90,13 +67,37 @@ im = im.conv mask, precision: :integer
|
|
90
67
|
im.write_to_file output_filename
|
91
68
|
```
|
92
69
|
|
93
|
-
|
70
|
+
The `Vips` section in the API docs has a [tutorial introduction with
|
71
|
+
examples](https://www.rubydoc.info/gems/ruby-vips/Vips).
|
94
72
|
|
95
|
-
|
73
|
+
ruby-vips has [API
|
74
|
+
documentation](http://www.rubydoc.info/gems/ruby-vips). The [libvips
|
75
|
+
reference manual](https://libvips.github.io/libvips/API/current/) has a
|
76
|
+
complete explanation of every method.
|
96
77
|
|
97
|
-
The
|
98
|
-
|
78
|
+
The
|
79
|
+
[`example/`](https://github.com/libvips/ruby-vips/tree/master/example)
|
80
|
+
directory has some simple example programs.
|
81
|
+
|
82
|
+
# Benchmarks
|
83
|
+
|
84
|
+
The benchmark at [vips-benchmarks](https://github.com/jcupitt/vips-benchmarks)
|
85
|
+
loads a large image, crops, shrinks, sharpens and saves again, and repeats
|
86
|
+
10 times.
|
87
|
+
|
88
|
+
```text
|
89
|
+
real time in seconds, fastest of five runs
|
90
|
+
benchmark tiff jpeg
|
91
|
+
ruby-vips.rb 0.85 0.78
|
92
|
+
image-magick 2.03 2.44
|
93
|
+
rmagick.rb 3.87 3.89
|
94
|
+
|
95
|
+
peak memory use in kb
|
96
|
+
benchmark peak RES
|
97
|
+
ruby-vips.rb 43864
|
98
|
+
rmagick.rb 788768
|
99
|
+
```
|
100
|
+
|
101
|
+
See also [benchmarks at the official libvips
|
102
|
+
website](https://github.com/libvips/libvips/wiki/Speed-and-memory-use).
|
99
103
|
|
100
|
-
The `1.0-stable` branch is based on `gobject-introspection` rather than
|
101
|
-
`ffi`. It supports the same API as the current version, but is harder to
|
102
|
-
install, less portable, slower, and less stable.
|
data/TODO
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.0.
|
1
|
+
2.0.17
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'vips'
|
4
|
+
|
5
|
+
file = File.open ARGV[0], "rb"
|
6
|
+
source = Vips::SourceCustom.new
|
7
|
+
source.on_read { |length| file.read length }
|
8
|
+
# this method is optional
|
9
|
+
# source.on_seek { |offset, whence| file.seek(offset, whence) }
|
10
|
+
|
11
|
+
dest = File.open ARGV[1], "wb"
|
12
|
+
target = Vips::TargetCustom.new
|
13
|
+
target.on_write { |chunk| dest.write(chunk) }
|
14
|
+
target.on_finish { dest.close }
|
15
|
+
|
16
|
+
image = Vips::Image.new_from_source source, "", access: :sequential
|
17
|
+
image.write_to_target target, ".png"
|
data/example/progress.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'vips'
|
4
|
+
|
5
|
+
image = Vips::Image.black 1, 100000
|
6
|
+
image.set_progress true
|
7
|
+
|
8
|
+
def progress_to_s(name, progress)
|
9
|
+
puts "#{name}:"
|
10
|
+
puts " progress.run = #{progress[:run]}"
|
11
|
+
puts " progress.eta = #{progress[:eta]}"
|
12
|
+
puts " progress.tpels = #{progress[:tpels]}"
|
13
|
+
puts " progress.npels = #{progress[:npels]}"
|
14
|
+
puts " progress.percent = #{progress[:percent]}"
|
15
|
+
end
|
16
|
+
|
17
|
+
image.signal_connect :preeval do |progress|
|
18
|
+
progress_to_s("preeval", progress)
|
19
|
+
end
|
20
|
+
|
21
|
+
image.signal_connect :eval do |progress|
|
22
|
+
progress_to_s("eval", progress)
|
23
|
+
image.set_kill(true) if progress[:percent] > 50
|
24
|
+
end
|
25
|
+
|
26
|
+
image.signal_connect :posteval do |progress|
|
27
|
+
progress_to_s("posteval", progress)
|
28
|
+
end
|
29
|
+
|
30
|
+
image.avg
|
data/lib/vips.rb
CHANGED
@@ -166,7 +166,7 @@ require 'vips/gobject'
|
|
166
166
|
require 'vips/gvalue'
|
167
167
|
|
168
168
|
# This module provides a binding for the [libvips image processing
|
169
|
-
# library](https://
|
169
|
+
# library](https://libvips.github.io/libvips/).
|
170
170
|
#
|
171
171
|
# # Example
|
172
172
|
#
|
@@ -212,6 +212,9 @@ require 'vips/gvalue'
|
|
212
212
|
# memory buffers, create images that wrap C-style memory arrays, or make images
|
213
213
|
# from constants.
|
214
214
|
#
|
215
|
+
# Use {Source} and {Image.new_from_source} to load images from any data
|
216
|
+
# source, for example URIs.
|
217
|
+
#
|
215
218
|
# The next line:
|
216
219
|
#
|
217
220
|
# ```ruby
|
@@ -253,6 +256,9 @@ require 'vips/gvalue'
|
|
253
256
|
# suffix. You can also write formatted images to memory buffers, or dump
|
254
257
|
# image data to a raw memory array.
|
255
258
|
#
|
259
|
+
# Use {Target} and {Image#write_to_target} to write formatted images to
|
260
|
+
# any data sink, for example URIs.
|
261
|
+
#
|
256
262
|
# # How it works
|
257
263
|
#
|
258
264
|
# The binding uses [ruby-ffi](https://github.com/ffi/ffi) to open the libvips
|
@@ -404,12 +410,12 @@ require 'vips/gvalue'
|
|
404
410
|
# # Automatic YARD documentation
|
405
411
|
#
|
406
412
|
# The bulk of these API docs are generated automatically by
|
407
|
-
# {Vips::
|
413
|
+
# {Vips::Yard::generate}. It examines
|
408
414
|
# libvips and writes a summary of each operation and the arguments and options
|
409
415
|
# that that operation expects.
|
410
416
|
#
|
411
417
|
# Use the [C API
|
412
|
-
# docs](https://
|
418
|
+
# docs](https://libvips.github.io/libvips/API/current)
|
413
419
|
# for more detail.
|
414
420
|
#
|
415
421
|
# # Enums
|
@@ -434,6 +440,55 @@ require 'vips/gvalue'
|
|
434
440
|
# If you want to avoid the copies, you'll need to call drawing operations
|
435
441
|
# yourself.
|
436
442
|
#
|
443
|
+
# # Progress
|
444
|
+
#
|
445
|
+
# You can attach signal handlers to images to watch computation progress. For
|
446
|
+
# example:
|
447
|
+
#
|
448
|
+
# ```ruby
|
449
|
+
# image = Vips::Image.black 1, 100000
|
450
|
+
# image.set_progress true
|
451
|
+
#
|
452
|
+
# def progress_to_s(name, progress)
|
453
|
+
# puts "#{name}:"
|
454
|
+
# puts " run = #{progress[:run]}"
|
455
|
+
# puts " eta = #{progress[:eta]}"
|
456
|
+
# puts " tpels = #{progress[:tpels]}"
|
457
|
+
# puts " npels = #{progress[:npels]}"
|
458
|
+
# puts " percent = #{progress[:percent]}"
|
459
|
+
# end
|
460
|
+
#
|
461
|
+
# image.signal_connect :preeval do |progress|
|
462
|
+
# progress_to_s("preeval", progress)
|
463
|
+
# end
|
464
|
+
#
|
465
|
+
# image.signal_connect :eval do |progress|
|
466
|
+
# progress_to_s("eval", progress)
|
467
|
+
# image.set_kill(true) if progress[:percent] > 50
|
468
|
+
# end
|
469
|
+
#
|
470
|
+
# image.signal_connect :posteval do |progress|
|
471
|
+
# progress_to_s("posteval", progress)
|
472
|
+
# end
|
473
|
+
#
|
474
|
+
# image.avg
|
475
|
+
# ```
|
476
|
+
#
|
477
|
+
# The `:eval` signal will fire for every tile that is processed. You can stop
|
478
|
+
# progress with {Image#set_kill} and processing will end with an exception.
|
479
|
+
#
|
480
|
+
# User streams
|
481
|
+
#
|
482
|
+
# You can make your own input and output stream objects with {SourceCustom} and
|
483
|
+
# {TargetCustom}. For example:
|
484
|
+
#
|
485
|
+
# ```ruby
|
486
|
+
# file = File.open "some/file", "rb"
|
487
|
+
# source = Vips::SourceCustom.new
|
488
|
+
# source.on_read { |length| file.read length }
|
489
|
+
# image = Vips::Image.new_from_source source, "", access: "sequential"
|
490
|
+
# ```
|
491
|
+
#
|
437
492
|
# # Overloads
|
438
493
|
#
|
439
494
|
# The wrapper defines the usual set of arithmetic, boolean and relational
|
@@ -614,7 +669,7 @@ module Vips
|
|
614
669
|
LIBRARY_VERSION = Vips::version_string
|
615
670
|
|
616
671
|
# libvips has this arbitrary number as a sanity-check upper bound on image
|
617
|
-
# size. It's sometimes useful
|
672
|
+
# size. It's sometimes useful to know when calculating scale factors.
|
618
673
|
MAX_COORD = 10000000
|
619
674
|
end
|
620
675
|
|
@@ -624,3 +679,8 @@ require 'vips/image'
|
|
624
679
|
require 'vips/interpolate'
|
625
680
|
require 'vips/region'
|
626
681
|
require 'vips/version'
|
682
|
+
require 'vips/connection'
|
683
|
+
require 'vips/source'
|
684
|
+
require 'vips/sourcecustom'
|
685
|
+
require 'vips/target'
|
686
|
+
require 'vips/targetcustom'
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# This module provides an interface to the top level bits of libvips
|
2
|
+
# via ruby-ffi.
|
3
|
+
#
|
4
|
+
# Author:: John Cupitt (mailto:jcupitt@gmail.com)
|
5
|
+
# License:: MIT
|
6
|
+
|
7
|
+
require 'ffi'
|
8
|
+
|
9
|
+
module Vips
|
10
|
+
if Vips::at_least_libvips?(8, 9)
|
11
|
+
attach_function :vips_connection_filename, [:pointer], :string
|
12
|
+
attach_function :vips_connection_nick, [:pointer], :string
|
13
|
+
end
|
14
|
+
|
15
|
+
# Abstract base class for connections.
|
16
|
+
class Connection < Vips::Object
|
17
|
+
# The layout of the VipsRegion struct.
|
18
|
+
module ConnectionLayout
|
19
|
+
def self.included(base)
|
20
|
+
base.class_eval do
|
21
|
+
layout :parent, Vips::Object::Struct
|
22
|
+
# rest opaque
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Struct < Vips::Object::Struct
|
28
|
+
include ConnectionLayout
|
29
|
+
end
|
30
|
+
|
31
|
+
class ManagedStruct < Vips::Object::ManagedStruct
|
32
|
+
include ConnectionLayout
|
33
|
+
end
|
34
|
+
|
35
|
+
# Get any filename associated with a connection, or nil.
|
36
|
+
def filename
|
37
|
+
Vips::vips_connection_filename self
|
38
|
+
end
|
39
|
+
|
40
|
+
# Get a nickname (short description) of a connection that could be shown to
|
41
|
+
# the user.
|
42
|
+
def nick
|
43
|
+
Vips::vips_connection_nick self
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/vips/gobject.rb
CHANGED
@@ -73,6 +73,9 @@ module GObject
|
|
73
73
|
def initialize ptr
|
74
74
|
# GLib::logger.debug("GObject::GObject.initialize") {"ptr = #{ptr}"}
|
75
75
|
@struct = ffi_managed_struct.new ptr
|
76
|
+
|
77
|
+
# sometimes we need to keep refs across C calls ... hide them here
|
78
|
+
@references = []
|
76
79
|
end
|
77
80
|
|
78
81
|
# access to the casting struct for this class
|
@@ -111,8 +114,13 @@ module GObject
|
|
111
114
|
layout :value, GParamSpec.ptr
|
112
115
|
end
|
113
116
|
|
114
|
-
attach_function :g_param_spec_get_blurb, [
|
117
|
+
attach_function :g_param_spec_get_blurb, [:pointer], :string
|
115
118
|
|
116
119
|
attach_function :g_object_ref, [:pointer], :void
|
117
120
|
attach_function :g_object_unref, [:pointer], :void
|
121
|
+
|
122
|
+
# we just use one gcallback type for every signal, hopefully this is OK
|
123
|
+
callback :gcallback, [:pointer], :void
|
124
|
+
attach_function :g_signal_connect_data,
|
125
|
+
[:pointer, :string, :gcallback, :pointer, :pointer, :int], :long
|
118
126
|
end
|
data/lib/vips/gvalue.rb
CHANGED
@@ -13,6 +13,8 @@ module GObject
|
|
13
13
|
# gvalue.init GObject::GDOUBLE_TYPE
|
14
14
|
# gvalue.set 3.1415
|
15
15
|
# value = gvalue.get
|
16
|
+
# # optional -- drop any ref the gvalue had
|
17
|
+
# gvalue.unset
|
16
18
|
# ```
|
17
19
|
#
|
18
20
|
# Lifetime is managed automatically. It doesn't know about all GType values,
|
@@ -25,12 +27,11 @@ module GObject
|
|
25
27
|
# convert an enum value (str/symb/int) into an int ready for libvips
|
26
28
|
def self.from_nick(gtype, value)
|
27
29
|
value = value.to_s if value.is_a? Symbol
|
28
|
-
# libvips expects "-" as a separator in enum names, but "_" is more
|
29
|
-
# convenient for ruby, eg. :b_w
|
30
|
-
value = value.tr("_", "-")
|
31
30
|
|
32
31
|
if value.is_a? String
|
33
|
-
|
32
|
+
# libvips expects "-" as a separator in enum names, but "_" is more
|
33
|
+
# convenient for ruby, eg. :b_w
|
34
|
+
value = Vips::vips_enum_from_nick "ruby-vips", gtype, value.tr("_", "-")
|
34
35
|
if value == -1
|
35
36
|
raise Vips::Error
|
36
37
|
end
|
@@ -244,6 +245,14 @@ module GObject
|
|
244
245
|
|
245
246
|
return result
|
246
247
|
end
|
248
|
+
|
249
|
+
# Clear the thing held by a GValue.
|
250
|
+
#
|
251
|
+
# This happens automatically when a GValue is GCed, but this method can be
|
252
|
+
# handy if you need to drop a reference explicitly for some reason.
|
253
|
+
def unset
|
254
|
+
::GObject::g_value_unset self
|
255
|
+
end
|
247
256
|
end
|
248
257
|
|
249
258
|
attach_function :g_value_init, [GValue.ptr, :GType], :void
|