ruby-vips 2.0.13 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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"
|