ruby-vips 2.0.13 → 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 +44 -0
- data/Gemfile +3 -1
- data/README.md +45 -47
- data/Rakefile +13 -15
- data/TODO +19 -10
- data/VERSION +1 -1
- data/example/annotate.rb +7 -7
- data/example/connection.rb +26 -0
- data/example/daltonize8.rb +27 -29
- data/example/draw_lines.rb +30 -0
- data/example/example1.rb +5 -6
- data/example/example2.rb +11 -11
- data/example/example3.rb +9 -9
- data/example/example4.rb +8 -8
- data/example/example5.rb +8 -9
- data/example/inheritance_with_refcount.rb +203 -221
- data/example/progress.rb +30 -0
- data/example/thumb.rb +12 -14
- data/example/trim8.rb +7 -7
- data/example/watermark.rb +15 -36
- data/example/wobble.rb +25 -25
- data/lib/ruby-vips.rb +1 -1
- data/lib/vips.rb +473 -338
- data/lib/vips/access.rb +9 -9
- data/lib/vips/align.rb +7 -8
- data/lib/vips/angle.rb +8 -9
- data/lib/vips/angle45.rb +12 -13
- data/lib/vips/bandformat.rb +16 -18
- data/lib/vips/blend_mode.rb +36 -0
- data/lib/vips/coding.rb +11 -12
- data/lib/vips/compass_direction.rb +13 -14
- data/lib/vips/connection.rb +46 -0
- data/lib/vips/direction.rb +7 -8
- data/lib/vips/extend.rb +13 -14
- data/lib/vips/gobject.rb +111 -100
- data/lib/vips/gvalue.rb +243 -237
- data/lib/vips/image.rb +1501 -1338
- data/lib/vips/interesting.rb +10 -11
- data/lib/vips/interpolate.rb +50 -54
- data/lib/vips/interpretation.rb +25 -26
- data/lib/vips/kernel.rb +18 -19
- data/lib/vips/methods.rb +929 -309
- data/lib/vips/mutableimage.rb +154 -0
- data/lib/vips/object.rb +318 -208
- data/lib/vips/operation.rb +467 -320
- data/lib/vips/operationboolean.rb +10 -11
- data/lib/vips/operationcomplex.rb +8 -9
- data/lib/vips/operationcomplex2.rb +6 -7
- data/lib/vips/operationcomplexget.rb +7 -8
- data/lib/vips/operationmath.rb +14 -15
- data/lib/vips/operationmath2.rb +6 -7
- data/lib/vips/operationrelational.rb +11 -12
- data/lib/vips/operationround.rb +7 -8
- data/lib/vips/region.rb +73 -0
- data/lib/vips/size.rb +9 -10
- data/lib/vips/source.rb +88 -0
- data/lib/vips/sourcecustom.rb +89 -0
- data/lib/vips/target.rb +86 -0
- data/lib/vips/targetcustom.rb +77 -0
- data/lib/vips/version.rb +1 -2
- data/ruby-vips.gemspec +29 -20
- metadata +51 -40
- data/.travis.yml +0 -55
- data/install-vips.sh +0 -26
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/example/thumb.rb
CHANGED
@@ -1,31 +1,29 @@
|
|
1
|
-
#!/usr/bin/
|
1
|
+
#!/usr/bin/ruby
|
2
2
|
|
3
3
|
# batch-process a lot of files
|
4
4
|
#
|
5
5
|
# this should run in constant memory -- if it doesn't, something has broken
|
6
6
|
|
7
|
-
require
|
7
|
+
require "vips"
|
8
8
|
|
9
9
|
# benchmark thumbnail via a memory buffer
|
10
|
-
def via_memory(filename, thumbnail_width)
|
11
|
-
|
10
|
+
def via_memory(filename, thumbnail_width)
|
11
|
+
data = IO.binread(filename)
|
12
12
|
|
13
|
-
|
13
|
+
thumb = Vips::Image.thumbnail_buffer data, thumbnail_width, crop: "centre"
|
14
14
|
|
15
|
-
|
15
|
+
thumb.write_to_buffer ".jpg"
|
16
16
|
end
|
17
17
|
|
18
18
|
# benchmark thumbnail via files
|
19
|
-
def via_files(filename, thumbnail_width)
|
20
|
-
|
19
|
+
def via_files(filename, thumbnail_width)
|
20
|
+
thumb = Vips::Image.thumbnail filename, thumbnail_width, crop: "centre"
|
21
21
|
|
22
|
-
|
22
|
+
thumb.write_to_buffer ".jpg"
|
23
23
|
end
|
24
24
|
|
25
25
|
ARGV.each do |filename|
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
puts "processing #{filename} ..."
|
27
|
+
_thumb = via_memory(filename, 500)
|
28
|
+
# _thumb = via_files(filename, 500)
|
29
29
|
end
|
30
|
-
|
31
|
-
|
data/example/trim8.rb
CHANGED
@@ -7,15 +7,15 @@
|
|
7
7
|
# non-zero row or column is the object edge. We make the mask image with an
|
8
8
|
# amount-different-from-background image plus a threshold.
|
9
9
|
|
10
|
-
require
|
10
|
+
require "vips"
|
11
11
|
|
12
12
|
im = Vips::Image.new_from_file ARGV[0]
|
13
13
|
|
14
|
-
# find the value of the pixel at (0, 0) ... we will search for all pixels
|
14
|
+
# find the value of the pixel at (0, 0) ... we will search for all pixels
|
15
15
|
# significantly different from this
|
16
16
|
background = im.getpoint(0, 0)
|
17
17
|
|
18
|
-
# we need to smooth the image, subtract the background from every pixel, take
|
18
|
+
# we need to smooth the image, subtract the background from every pixel, take
|
19
19
|
# the absolute value of the difference, then threshold
|
20
20
|
mask = (im.median - background).abs > 10
|
21
21
|
|
@@ -23,16 +23,16 @@ mask = (im.median - background).abs > 10
|
|
23
23
|
# direction
|
24
24
|
columns, rows = mask.project
|
25
25
|
|
26
|
-
|
26
|
+
_first_column, first_row = columns.profile
|
27
27
|
left = first_row.min
|
28
28
|
|
29
|
-
|
29
|
+
_first_column, first_row = columns.fliphor.profile
|
30
30
|
right = columns.width - first_row.min
|
31
31
|
|
32
|
-
first_column,
|
32
|
+
first_column, _first_row = rows.profile
|
33
33
|
top = first_column.min
|
34
34
|
|
35
|
-
first_column,
|
35
|
+
first_column, _first_row = rows.flipver.profile
|
36
36
|
bottom = rows.height - first_column.min
|
37
37
|
|
38
38
|
# and now crop the original image
|
data/example/watermark.rb
CHANGED
@@ -1,44 +1,23 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
|
5
|
-
im = Vips::Image.new_from_file ARGV[0], :
|
6
|
-
|
7
|
-
|
3
|
+
require "vips"
|
4
|
+
|
5
|
+
im = Vips::Image.new_from_file ARGV[0], access: :sequential
|
6
|
+
|
7
|
+
# make the text mask
|
8
|
+
text = Vips::Image.text ARGV[2], width: 200, dpi: 200, font: "sans bold"
|
9
|
+
text = text.rotate(-45)
|
10
|
+
# make the text transparent
|
8
11
|
text = (text * 0.3).cast(:uchar)
|
9
|
-
text = text.
|
12
|
+
text = text.gravity :centre, 200, 200
|
10
13
|
text = text.replicate 1 + im.width / text.width, 1 + im.height / text.height
|
11
14
|
text = text.crop 0, 0, im.width, im.height
|
12
15
|
|
13
|
-
# we
|
14
|
-
|
15
|
-
|
16
|
-
# guess how many bands from the start of im contain visible colour information
|
17
|
-
if im.bands >= 4 and im.interpretation == :cmyk
|
18
|
-
# cmyk image
|
19
|
-
n_visible_bands = 4
|
20
|
-
text_colour = [0, 255, 0, 0]
|
21
|
-
elsif im.bands >= 3
|
22
|
-
# rgb image
|
23
|
-
n_visible_bands = 3
|
24
|
-
text_colour = [255, 0, 0]
|
25
|
-
else
|
26
|
-
# mono image
|
27
|
-
n_visible_bands = 1
|
28
|
-
text_colour = 255
|
29
|
-
end
|
30
|
-
|
31
|
-
# split into image and alpha
|
32
|
-
if im.bands - n_visible_bands > 0
|
33
|
-
alpha = im.extract_band n_visible_bands, :n => im.bands - n_visible_bands
|
34
|
-
im = im.extract_band 0, :n => n_visible_bands
|
35
|
-
else
|
36
|
-
alpha = nil
|
37
|
-
end
|
16
|
+
# we make a constant colour image and attach the text mask as the alpha
|
17
|
+
overlay = (text.new_from_image [255, 128, 128]).copy interpretation: :srgb
|
18
|
+
overlay = overlay.bandjoin text
|
38
19
|
|
39
|
-
|
20
|
+
# overlay the text
|
21
|
+
im = im.composite overlay, :over
|
40
22
|
|
41
|
-
|
42
|
-
marked = marked.bandjoin alpha if alpha
|
43
|
-
|
44
|
-
marked.write_to_file ARGV[1]
|
23
|
+
im.write_to_file ARGV[1]
|
data/example/wobble.rb
CHANGED
@@ -1,35 +1,35 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
|
3
|
-
require
|
3
|
+
require "vips"
|
4
4
|
|
5
5
|
image = Vips::Image.new_from_file ARGV[0]
|
6
6
|
|
7
7
|
module Vips
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
8
|
+
class Image
|
9
|
+
def wobble
|
10
|
+
# this makes an image where pixel (0, 0) (at the top-left) has
|
11
|
+
# value [0, 0], and pixel (image.width - 1, image.height - 1) at the
|
12
|
+
# bottom-right has value [image.width - 1, image.height - 1]
|
13
|
+
index = Vips::Image.xyz width, height
|
14
|
+
|
15
|
+
# make a version with (0, 0) at the centre, negative values up
|
16
|
+
# and left, positive down and right
|
17
|
+
centre = index - [width / 2, height / 2]
|
18
|
+
|
19
|
+
# to polar space, so each pixel is now distance and angle in degrees
|
20
|
+
polar = centre.polar
|
21
|
+
|
22
|
+
# scale sin(distance) by 1/distance to make a wavey pattern
|
23
|
+
d = ((polar[0] * 3).sin * 10000) / (polar[0] + 1)
|
24
|
+
|
25
|
+
# and back to rectangular coordinates again to make a set of
|
26
|
+
# vectors we can apply to the original index image
|
27
|
+
index += d.bandjoin(polar[1]).rect
|
28
|
+
|
29
|
+
# finally, use our modified index image to distort!
|
30
|
+
mapim index
|
32
31
|
end
|
32
|
+
end
|
33
33
|
end
|
34
34
|
|
35
35
|
image = image.wobble
|
data/lib/ruby-vips.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require
|
1
|
+
require "vips"
|
data/lib/vips.rb
CHANGED
@@ -4,161 +4,169 @@
|
|
4
4
|
# Author:: John Cupitt (mailto:jcupitt@gmail.com)
|
5
5
|
# License:: MIT
|
6
6
|
|
7
|
-
require
|
8
|
-
require
|
9
|
-
|
10
|
-
# This module uses FFI to make a simple layer over the glib and gobject
|
11
|
-
# libraries.
|
7
|
+
require "ffi"
|
8
|
+
require "logger"
|
9
|
+
|
10
|
+
# This module uses FFI to make a simple layer over the glib and gobject
|
11
|
+
# libraries.
|
12
|
+
|
13
|
+
# Generate a library name for ffi.
|
14
|
+
#
|
15
|
+
# Platform notes:
|
16
|
+
# linux:
|
17
|
+
# Some distros allow "libvips.so", but only if the -dev headers have been
|
18
|
+
# installed. To work everywhere, you must include the ABI number.
|
19
|
+
# Confusingly, the file extension is not at the end. ffi adds the "lib"
|
20
|
+
# prefix.
|
21
|
+
# mac:
|
22
|
+
# As linux, but the extension is at the end and is added by ffi.
|
23
|
+
# windows:
|
24
|
+
# The ABI number must be included, but with a hyphen. ffi does not add a
|
25
|
+
# "lib" prefix or a ".dll" suffix.
|
26
|
+
def library_name(name, abi_number)
|
27
|
+
if FFI::Platform.windows?
|
28
|
+
"lib#{name}-#{abi_number}.dll"
|
29
|
+
elsif FFI::Platform.mac?
|
30
|
+
"#{name}.#{abi_number}"
|
31
|
+
else
|
32
|
+
"#{name}.so.#{abi_number}"
|
33
|
+
end
|
34
|
+
end
|
12
35
|
|
13
36
|
module GLib
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.remove_log_handler
|
74
|
-
if @glib_log_handler_id != 0 && @glib_log_domain
|
75
|
-
g_log_remove_handler @glib_log_domain, @glib_log_handler_id
|
76
|
-
@glib_log_handler_id = nil
|
77
|
-
end
|
37
|
+
class << self
|
38
|
+
attr_accessor :logger
|
39
|
+
end
|
40
|
+
@logger = Logger.new($stdout)
|
41
|
+
@logger.level = Logger::WARN
|
42
|
+
|
43
|
+
extend FFI::Library
|
44
|
+
|
45
|
+
ffi_lib library_name("glib-2.0", 0)
|
46
|
+
|
47
|
+
attach_function :g_malloc, [:size_t], :pointer
|
48
|
+
|
49
|
+
# save the FFI::Function that attach will return ... we can use it directly
|
50
|
+
# as a param for callbacks
|
51
|
+
G_FREE = attach_function :g_free, [:pointer], :void
|
52
|
+
|
53
|
+
callback :g_log_func, [:string, :int, :string, :pointer], :void
|
54
|
+
attach_function :g_log_set_handler,
|
55
|
+
[:string, :int, :g_log_func, :pointer], :int
|
56
|
+
attach_function :g_log_remove_handler, [:string, :int], :void
|
57
|
+
|
58
|
+
# log flags
|
59
|
+
LOG_FLAG_RECURSION = 1 << 0
|
60
|
+
LOG_FLAG_FATAL = 1 << 1
|
61
|
+
|
62
|
+
# GLib log levels
|
63
|
+
LOG_LEVEL_ERROR = 1 << 2 # always fatal
|
64
|
+
LOG_LEVEL_CRITICAL = 1 << 3
|
65
|
+
LOG_LEVEL_WARNING = 1 << 4
|
66
|
+
LOG_LEVEL_MESSAGE = 1 << 5
|
67
|
+
LOG_LEVEL_INFO = 1 << 6
|
68
|
+
LOG_LEVEL_DEBUG = 1 << 7
|
69
|
+
|
70
|
+
# map glib levels to Logger::Severity
|
71
|
+
GLIB_TO_SEVERITY = {
|
72
|
+
LOG_LEVEL_ERROR => Logger::ERROR,
|
73
|
+
LOG_LEVEL_CRITICAL => Logger::FATAL,
|
74
|
+
LOG_LEVEL_WARNING => Logger::WARN,
|
75
|
+
LOG_LEVEL_MESSAGE => Logger::UNKNOWN,
|
76
|
+
LOG_LEVEL_INFO => Logger::INFO,
|
77
|
+
LOG_LEVEL_DEBUG => Logger::DEBUG
|
78
|
+
}
|
79
|
+
GLIB_TO_SEVERITY.default = Logger::UNKNOWN
|
80
|
+
|
81
|
+
# nil being the default
|
82
|
+
@glib_log_domain = nil
|
83
|
+
@glib_log_handler_id = 0
|
84
|
+
|
85
|
+
# module-level, so it's not GCd away
|
86
|
+
LOG_HANDLER = proc { |domain, level, message, _user_data|
|
87
|
+
@logger.log(GLIB_TO_SEVERITY[level], message, domain)
|
88
|
+
}
|
89
|
+
|
90
|
+
def self.remove_log_handler
|
91
|
+
if @glib_log_handler_id != 0 && @glib_log_domain
|
92
|
+
g_log_remove_handler @glib_log_domain, @glib_log_handler_id
|
93
|
+
@glib_log_handler_id = nil
|
78
94
|
end
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
#
|
99
|
-
#
|
100
|
-
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.set_log_domain domain
|
98
|
+
GLib.remove_log_handler
|
99
|
+
|
100
|
+
@glib_log_domain = domain
|
101
|
+
|
102
|
+
# forward all glib logging output from this domain to a Ruby logger
|
103
|
+
if @glib_log_domain
|
104
|
+
# disable this feature for now
|
105
|
+
#
|
106
|
+
# libvips background worker threads can issue warnings, and
|
107
|
+
# since the main thread is blocked waiting for libvips to come back
|
108
|
+
# from an ffi call, you get a deadlock on the GIL
|
109
|
+
#
|
110
|
+
# to fix this, we need a way for g_log() calls from libvips workers
|
111
|
+
# to be returned via the main thread
|
112
|
+
#
|
113
|
+
|
114
|
+
# @glib_log_handler_id = g_log_set_handler @glib_log_domain,
|
115
|
+
# LOG_LEVEL_DEBUG |
|
116
|
+
# LOG_LEVEL_INFO |
|
117
|
+
# LOG_LEVEL_MESSAGE |
|
118
|
+
# LOG_LEVEL_WARNING |
|
119
|
+
# LOG_LEVEL_ERROR |
|
120
|
+
# LOG_LEVEL_CRITICAL |
|
121
|
+
# LOG_FLAG_FATAL | LOG_FLAG_RECURSION,
|
122
|
+
# LOG_HANDLER, nil
|
123
|
+
|
124
|
+
# we must remove any handlers on exit, since libvips may log stuff
|
125
|
+
# on shutdown and we don't want LOG_HANDLER to be invoked
|
126
|
+
# after Ruby has gone
|
127
|
+
at_exit {
|
128
|
+
GLib.remove_log_handler
|
129
|
+
}
|
115
130
|
end
|
116
|
-
|
131
|
+
end
|
117
132
|
end
|
118
133
|
|
119
134
|
module GObject
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
GUINT64_TYPE = g_type_from_name "guint64"
|
149
|
-
GDOUBLE_TYPE = g_type_from_name "gdouble"
|
150
|
-
GENUM_TYPE = g_type_from_name "GEnum"
|
151
|
-
GFLAGS_TYPE = g_type_from_name "GFlags"
|
152
|
-
GSTR_TYPE = g_type_from_name "gchararray"
|
153
|
-
GOBJECT_TYPE = g_type_from_name "GObject"
|
154
|
-
|
135
|
+
extend FFI::Library
|
136
|
+
|
137
|
+
ffi_lib library_name("gobject-2.0", 0)
|
138
|
+
|
139
|
+
# we can't just use ulong, windows has different int sizing rules
|
140
|
+
if FFI::Platform::ADDRESS_SIZE == 64
|
141
|
+
typedef :uint64, :GType
|
142
|
+
else
|
143
|
+
typedef :uint32, :GType
|
144
|
+
end
|
145
|
+
|
146
|
+
attach_function :g_type_init, [], :void
|
147
|
+
attach_function :g_type_name, [:GType], :string
|
148
|
+
attach_function :g_type_from_name, [:string], :GType
|
149
|
+
attach_function :g_type_fundamental, [:GType], :GType
|
150
|
+
|
151
|
+
# glib before 2.36 needed this, does nothing in current glib
|
152
|
+
g_type_init
|
153
|
+
|
154
|
+
# look up some common gtypes
|
155
|
+
GBOOL_TYPE = g_type_from_name "gboolean"
|
156
|
+
GINT_TYPE = g_type_from_name "gint"
|
157
|
+
GUINT64_TYPE = g_type_from_name "guint64"
|
158
|
+
GDOUBLE_TYPE = g_type_from_name "gdouble"
|
159
|
+
GENUM_TYPE = g_type_from_name "GEnum"
|
160
|
+
GFLAGS_TYPE = g_type_from_name "GFlags"
|
161
|
+
GSTR_TYPE = g_type_from_name "gchararray"
|
162
|
+
GOBJECT_TYPE = g_type_from_name "GObject"
|
155
163
|
end
|
156
164
|
|
157
|
-
require
|
158
|
-
require
|
165
|
+
require "vips/gobject"
|
166
|
+
require "vips/gvalue"
|
159
167
|
|
160
|
-
# This module provides a binding for the [libvips image processing
|
161
|
-
# library](https://
|
168
|
+
# This module provides a binding for the [libvips image processing
|
169
|
+
# library](https://libvips.github.io/libvips/).
|
162
170
|
#
|
163
171
|
# # Example
|
164
172
|
#
|
@@ -183,8 +191,8 @@ require 'vips/gvalue'
|
|
183
191
|
# im.write_to_file ARGV[1]
|
184
192
|
# ```
|
185
193
|
#
|
186
|
-
# This example loads a file, boosts the green channel (I'm not sure why),
|
187
|
-
# sharpens the image, and saves it back to disc again.
|
194
|
+
# This example loads a file, boosts the green channel (I'm not sure why),
|
195
|
+
# sharpens the image, and saves it back to disc again.
|
188
196
|
#
|
189
197
|
# Reading this example line by line, we have:
|
190
198
|
#
|
@@ -198,11 +206,12 @@ require 'vips/gvalue'
|
|
198
206
|
# default mode is `:random`: this allows for full random access to image pixels,
|
199
207
|
# but is slower and needs more memory. See {Access}
|
200
208
|
# for full details
|
201
|
-
# on the various modes available.
|
209
|
+
# on the various modes available.
|
202
210
|
#
|
203
|
-
# You can also load formatted images from
|
204
|
-
#
|
205
|
-
# from
|
211
|
+
# You can also load formatted images from memory buffers, create images that
|
212
|
+
# wrap C-style memory arrays, or make images from constants. Use {Source}
|
213
|
+
# and {Image.new_from_source} to load images from any data source, for
|
214
|
+
# example URIs.
|
206
215
|
#
|
207
216
|
# The next line:
|
208
217
|
#
|
@@ -226,13 +235,13 @@ require 'vips/gvalue'
|
|
226
235
|
# ```
|
227
236
|
#
|
228
237
|
# {Image.new_from_array} creates an image from an array constant. The 8 at
|
229
|
-
# the end sets the scale: the amount to divide the image by after
|
230
|
-
# integer convolution.
|
238
|
+
# the end sets the scale: the amount to divide the image by after
|
239
|
+
# integer convolution.
|
231
240
|
#
|
232
241
|
# See the libvips API docs for `vips_conv()` (the operation
|
233
242
|
# invoked by {Image#conv}) for details on the convolution operator. By default,
|
234
|
-
# it computes with a float mask, but `:integer` is fine for this case, and is
|
235
|
-
# much faster.
|
243
|
+
# it computes with a float mask, but `:integer` is fine for this case, and is
|
244
|
+
# much faster.
|
236
245
|
#
|
237
246
|
# Finally:
|
238
247
|
#
|
@@ -240,10 +249,13 @@ require 'vips/gvalue'
|
|
240
249
|
# im.write_to_file ARGV[1]
|
241
250
|
# ```
|
242
251
|
#
|
243
|
-
# {Image#write_to_file} writes an image back to the filesystem. It can
|
244
|
-
# write any format supported by vips: the file type is set from the filename
|
245
|
-
# suffix. You can also write formatted images to memory buffers, or dump
|
246
|
-
# image data to a raw memory array.
|
252
|
+
# {Image#write_to_file} writes an image back to the filesystem. It can
|
253
|
+
# write any format supported by vips: the file type is set from the filename
|
254
|
+
# suffix. You can also write formatted images to memory buffers, or dump
|
255
|
+
# image data to a raw memory array.
|
256
|
+
#
|
257
|
+
# Use {Target} and {Image#write_to_target} to write formatted images to
|
258
|
+
# any data sink, for example URIs.
|
247
259
|
#
|
248
260
|
# # How it works
|
249
261
|
#
|
@@ -251,30 +263,30 @@ require 'vips/gvalue'
|
|
251
263
|
# shared library. When you call a method on the image class, it uses libvips
|
252
264
|
# introspection system (based on GObject) to search the
|
253
265
|
# library for an operation of that name, transforms the arguments to a form
|
254
|
-
# libvips can digest, and runs the operation.
|
266
|
+
# libvips can digest, and runs the operation.
|
255
267
|
#
|
256
268
|
# This means ruby-vips always presents the API implemented by the libvips shared
|
257
|
-
# library. It should update itself as new features are added.
|
269
|
+
# library. It should update itself as new features are added.
|
258
270
|
#
|
259
271
|
# # Automatic wrapping
|
260
272
|
#
|
261
273
|
# `ruby-vips` adds a {Image.method_missing} handler to {Image} and uses
|
262
274
|
# it to look up vips operations. For example, the libvips operation `add`, which
|
263
|
-
# appears in C as `vips_add()`, appears in Ruby as {Image#add}.
|
275
|
+
# appears in C as `vips_add()`, appears in Ruby as {Image#add}.
|
264
276
|
#
|
265
|
-
# The operation's list of required arguments is searched and the first input
|
266
|
-
# image is set to the value of `self`. Operations which do not take an input
|
277
|
+
# The operation's list of required arguments is searched and the first input
|
278
|
+
# image is set to the value of `self`. Operations which do not take an input
|
267
279
|
# image, such as {Image.black}, appear as class methods. The remainder of
|
268
280
|
# the arguments you supply in the function call are used to set the other
|
269
281
|
# required input arguments. Any trailing keyword arguments are used to set
|
270
282
|
# options on the operation.
|
271
|
-
#
|
272
|
-
# The result is the required output
|
283
|
+
#
|
284
|
+
# The result is the required output
|
273
285
|
# argument if there is only one result, or an array of values if the operation
|
274
286
|
# produces several results. If the operation has optional output objects, they
|
275
287
|
# are returned as a final hash.
|
276
288
|
#
|
277
|
-
# For example, {Image#min}, the vips operation that searches an image for
|
289
|
+
# For example, {Image#min}, the vips operation that searches an image for
|
278
290
|
# the minimum value, has a large number of optional arguments. You can use it to
|
279
291
|
# find the minimum value like this:
|
280
292
|
#
|
@@ -283,14 +295,14 @@ require 'vips/gvalue'
|
|
283
295
|
# ```
|
284
296
|
#
|
285
297
|
# You can ask it to return the position of the minimum with `:x` and `:y`.
|
286
|
-
#
|
298
|
+
#
|
287
299
|
# ```ruby
|
288
300
|
# min_value, opts = min x: true, y: true
|
289
301
|
# x_pos = opts['x']
|
290
302
|
# y_pos = opts['y']
|
291
303
|
# ```
|
292
304
|
#
|
293
|
-
# Now `x_pos` and `y_pos` will have the coordinates of the minimum value.
|
305
|
+
# Now `x_pos` and `y_pos` will have the coordinates of the minimum value.
|
294
306
|
# There's actually a convenience method for this, {Image#minpos}.
|
295
307
|
#
|
296
308
|
# You can also ask for the top *n* minimum, for example:
|
@@ -301,7 +313,7 @@ require 'vips/gvalue'
|
|
301
313
|
# y_pos = opts['y_array']
|
302
314
|
# ```
|
303
315
|
#
|
304
|
-
# Now `x_pos` and `y_pos` will be 10-element arrays.
|
316
|
+
# Now `x_pos` and `y_pos` will be 10-element arrays.
|
305
317
|
#
|
306
318
|
# Because operations are member functions and return the result image, you can
|
307
319
|
# chain them. For example, you can write:
|
@@ -310,30 +322,30 @@ require 'vips/gvalue'
|
|
310
322
|
# result_image = image.real.cos
|
311
323
|
# ```
|
312
324
|
#
|
313
|
-
# to calculate the cosine of the real part of a complex image.
|
325
|
+
# to calculate the cosine of the real part of a complex image.
|
314
326
|
# There are also a full set
|
315
327
|
# of arithmetic operator overloads, see below.
|
316
328
|
#
|
317
|
-
# libvips types are also automatically wrapped. The override looks at the type
|
318
|
-
# of argument required by the operation and converts the value you supply,
|
319
|
-
# when it can. For example, {Image#linear} takes a `VipsArrayDouble` as
|
320
|
-
# an argument
|
321
|
-
# for the set of constants to use for multiplication. You can supply this
|
322
|
-
# value as an integer, a float, or some kind of compound object and it
|
329
|
+
# libvips types are also automatically wrapped. The override looks at the type
|
330
|
+
# of argument required by the operation and converts the value you supply,
|
331
|
+
# when it can. For example, {Image#linear} takes a `VipsArrayDouble` as
|
332
|
+
# an argument
|
333
|
+
# for the set of constants to use for multiplication. You can supply this
|
334
|
+
# value as an integer, a float, or some kind of compound object and it
|
323
335
|
# will be converted for you. You can write:
|
324
336
|
#
|
325
337
|
# ```ruby
|
326
|
-
# result_image = image.linear 1, 3
|
327
|
-
# result_image = image.linear 12.4, 13.9
|
328
|
-
# result_image = image.linear [1, 2, 3], [4, 5, 6]
|
329
|
-
# result_image = image.linear 1, [4, 5, 6]
|
338
|
+
# result_image = image.linear 1, 3
|
339
|
+
# result_image = image.linear 12.4, 13.9
|
340
|
+
# result_image = image.linear [1, 2, 3], [4, 5, 6]
|
341
|
+
# result_image = image.linear 1, [4, 5, 6]
|
330
342
|
# ```
|
331
343
|
#
|
332
344
|
# And so on. A set of overloads are defined for {Image#linear}, see below.
|
333
345
|
#
|
334
346
|
# It does a couple of more ambitious conversions. It will automatically convert
|
335
347
|
# to and from the various vips types, like `VipsBlob` and `VipsArrayImage`. For
|
336
|
-
# example, you can read the ICC profile out of an image like this:
|
348
|
+
# example, you can read the ICC profile out of an image like this:
|
337
349
|
#
|
338
350
|
# ```ruby
|
339
351
|
# profile = im.get_value "icc-profile-data"
|
@@ -343,7 +355,7 @@ require 'vips/gvalue'
|
|
343
355
|
#
|
344
356
|
# If an operation takes several input images, you can use a constant for all but
|
345
357
|
# one of them and the wrapper will expand the constant to an image for you. For
|
346
|
-
# example, {Image#ifthenelse} uses a condition image to pick pixels
|
358
|
+
# example, {Image#ifthenelse} uses a condition image to pick pixels
|
347
359
|
# between a then and an else image:
|
348
360
|
#
|
349
361
|
# ```ruby
|
@@ -360,7 +372,7 @@ require 'vips/gvalue'
|
|
360
372
|
#
|
361
373
|
# Will make an image where true pixels are green and false pixels are red.
|
362
374
|
#
|
363
|
-
# This is useful for {Image#bandjoin}, the thing to join two or more
|
375
|
+
# This is useful for {Image#bandjoin}, the thing to join two or more
|
364
376
|
# images up bandwise. You can write:
|
365
377
|
#
|
366
378
|
# ```ruby
|
@@ -377,54 +389,150 @@ require 'vips/gvalue'
|
|
377
389
|
# result_image = image1.bandjoin [image2, 255]
|
378
390
|
# ```
|
379
391
|
#
|
380
|
-
# and so on.
|
392
|
+
# and so on.
|
381
393
|
#
|
382
394
|
# # Logging
|
383
395
|
#
|
384
|
-
# Libvips uses g_log() to log warning, debug, info and (some) error messages.
|
396
|
+
# Libvips uses g_log() to log warning, debug, info and (some) error messages.
|
385
397
|
#
|
386
398
|
# https://developer.gnome.org/glib/stable/glib-Message-Logging.html
|
387
399
|
#
|
388
|
-
# You can disable
|
389
|
-
# You can enable info output by defining `VIPS_INFO`.
|
400
|
+
# You can disable warnings by defining the `VIPS_WARNING` environment variable.
|
401
|
+
# You can enable info output by defining `VIPS_INFO`.
|
390
402
|
#
|
391
403
|
# # Exceptions
|
392
404
|
#
|
393
405
|
# The wrapper spots errors from vips operations and raises the {Vips::Error}
|
394
|
-
# exception. You can catch it in the usual way.
|
406
|
+
# exception. You can catch it in the usual way.
|
395
407
|
#
|
396
408
|
# # Automatic YARD documentation
|
397
409
|
#
|
398
|
-
# The bulk of these API docs are generated automatically by
|
399
|
-
#
|
400
|
-
#
|
401
|
-
#
|
402
|
-
#
|
403
|
-
# Use the [C API
|
404
|
-
# docs](https://jcupitt.github.io/libvips/API/current)
|
410
|
+
# The bulk of these API docs are generated automatically by {Yard#generate}.
|
411
|
+
# It examines libvips and writes a summary of each operation and the arguments
|
412
|
+
# and options that that operation expects.
|
413
|
+
#
|
414
|
+
# Use the [C API # docs](https://libvips.github.io/libvips/API/current)
|
405
415
|
# for more detail.
|
406
416
|
#
|
407
417
|
# # Enums
|
408
418
|
#
|
409
419
|
# The libvips enums, such as `VipsBandFormat` appear in ruby-vips as Symbols
|
410
420
|
# like `:uchar`. They are documented as a set of classes for convenience, see
|
411
|
-
#
|
412
|
-
#
|
421
|
+
# {Vips::BandFormat}, for example.
|
422
|
+
#
|
413
423
|
# # Draw operations
|
414
424
|
#
|
415
|
-
#
|
416
|
-
#
|
417
|
-
#
|
418
|
-
#
|
425
|
+
# There are two ways of calling the libvips draw operations, like
|
426
|
+
# {Image#draw_circle} and {Image#draw_line}.
|
427
|
+
#
|
428
|
+
# First, you can use them like functions. For example:
|
429
|
+
#
|
430
|
+
# ```ruby
|
431
|
+
# y = x.draw_line 255, 0, 0, x.width, x.height
|
432
|
+
# ```
|
433
|
+
#
|
434
|
+
# This will make a new image, `y`, which is a copy of `x` but with a line
|
435
|
+
# drawn across it. `x` is unchanged.
|
436
|
+
#
|
437
|
+
# This is simple, but will be slow if you want to draw many lines, since
|
438
|
+
# ruby-vips will make a copy of the whole image each time.
|
439
|
+
#
|
440
|
+
# You can use {Image#mutate} to make a {MutableImage}. This is an image which
|
441
|
+
# is unshared and is only available inside the {Image#mutate} block. Within
|
442
|
+
# this block, you can use `!` versions of the draw operations to modify images
|
443
|
+
# and avoid the copy. For example:
|
444
|
+
#
|
445
|
+
# ```ruby
|
446
|
+
# image = image.mutate do |mutable|
|
447
|
+
# (0 ... 1).step(0.01) do |i|
|
448
|
+
# mutable.draw_line! 255, mutable.width * i, 0, 0, mutable.height * (1 - i)
|
449
|
+
# end
|
450
|
+
# end
|
451
|
+
# ```
|
452
|
+
#
|
453
|
+
# Now each {Image#draw_line} will directly modify the mutable image, saving
|
454
|
+
# the copy. This is much faster and needs much less memory.
|
455
|
+
#
|
456
|
+
# # Metadata read
|
457
|
+
#
|
458
|
+
# Use {Image#get_fields} to get a list of the metadata fields that an image
|
459
|
+
# supports. ICC profiles, for example, are in a field called
|
460
|
+
# `icc-profile-data`. Use `vipsheader -a something.jpg` at the command-line
|
461
|
+
# to see all the fields on an image.
|
462
|
+
#
|
463
|
+
# Use {Image#get_typeof} to get the type of a field. Types are integers, with
|
464
|
+
# 0 meaning "no such field". Constants like {GObject::GINT_TYPE} are useful for
|
465
|
+
# testing field types.
|
466
|
+
#
|
467
|
+
# You can read image metadata using {Image#get}. The field value is converted
|
468
|
+
# to a Ruby value in the obvious way.
|
469
|
+
#
|
470
|
+
# # Metadata write
|
471
|
+
#
|
472
|
+
# You can also set and remove image metadata fields. Images are immutable, so
|
473
|
+
# you must make any changes inside a {Image#mutate} block. For example:
|
474
|
+
#
|
475
|
+
# ```ruby
|
476
|
+
# image = image.mutate do |mutable|
|
477
|
+
# image.get_fields.each do |field|
|
478
|
+
# mutable.remove! field unless field == "icc-profile-data"
|
479
|
+
# end
|
480
|
+
# end
|
481
|
+
# ```
|
482
|
+
#
|
483
|
+
# To remove all metadata except the icc profile.
|
484
|
+
#
|
485
|
+
# You can use {MutableImage#set!} to change the value of an existing field,
|
486
|
+
# and {MutableImage#set_type!} to create a new field with a specified type.
|
487
|
+
#
|
488
|
+
# # Progress
|
489
|
+
#
|
490
|
+
# You can attach signal handlers to images to watch computation progress. For
|
491
|
+
# example:
|
492
|
+
#
|
493
|
+
# ```ruby
|
494
|
+
# image = Vips::Image.black 1, 100000
|
495
|
+
# image.set_progress true
|
496
|
+
#
|
497
|
+
# def progress_to_s(name, progress)
|
498
|
+
# puts "#{name}:"
|
499
|
+
# puts " run = #{progress[:run]}"
|
500
|
+
# puts " eta = #{progress[:eta]}"
|
501
|
+
# puts " tpels = #{progress[:tpels]}"
|
502
|
+
# puts " npels = #{progress[:npels]}"
|
503
|
+
# puts " percent = #{progress[:percent]}"
|
504
|
+
# end
|
505
|
+
#
|
506
|
+
# image.signal_connect :preeval do |progress|
|
507
|
+
# progress_to_s("preeval", progress)
|
508
|
+
# end
|
509
|
+
#
|
510
|
+
# image.signal_connect :eval do |progress|
|
511
|
+
# progress_to_s("eval", progress)
|
512
|
+
# image.set_kill(true) if progress[:percent] > 50
|
513
|
+
# end
|
514
|
+
#
|
515
|
+
# image.signal_connect :posteval do |progress|
|
516
|
+
# progress_to_s("posteval", progress)
|
517
|
+
# end
|
518
|
+
#
|
519
|
+
# image.avg
|
520
|
+
# ```
|
521
|
+
#
|
522
|
+
# The `:eval` signal will fire for every tile that is processed. You can stop
|
523
|
+
# progress with {Image#set_kill} and processing will end with an exception.
|
524
|
+
#
|
525
|
+
# User streams
|
419
526
|
#
|
420
|
-
#
|
421
|
-
#
|
422
|
-
# make it inefficient. If you draw 100 lines on an image, for example, you'll
|
423
|
-
# copy the image 100 times. The wrapper does make sure that memory is recycled
|
424
|
-
# where possible, so you won't have 100 copies in memory.
|
527
|
+
# You can make your own input and output stream objects with {SourceCustom} and
|
528
|
+
# {TargetCustom}. For example:
|
425
529
|
#
|
426
|
-
#
|
427
|
-
#
|
530
|
+
# ```ruby
|
531
|
+
# file = File.open "some/file", "rb"
|
532
|
+
# source = Vips::SourceCustom.new
|
533
|
+
# source.on_read { |length| file.read length }
|
534
|
+
# image = Vips::Image.new_from_source source, "", access: "sequential"
|
535
|
+
# ```
|
428
536
|
#
|
429
537
|
# # Overloads
|
430
538
|
#
|
@@ -438,7 +546,7 @@ require 'vips/gvalue'
|
|
438
546
|
#
|
439
547
|
# # Expansions
|
440
548
|
#
|
441
|
-
# Some vips operators take an enum to select an action, for example
|
549
|
+
# Some vips operators take an enum to select an action, for example
|
442
550
|
# {Image#math} can be used to calculate sine of every pixel like this:
|
443
551
|
#
|
444
552
|
# ```ruby
|
@@ -454,144 +562,171 @@ require 'vips/gvalue'
|
|
454
562
|
#
|
455
563
|
# # Convenience functions
|
456
564
|
#
|
457
|
-
# The wrapper defines a few extra useful utility functions:
|
458
|
-
# {Image#get_value}, {Image#set_value}, {Image#bandsplit},
|
459
|
-
# {Image#maxpos}, {Image#minpos},
|
565
|
+
# The wrapper defines a few extra useful utility functions:
|
566
|
+
# {Image#get_value}, {Image#set_value}, {Image#bandsplit},
|
567
|
+
# {Image#maxpos}, {Image#minpos},
|
460
568
|
# {Image#median}.
|
461
569
|
|
462
570
|
module Vips
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
571
|
+
extend FFI::Library
|
572
|
+
|
573
|
+
ffi_lib library_name("vips", 42)
|
574
|
+
|
575
|
+
LOG_DOMAIN = "VIPS"
|
576
|
+
GLib.set_log_domain LOG_DOMAIN
|
577
|
+
|
578
|
+
typedef :ulong, :GType
|
579
|
+
|
580
|
+
attach_function :vips_error_buffer, [], :string
|
581
|
+
attach_function :vips_error_clear, [], :void
|
582
|
+
|
583
|
+
# The ruby-vips error class.
|
584
|
+
class Error < RuntimeError
|
585
|
+
# @param msg [String] The error message. If this is not supplied, grab
|
586
|
+
# and clear the vips error buffer and use that.
|
587
|
+
def initialize msg = nil
|
588
|
+
if msg
|
589
|
+
@details = msg
|
590
|
+
elsif Vips.vips_error_buffer != ""
|
591
|
+
@details = Vips.vips_error_buffer
|
592
|
+
Vips.vips_error_clear
|
593
|
+
else
|
594
|
+
@details = nil
|
595
|
+
end
|
469
596
|
end
|
470
597
|
|
471
|
-
|
472
|
-
|
473
|
-
LOG_DOMAIN = "VIPS"
|
474
|
-
GLib::set_log_domain LOG_DOMAIN
|
475
|
-
|
476
|
-
typedef :ulong, :GType
|
477
|
-
|
478
|
-
attach_function :vips_error_buffer, [], :string
|
479
|
-
attach_function :vips_error_clear, [], :void
|
480
|
-
|
481
|
-
# The ruby-vips error class.
|
482
|
-
class Error < RuntimeError
|
483
|
-
# @param msg [String] The error message. If this is not supplied, grab
|
484
|
-
# and clear the vips error buffer and use that.
|
485
|
-
def initialize msg = nil
|
486
|
-
if msg
|
487
|
-
@details = msg
|
488
|
-
elsif Vips::vips_error_buffer != ""
|
489
|
-
@details = Vips::vips_error_buffer
|
490
|
-
Vips::vips_error_clear
|
491
|
-
else
|
492
|
-
@details = nil
|
493
|
-
end
|
494
|
-
end
|
495
|
-
|
496
|
-
# Pretty-print a {Vips::Error}.
|
497
|
-
#
|
498
|
-
# @return [String] The error message
|
499
|
-
def to_s
|
500
|
-
if @details != nil
|
501
|
-
@details
|
502
|
-
else
|
503
|
-
super.to_s
|
504
|
-
end
|
505
|
-
end
|
506
|
-
end
|
507
|
-
|
508
|
-
attach_function :vips_init, [:string], :int
|
509
|
-
|
510
|
-
if Vips::vips_init($0) != 0
|
511
|
-
throw Vips::get_error
|
512
|
-
end
|
513
|
-
|
514
|
-
# don't use at_exit to call vips_shutdown, it causes problems with fork, and
|
515
|
-
# in any case libvips does this for us
|
516
|
-
|
517
|
-
attach_function :vips_leak_set, [:int], :void
|
518
|
-
attach_function :vips_vector_set_enabled, [:int], :void
|
519
|
-
attach_function :vips_concurrency_set, [:int], :void
|
520
|
-
|
521
|
-
# Turn libvips leak testing on and off. Handy for debugging ruby-vips, not
|
522
|
-
# very useful for user code.
|
523
|
-
def self.leak_set leak
|
524
|
-
vips_leak_set (leak ? 1 : 0)
|
525
|
-
end
|
526
|
-
|
527
|
-
attach_function :vips_cache_set_max, [:int], :void
|
528
|
-
attach_function :vips_cache_set_max_mem, [:int], :void
|
529
|
-
attach_function :vips_cache_set_max_files, [:int], :void
|
530
|
-
|
531
|
-
# Set the maximum number of operations that libvips should cache. Set 0 to
|
532
|
-
# disable the operation cache. The default is 1000.
|
533
|
-
def self.cache_set_max size
|
534
|
-
vips_cache_set_max size
|
535
|
-
end
|
536
|
-
|
537
|
-
# Set the maximum amount of memory that libvips should use for the operation
|
538
|
-
# cache. Set 0 to disable the operation cache. The default is 100mb.
|
539
|
-
def self.cache_set_max_mem size
|
540
|
-
vips_cache_set_max_mem size
|
541
|
-
end
|
542
|
-
|
543
|
-
# Set the maximum number of files libvips should keep open in the
|
544
|
-
# operation cache. Set 0 to disable the operation cache. The default is
|
545
|
-
# 100.
|
546
|
-
def self.cache_set_max_files size
|
547
|
-
vips_cache_set_max_files size
|
548
|
-
end
|
549
|
-
|
550
|
-
# Set the size of the libvips worker pool. This defaults to the number of
|
551
|
-
# hardware threads on your computer. Set to 1 to disable threading.
|
552
|
-
def self.concurrency_set n
|
553
|
-
vips_concurrency_set n
|
554
|
-
end
|
555
|
-
|
556
|
-
# Enable or disable SIMD and the run-time compiler. This can give a nice
|
557
|
-
# speed-up, but can also be unstable on some systems or with some versions
|
558
|
-
# of the run-time compiler.
|
559
|
-
def self.vector_set enabled
|
560
|
-
vips_vector_set_enabled(enabled ? 1 : 0)
|
561
|
-
end
|
562
|
-
|
563
|
-
# Deprecated compatibility function.
|
598
|
+
# Pretty-print a {Vips::Error}.
|
564
599
|
#
|
565
|
-
#
|
566
|
-
def
|
567
|
-
|
568
|
-
|
569
|
-
|
600
|
+
# @return [String] The error message
|
601
|
+
def to_s
|
602
|
+
if !@details.nil?
|
603
|
+
@details
|
604
|
+
else
|
605
|
+
super.to_s
|
606
|
+
end
|
570
607
|
end
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
608
|
+
end
|
609
|
+
|
610
|
+
attach_function :vips_init, [:string], :int
|
611
|
+
|
612
|
+
if Vips.vips_init($0) != 0
|
613
|
+
throw Vips.get_error
|
614
|
+
end
|
615
|
+
|
616
|
+
# don't use at_exit to call vips_shutdown, it causes problems with fork, and
|
617
|
+
# in any case libvips does this for us
|
618
|
+
|
619
|
+
attach_function :vips_leak_set, [:int], :void
|
620
|
+
attach_function :vips_vector_set_enabled, [:int], :void
|
621
|
+
attach_function :vips_concurrency_set, [:int], :void
|
622
|
+
|
623
|
+
# vips_foreign_get_suffixes was added in libvips 8.8
|
624
|
+
begin
|
625
|
+
attach_function :vips_foreign_get_suffixes, [], :pointer
|
626
|
+
rescue FFI::NotFoundError
|
627
|
+
nil
|
628
|
+
end
|
629
|
+
|
630
|
+
# Turn libvips leak testing on and off. Handy for debugging ruby-vips, not
|
631
|
+
# very useful for user code.
|
632
|
+
def self.leak_set leak
|
633
|
+
vips_leak_set((leak ? 1 : 0))
|
634
|
+
end
|
635
|
+
|
636
|
+
attach_function :vips_cache_set_max, [:int], :void
|
637
|
+
attach_function :vips_cache_set_max_mem, [:int], :void
|
638
|
+
attach_function :vips_cache_set_max_files, [:int], :void
|
639
|
+
|
640
|
+
# Set the maximum number of operations that libvips should cache. Set 0 to
|
641
|
+
# disable the operation cache. The default is 1000.
|
642
|
+
def self.cache_set_max size
|
643
|
+
vips_cache_set_max size
|
644
|
+
end
|
645
|
+
|
646
|
+
# Set the maximum amount of memory that libvips should use for the operation
|
647
|
+
# cache. Set 0 to disable the operation cache. The default is 100mb.
|
648
|
+
def self.cache_set_max_mem size
|
649
|
+
vips_cache_set_max_mem size
|
650
|
+
end
|
651
|
+
|
652
|
+
# Set the maximum number of files libvips should keep open in the
|
653
|
+
# operation cache. Set 0 to disable the operation cache. The default is
|
654
|
+
# 100.
|
655
|
+
def self.cache_set_max_files size
|
656
|
+
vips_cache_set_max_files size
|
657
|
+
end
|
658
|
+
|
659
|
+
# Set the size of the libvips worker pool. This defaults to the number of
|
660
|
+
# hardware threads on your computer. Set to 1 to disable threading.
|
661
|
+
def self.concurrency_set n
|
662
|
+
vips_concurrency_set n
|
663
|
+
end
|
664
|
+
|
665
|
+
# Enable or disable SIMD and the run-time compiler. This can give a nice
|
666
|
+
# speed-up, but can also be unstable on some systems or with some versions
|
667
|
+
# of the run-time compiler.
|
668
|
+
def self.vector_set enabled
|
669
|
+
vips_vector_set_enabled(enabled ? 1 : 0)
|
670
|
+
end
|
671
|
+
|
672
|
+
# Deprecated compatibility function.
|
673
|
+
#
|
674
|
+
# Don't use this, instead change GLib::logger.level.
|
675
|
+
def self.set_debug debug
|
676
|
+
if debug
|
677
|
+
GLib.logger.level = Logger::DEBUG
|
678
|
+
end
|
679
|
+
end
|
680
|
+
|
681
|
+
attach_function :version, :vips_version, [:int], :int
|
682
|
+
attach_function :version_string, :vips_version_string, [], :string
|
683
|
+
|
684
|
+
# True if this is at least libvips x.y
|
685
|
+
def self.at_least_libvips?(x, y)
|
686
|
+
major = version(0)
|
687
|
+
minor = version(1)
|
688
|
+
|
689
|
+
major > x || (major == x && minor >= y)
|
690
|
+
end
|
691
|
+
|
692
|
+
# Get a list of all supported file suffixes.
|
693
|
+
#
|
694
|
+
# @return [[String]] array of supported suffixes
|
695
|
+
def self.get_suffixes
|
696
|
+
# vips_foreign_get_suffixes() was added in libvips 8.8
|
697
|
+
return [] unless Vips.respond_to? :vips_foreign_get_suffixes
|
698
|
+
|
699
|
+
array = Vips.vips_foreign_get_suffixes
|
700
|
+
|
701
|
+
names = []
|
702
|
+
p = array
|
703
|
+
until (q = p.read_pointer).null?
|
704
|
+
suff = q.read_string
|
705
|
+
GLib.g_free q
|
706
|
+
names << suff unless names.include? suff
|
707
|
+
p += FFI::Type::POINTER.size
|
581
708
|
end
|
709
|
+
GLib.g_free array
|
582
710
|
|
583
|
-
|
711
|
+
names
|
712
|
+
end
|
584
713
|
|
585
|
-
|
586
|
-
# size. It's sometimes useful for know whan calculating image ratios.
|
587
|
-
MAX_COORD = 10000000
|
714
|
+
LIBRARY_VERSION = Vips.version_string
|
588
715
|
|
716
|
+
# libvips has this arbitrary number as a sanity-check upper bound on image
|
717
|
+
# size. It's sometimes useful to know when calculating scale factors.
|
718
|
+
MAX_COORD = 10000000
|
589
719
|
end
|
590
720
|
|
591
|
-
require
|
592
|
-
require
|
593
|
-
require
|
594
|
-
require
|
595
|
-
require
|
596
|
-
|
597
|
-
|
721
|
+
require "vips/object"
|
722
|
+
require "vips/operation"
|
723
|
+
require "vips/image"
|
724
|
+
require "vips/mutableimage"
|
725
|
+
require "vips/interpolate"
|
726
|
+
require "vips/region"
|
727
|
+
require "vips/version"
|
728
|
+
require "vips/connection"
|
729
|
+
require "vips/source"
|
730
|
+
require "vips/sourcecustom"
|
731
|
+
require "vips/target"
|
732
|
+
require "vips/targetcustom"
|