vips 8.6.3.2 → 8.8.2

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +27 -22
  3. data/CHANGELOG.md +273 -0
  4. data/example/annotate.rb +2 -2
  5. data/example/daltonize8.rb +26 -28
  6. data/example/example1.rb +1 -2
  7. data/example/example2.rb +6 -6
  8. data/example/example3.rb +5 -5
  9. data/example/example4.rb +6 -6
  10. data/example/example5.rb +6 -7
  11. data/example/inheritance_with_refcount.rb +201 -218
  12. data/example/thumb.rb +10 -12
  13. data/example/trim8.rb +6 -6
  14. data/example/watermark.rb +14 -35
  15. data/example/wobble.rb +24 -24
  16. data/lib/vips.rb +335 -312
  17. data/lib/vips/access.rb +9 -9
  18. data/lib/vips/align.rb +7 -8
  19. data/lib/vips/angle.rb +8 -9
  20. data/lib/vips/angle45.rb +12 -13
  21. data/lib/vips/bandformat.rb +16 -18
  22. data/lib/vips/blend_mode.rb +32 -0
  23. data/lib/vips/coding.rb +11 -12
  24. data/lib/vips/compass_direction.rb +13 -14
  25. data/lib/vips/direction.rb +7 -8
  26. data/lib/vips/extend.rb +13 -14
  27. data/lib/vips/gobject.rb +92 -96
  28. data/lib/vips/gvalue.rb +231 -237
  29. data/lib/vips/image.rb +1329 -1330
  30. data/lib/vips/interesting.rb +10 -11
  31. data/lib/vips/interpolate.rb +49 -54
  32. data/lib/vips/interpretation.rb +25 -26
  33. data/lib/vips/kernel.rb +18 -19
  34. data/lib/vips/methods.rb +2319 -2141
  35. data/lib/vips/object.rb +204 -213
  36. data/lib/vips/operation.rb +317 -323
  37. data/lib/vips/operationboolean.rb +10 -11
  38. data/lib/vips/operationcomplex.rb +8 -9
  39. data/lib/vips/operationcomplex2.rb +6 -7
  40. data/lib/vips/operationcomplexget.rb +7 -8
  41. data/lib/vips/operationmath.rb +14 -15
  42. data/lib/vips/operationmath2.rb +6 -7
  43. data/lib/vips/operationrelational.rb +11 -12
  44. data/lib/vips/operationround.rb +7 -8
  45. data/lib/vips/size.rb +9 -10
  46. data/lib/vips/version.rb +1 -1
  47. data/vips.gemspec +1 -1
  48. metadata +9 -8
data/example/thumb.rb CHANGED
@@ -7,25 +7,23 @@
7
7
  require 'vips'
8
8
 
9
9
  # benchmark thumbnail via a memory buffer
10
- def via_memory(filename, thumbnail_width)
11
- data = IO.binread(filename)
10
+ def via_memory(filename, thumbnail_width)
11
+ data = IO.binread(filename)
12
12
 
13
- thumb = Vips::Image.thumbnail_buffer data, thumbnail_width, crop: 'centre'
13
+ thumb = Vips::Image.thumbnail_buffer data, thumbnail_width, crop: 'centre'
14
14
 
15
- thumb.write_to_buffer '.jpg'
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
- thumb = Vips::Image.thumbnail filename, thumbnail_width, crop: 'centre'
19
+ def via_files(filename, thumbnail_width)
20
+ thumb = Vips::Image.thumbnail filename, thumbnail_width, crop: 'centre'
21
21
 
22
- thumb.write_to_buffer '.jpg'
22
+ thumb.write_to_buffer '.jpg'
23
23
  end
24
24
 
25
25
  ARGV.each do |filename|
26
- puts "processing #{filename} ..."
27
- thumb = via_memory(filename, 500)
28
- # thumb = via_files(filename, 500)
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
@@ -11,11 +11,11 @@ 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
- first_column, first_row = columns.profile
26
+ _first_column, first_row = columns.profile
27
27
  left = first_row.min
28
28
 
29
- first_column, first_row = columns.fliphor.profile
29
+ _first_column, first_row = columns.fliphor.profile
30
30
  right = columns.width - first_row.min
31
31
 
32
- first_column, first_row = rows.profile
32
+ first_column, _first_row = rows.profile
33
33
  top = first_column.min
34
34
 
35
- first_column, first_row = rows.flipver.profile
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
3
  require 'vips'
4
-
5
- im = Vips::Image.new_from_file ARGV[0], :access => :sequential
6
-
7
- text = Vips::Image.text ARGV[2], :width => 500, :dpi => 300
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.embed 100, 100, text.width + 200, text.width + 200
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 want to blend into the visible part of the image and leave any alpha
14
- # channels untouched ... we need to split im into two parts
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
- marked = text.ifthenelse text_colour, im, :blend => true
20
+ # overlay the text
21
+ im = im.composite overlay, :over
40
22
 
41
- # reattach alpha
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
@@ -5,31 +5,31 @@ require 'vips'
5
5
  image = Vips::Image.new_from_file ARGV[0]
6
6
 
7
7
  module Vips
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
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/vips.rb CHANGED
@@ -7,157 +7,154 @@
7
7
  require 'ffi'
8
8
  require 'logger'
9
9
 
10
- # This module uses FFI to make a simple layer over the glib and gobject
11
- # libraries.
10
+ # This module uses FFI to make a simple layer over the glib and gobject
11
+ # libraries.
12
12
 
13
13
  module GLib
14
- class << self
15
- attr_accessor :logger
14
+ class << self
15
+ attr_accessor :logger
16
+ end
17
+ @logger = Logger.new(STDOUT)
18
+ @logger.level = Logger::WARN
19
+
20
+ extend FFI::Library
21
+
22
+ if FFI::Platform.windows?
23
+ glib_libname = 'libglib-2.0-0.dll'
24
+ else
25
+ glib_libname = 'glib-2.0'
26
+ end
27
+
28
+ ffi_lib glib_libname
29
+
30
+ attach_function :g_malloc, [:size_t], :pointer
31
+
32
+ # save the FFI::Function that attach will return ... we can use it directly
33
+ # as a param for callbacks
34
+ G_FREE = attach_function :g_free, [:pointer], :void
35
+
36
+ callback :g_log_func, [:string, :int, :string, :pointer], :void
37
+ attach_function :g_log_set_handler,
38
+ [:string, :int, :g_log_func, :pointer], :int
39
+ attach_function :g_log_remove_handler, [:string, :int], :void
40
+
41
+ # log flags
42
+ LOG_FLAG_RECURSION = 1 << 0
43
+ LOG_FLAG_FATAL = 1 << 1
44
+
45
+ # GLib log levels
46
+ LOG_LEVEL_ERROR = 1 << 2 # always fatal
47
+ LOG_LEVEL_CRITICAL = 1 << 3
48
+ LOG_LEVEL_WARNING = 1 << 4
49
+ LOG_LEVEL_MESSAGE = 1 << 5
50
+ LOG_LEVEL_INFO = 1 << 6
51
+ LOG_LEVEL_DEBUG = 1 << 7
52
+
53
+ # map glib levels to Logger::Severity
54
+ GLIB_TO_SEVERITY = {
55
+ LOG_LEVEL_ERROR => Logger::ERROR,
56
+ LOG_LEVEL_CRITICAL => Logger::FATAL,
57
+ LOG_LEVEL_WARNING => Logger::WARN,
58
+ LOG_LEVEL_MESSAGE => Logger::UNKNOWN,
59
+ LOG_LEVEL_INFO => Logger::INFO,
60
+ LOG_LEVEL_DEBUG => Logger::DEBUG
61
+ }
62
+ GLIB_TO_SEVERITY.default = Logger::UNKNOWN
63
+
64
+ # nil being the default
65
+ @glib_log_domain = nil
66
+ @glib_log_handler_id = 0
67
+
68
+ # module-level, so it's not GCd away
69
+ LOG_HANDLER = Proc.new do |domain, level, message, _user_data|
70
+ @logger.log(GLIB_TO_SEVERITY[level], message, domain)
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
16
77
  end
17
- @logger = Logger.new(STDOUT)
18
- @logger.level = Logger::WARN
19
-
20
- extend FFI::Library
21
-
22
- if FFI::Platform.windows?
23
- glib_libname = 'libglib-2.0-0.dll'
24
- else
25
- glib_libname = 'glib-2.0'
26
- end
27
-
28
- ffi_lib glib_libname
29
-
30
- attach_function :g_malloc, [:size_t], :pointer
31
-
32
- # save the FFI::Function that attach will return ... we can use it directly
33
- # as a param for callbacks
34
- G_FREE = attach_function :g_free, [:pointer], :void
35
-
36
- callback :g_log_func, [:string, :int, :string, :pointer], :void
37
- attach_function :g_log_set_handler,
38
- [:string, :int, :g_log_func, :pointer], :int
39
- attach_function :g_log_remove_handler, [:string, :int], :void
40
-
41
- # log flags
42
- LOG_FLAG_RECURSION = 1 << 0
43
- LOG_FLAG_FATAL = 1 << 1
44
-
45
- # GLib log levels
46
- LOG_LEVEL_ERROR = 1 << 2 # always fatal
47
- LOG_LEVEL_CRITICAL = 1 << 3
48
- LOG_LEVEL_WARNING = 1 << 4
49
- LOG_LEVEL_MESSAGE = 1 << 5
50
- LOG_LEVEL_INFO = 1 << 6
51
- LOG_LEVEL_DEBUG = 1 << 7
52
-
53
- # map glib levels to Logger::Severity
54
- GLIB_TO_SEVERITY = {
55
- LOG_LEVEL_ERROR => Logger::ERROR,
56
- LOG_LEVEL_CRITICAL => Logger::FATAL,
57
- LOG_LEVEL_WARNING => Logger::WARN,
58
- LOG_LEVEL_MESSAGE => Logger::UNKNOWN,
59
- LOG_LEVEL_INFO => Logger::INFO,
60
- LOG_LEVEL_DEBUG => Logger::DEBUG
61
- }
62
- GLIB_TO_SEVERITY.default = Logger::UNKNOWN
63
-
64
- # nil being the default
65
- @glib_log_domain = nil
66
- @glib_log_handler_id = 0
67
-
68
- # module-level, so it's not GCd away
69
- LOG_HANDLER = Proc.new do |domain, level, message, user_data|
70
- @logger.log(GLIB_TO_SEVERITY[level], message, domain)
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
78
- end
79
-
80
- def self.set_log_domain domain
78
+ end
79
+
80
+ def self.set_log_domain domain
81
+ GLib::remove_log_handler
82
+
83
+ @glib_log_domain = domain
84
+
85
+ # forward all glib logging output from this domain to a Ruby logger
86
+ if @glib_log_domain
87
+ # disable this feature for now
88
+ #
89
+ # libvips background worker threads can issue warnings, and
90
+ # since the main thread is blocked waiting for libvips to come back
91
+ # from an ffi call, you get a deadlock on the GIL
92
+ #
93
+ # to fix this, we need a way for g_log() calls from libvips workers
94
+ # to be returned via the main thread
95
+ #
96
+
97
+ # @glib_log_handler_id = g_log_set_handler @glib_log_domain,
98
+ # LOG_LEVEL_DEBUG |
99
+ # LOG_LEVEL_INFO |
100
+ # LOG_LEVEL_MESSAGE |
101
+ # LOG_LEVEL_WARNING |
102
+ # LOG_LEVEL_ERROR |
103
+ # LOG_LEVEL_CRITICAL |
104
+ # LOG_FLAG_FATAL | LOG_FLAG_RECURSION,
105
+ # LOG_HANDLER, nil
106
+
107
+ # we must remove any handlers on exit, since libvips may log stuff
108
+ # on shutdown and we don't want LOG_HANDLER to be invoked
109
+ # after Ruby has gone
110
+ at_exit {
81
111
  GLib::remove_log_handler
82
-
83
- @glib_log_domain = domain
84
-
85
- # forward all glib logging output from this domain to a Ruby logger
86
- if @glib_log_domain
87
- # disable this feature for now
88
- #
89
- # libvips background worker threads can issue warnings, and
90
- # since the main thread is blocked waiting for libvips to come back
91
- # from an ffi call, you get a deadlock on the GIL
92
- #
93
- # to fix this, we need a way for g_log() calls from libvips workers
94
- # to be returned via the main thread
95
- #
96
-
97
- # @glib_log_handler_id = g_log_set_handler @glib_log_domain,
98
- # LOG_LEVEL_DEBUG |
99
- # LOG_LEVEL_INFO |
100
- # LOG_LEVEL_MESSAGE |
101
- # LOG_LEVEL_WARNING |
102
- # LOG_LEVEL_ERROR |
103
- # LOG_LEVEL_CRITICAL |
104
- # LOG_FLAG_FATAL | LOG_FLAG_RECURSION,
105
- # LOG_HANDLER, nil
106
-
107
- # we must remove any handlers on exit, since libvips may log stuff
108
- # on shutdown and we don't want LOG_HANDLER to be invoked
109
- # after Ruby has gone
110
- at_exit {
111
- GLib::remove_log_handler
112
- }
113
- end
114
-
112
+ }
115
113
  end
116
-
114
+ end
117
115
  end
118
116
 
119
117
  module GObject
120
- extend FFI::Library
121
-
122
- if FFI::Platform.windows?
123
- gobject_libname = 'libgobject-2.0-0.dll'
124
- else
125
- gobject_libname = 'gobject-2.0'
126
- end
127
-
128
- ffi_lib gobject_libname
129
-
130
- # we can't just use ulong, windows has different int sizing rules
131
- if FFI::Platform::ADDRESS_SIZE == 64
132
- typedef :uint64, :GType
133
- else
134
- typedef :uint32, :GType
135
- end
136
-
137
- attach_function :g_type_init, [], :void
138
- attach_function :g_type_name, [:GType], :string
139
- attach_function :g_type_from_name, [:string], :GType
140
- attach_function :g_type_fundamental, [:GType], :GType
141
-
142
- # glib before 2.36 needed this, does nothing in current glib
143
- g_type_init
144
-
145
- # look up some common gtypes
146
- GBOOL_TYPE = g_type_from_name "gboolean"
147
- GINT_TYPE = g_type_from_name "gint"
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
-
118
+ extend FFI::Library
119
+
120
+ if FFI::Platform.windows?
121
+ gobject_libname = 'libgobject-2.0-0.dll'
122
+ else
123
+ gobject_libname = 'gobject-2.0'
124
+ end
125
+
126
+ ffi_lib gobject_libname
127
+
128
+ # we can't just use ulong, windows has different int sizing rules
129
+ if FFI::Platform::ADDRESS_SIZE == 64
130
+ typedef :uint64, :GType
131
+ else
132
+ typedef :uint32, :GType
133
+ end
134
+
135
+ attach_function :g_type_init, [], :void
136
+ attach_function :g_type_name, [:GType], :string
137
+ attach_function :g_type_from_name, [:string], :GType
138
+ attach_function :g_type_fundamental, [:GType], :GType
139
+
140
+ # glib before 2.36 needed this, does nothing in current glib
141
+ g_type_init
142
+
143
+ # look up some common gtypes
144
+ GBOOL_TYPE = g_type_from_name "gboolean"
145
+ GINT_TYPE = g_type_from_name "gint"
146
+ GUINT64_TYPE = g_type_from_name "guint64"
147
+ GDOUBLE_TYPE = g_type_from_name "gdouble"
148
+ GENUM_TYPE = g_type_from_name "GEnum"
149
+ GFLAGS_TYPE = g_type_from_name "GFlags"
150
+ GSTR_TYPE = g_type_from_name "gchararray"
151
+ GOBJECT_TYPE = g_type_from_name "GObject"
155
152
  end
156
153
 
157
154
  require 'vips/gobject'
158
155
  require 'vips/gvalue'
159
156
 
160
- # This module provides a binding for the [libvips image processing
157
+ # This module provides a binding for the [libvips image processing
161
158
  # library](https://jcupitt.github.io/libvips/).
162
159
  #
163
160
  # # Example
@@ -183,8 +180,8 @@ require 'vips/gvalue'
183
180
  # im.write_to_file ARGV[1]
184
181
  # ```
185
182
  #
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.
183
+ # This example loads a file, boosts the green channel (I'm not sure why),
184
+ # sharpens the image, and saves it back to disc again.
188
185
  #
189
186
  # Reading this example line by line, we have:
190
187
  #
@@ -198,9 +195,9 @@ require 'vips/gvalue'
198
195
  # default mode is `:random`: this allows for full random access to image pixels,
199
196
  # but is slower and needs more memory. See {Access}
200
197
  # for full details
201
- # on the various modes available.
198
+ # on the various modes available.
202
199
  #
203
- # You can also load formatted images from
200
+ # You can also load formatted images from
204
201
  # memory buffers, create images that wrap C-style memory arrays, or make images
205
202
  # from constants.
206
203
  #
@@ -226,13 +223,13 @@ require 'vips/gvalue'
226
223
  # ```
227
224
  #
228
225
  # {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.
226
+ # the end sets the scale: the amount to divide the image by after
227
+ # integer convolution.
231
228
  #
232
229
  # See the libvips API docs for `vips_conv()` (the operation
233
230
  # 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.
231
+ # it computes with a float mask, but `:integer` is fine for this case, and is
232
+ # much faster.
236
233
  #
237
234
  # Finally:
238
235
  #
@@ -240,10 +237,10 @@ require 'vips/gvalue'
240
237
  # im.write_to_file ARGV[1]
241
238
  # ```
242
239
  #
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.
240
+ # {Image#write_to_file} writes an image back to the filesystem. It can
241
+ # write any format supported by vips: the file type is set from the filename
242
+ # suffix. You can also write formatted images to memory buffers, or dump
243
+ # image data to a raw memory array.
247
244
  #
248
245
  # # How it works
249
246
  #
@@ -251,30 +248,30 @@ require 'vips/gvalue'
251
248
  # shared library. When you call a method on the image class, it uses libvips
252
249
  # introspection system (based on GObject) to search the
253
250
  # library for an operation of that name, transforms the arguments to a form
254
- # libvips can digest, and runs the operation.
251
+ # libvips can digest, and runs the operation.
255
252
  #
256
253
  # This means ruby-vips always presents the API implemented by the libvips shared
257
- # library. It should update itself as new features are added.
254
+ # library. It should update itself as new features are added.
258
255
  #
259
256
  # # Automatic wrapping
260
257
  #
261
258
  # `ruby-vips` adds a {Image.method_missing} handler to {Image} and uses
262
259
  # 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}.
260
+ # appears in C as `vips_add()`, appears in Ruby as {Image#add}.
264
261
  #
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
262
+ # The operation's list of required arguments is searched and the first input
263
+ # image is set to the value of `self`. Operations which do not take an input
267
264
  # image, such as {Image.black}, appear as class methods. The remainder of
268
265
  # the arguments you supply in the function call are used to set the other
269
266
  # required input arguments. Any trailing keyword arguments are used to set
270
267
  # options on the operation.
271
- #
272
- # The result is the required output
268
+ #
269
+ # The result is the required output
273
270
  # argument if there is only one result, or an array of values if the operation
274
271
  # produces several results. If the operation has optional output objects, they
275
272
  # are returned as a final hash.
276
273
  #
277
- # For example, {Image#min}, the vips operation that searches an image for
274
+ # For example, {Image#min}, the vips operation that searches an image for
278
275
  # the minimum value, has a large number of optional arguments. You can use it to
279
276
  # find the minimum value like this:
280
277
  #
@@ -283,14 +280,14 @@ require 'vips/gvalue'
283
280
  # ```
284
281
  #
285
282
  # You can ask it to return the position of the minimum with `:x` and `:y`.
286
- #
283
+ #
287
284
  # ```ruby
288
285
  # min_value, opts = min x: true, y: true
289
286
  # x_pos = opts['x']
290
287
  # y_pos = opts['y']
291
288
  # ```
292
289
  #
293
- # Now `x_pos` and `y_pos` will have the coordinates of the minimum value.
290
+ # Now `x_pos` and `y_pos` will have the coordinates of the minimum value.
294
291
  # There's actually a convenience method for this, {Image#minpos}.
295
292
  #
296
293
  # You can also ask for the top *n* minimum, for example:
@@ -301,7 +298,7 @@ require 'vips/gvalue'
301
298
  # y_pos = opts['y_array']
302
299
  # ```
303
300
  #
304
- # Now `x_pos` and `y_pos` will be 10-element arrays.
301
+ # Now `x_pos` and `y_pos` will be 10-element arrays.
305
302
  #
306
303
  # Because operations are member functions and return the result image, you can
307
304
  # chain them. For example, you can write:
@@ -310,30 +307,30 @@ require 'vips/gvalue'
310
307
  # result_image = image.real.cos
311
308
  # ```
312
309
  #
313
- # to calculate the cosine of the real part of a complex image.
310
+ # to calculate the cosine of the real part of a complex image.
314
311
  # There are also a full set
315
312
  # of arithmetic operator overloads, see below.
316
313
  #
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
314
+ # libvips types are also automatically wrapped. The override looks at the type
315
+ # of argument required by the operation and converts the value you supply,
316
+ # when it can. For example, {Image#linear} takes a `VipsArrayDouble` as
317
+ # an argument
318
+ # for the set of constants to use for multiplication. You can supply this
319
+ # value as an integer, a float, or some kind of compound object and it
323
320
  # will be converted for you. You can write:
324
321
  #
325
322
  # ```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]
323
+ # result_image = image.linear 1, 3
324
+ # result_image = image.linear 12.4, 13.9
325
+ # result_image = image.linear [1, 2, 3], [4, 5, 6]
326
+ # result_image = image.linear 1, [4, 5, 6]
330
327
  # ```
331
328
  #
332
329
  # And so on. A set of overloads are defined for {Image#linear}, see below.
333
330
  #
334
331
  # It does a couple of more ambitious conversions. It will automatically convert
335
332
  # 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:
333
+ # example, you can read the ICC profile out of an image like this:
337
334
  #
338
335
  # ```ruby
339
336
  # profile = im.get_value "icc-profile-data"
@@ -343,7 +340,7 @@ require 'vips/gvalue'
343
340
  #
344
341
  # If an operation takes several input images, you can use a constant for all but
345
342
  # 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
343
+ # example, {Image#ifthenelse} uses a condition image to pick pixels
347
344
  # between a then and an else image:
348
345
  #
349
346
  # ```ruby
@@ -360,7 +357,7 @@ require 'vips/gvalue'
360
357
  #
361
358
  # Will make an image where true pixels are green and false pixels are red.
362
359
  #
363
- # This is useful for {Image#bandjoin}, the thing to join two or more
360
+ # This is useful for {Image#bandjoin}, the thing to join two or more
364
361
  # images up bandwise. You can write:
365
362
  #
366
363
  # ```ruby
@@ -377,39 +374,39 @@ require 'vips/gvalue'
377
374
  # result_image = image1.bandjoin [image2, 255]
378
375
  # ```
379
376
  #
380
- # and so on.
377
+ # and so on.
381
378
  #
382
379
  # # Logging
383
380
  #
384
- # Libvips uses g_log() to log warning, debug, info and (some) error messages.
381
+ # Libvips uses g_log() to log warning, debug, info and (some) error messages.
385
382
  #
386
383
  # https://developer.gnome.org/glib/stable/glib-Message-Logging.html
387
384
  #
388
- # You can disable wanrings by defining the `VIPS_WARNING` environment variable.
389
- # You can enable info output by defining `VIPS_INFO`.
385
+ # You can disable warnings by defining the `VIPS_WARNING` environment variable.
386
+ # You can enable info output by defining `VIPS_INFO`.
390
387
  #
391
388
  # # Exceptions
392
389
  #
393
390
  # The wrapper spots errors from vips operations and raises the {Vips::Error}
394
- # exception. You can catch it in the usual way.
391
+ # exception. You can catch it in the usual way.
395
392
  #
396
393
  # # Automatic YARD documentation
397
394
  #
398
- # The bulk of these API docs are generated automatically by
395
+ # The bulk of these API docs are generated automatically by
399
396
  # {Vips::generate_yard}. It examines
400
397
  # libvips and writes a summary of each operation and the arguments and options
401
- # that that operation expects.
402
- #
403
- # Use the [C API
404
- # docs](https://jcupitt.github.io/libvips/API/current)
398
+ # that that operation expects.
399
+ #
400
+ # Use the [C API
401
+ # docs](https://jcupitt.github.io/libvips/API/current)
405
402
  # for more detail.
406
403
  #
407
404
  # # Enums
408
405
  #
409
406
  # The libvips enums, such as `VipsBandFormat` appear in ruby-vips as Symbols
410
407
  # like `:uchar`. They are documented as a set of classes for convenience, see
411
- # the class list.
412
- #
408
+ # the class list.
409
+ #
413
410
  # # Draw operations
414
411
  #
415
412
  # Paint operations like {Image#draw_circle} and {Image#draw_line}
@@ -421,7 +418,7 @@ require 'vips/gvalue'
421
418
  # image in memory before calling the operation. This stops crashes, but it does
422
419
  # make it inefficient. If you draw 100 lines on an image, for example, you'll
423
420
  # 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.
421
+ # where possible, so you won't have 100 copies in memory.
425
422
  #
426
423
  # If you want to avoid the copies, you'll need to call drawing operations
427
424
  # yourself.
@@ -438,7 +435,7 @@ require 'vips/gvalue'
438
435
  #
439
436
  # # Expansions
440
437
  #
441
- # Some vips operators take an enum to select an action, for example
438
+ # Some vips operators take an enum to select an action, for example
442
439
  # {Image#math} can be used to calculate sine of every pixel like this:
443
440
  #
444
441
  # ```ruby
@@ -454,138 +451,166 @@ require 'vips/gvalue'
454
451
  #
455
452
  # # Convenience functions
456
453
  #
457
- # The wrapper defines a few extra useful utility functions:
458
- # {Image#get_value}, {Image#set_value}, {Image#bandsplit},
459
- # {Image#maxpos}, {Image#minpos},
454
+ # The wrapper defines a few extra useful utility functions:
455
+ # {Image#get_value}, {Image#set_value}, {Image#bandsplit},
456
+ # {Image#maxpos}, {Image#minpos},
460
457
  # {Image#median}.
461
458
 
462
459
  module Vips
463
- extend FFI::Library
464
-
465
- if FFI::Platform.windows?
466
- vips_libname = 'libvips-42.dll'
467
- else
468
- vips_libname = File.expand_path(FFI::map_library_name('vips'), __dir__)
460
+ extend FFI::Library
461
+
462
+ if FFI::Platform.windows?
463
+ vips_libname = 'libvips-42.dll'
464
+ else
465
+ vips_libname = File.expand_path(FFI::map_library_name('vips'), __dir__)
466
+ end
467
+
468
+ ffi_lib vips_libname
469
+
470
+ LOG_DOMAIN = "VIPS"
471
+ GLib::set_log_domain LOG_DOMAIN
472
+
473
+ typedef :ulong, :GType
474
+
475
+ attach_function :vips_error_buffer, [], :string
476
+ attach_function :vips_error_clear, [], :void
477
+
478
+ # The ruby-vips error class.
479
+ class Error < RuntimeError
480
+ # @param msg [String] The error message. If this is not supplied, grab
481
+ # and clear the vips error buffer and use that.
482
+ def initialize msg = nil
483
+ if msg
484
+ @details = msg
485
+ elsif Vips::vips_error_buffer != ""
486
+ @details = Vips::vips_error_buffer
487
+ Vips::vips_error_clear
488
+ else
489
+ @details = nil
490
+ end
469
491
  end
470
492
 
471
- ffi_lib vips_libname
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.
493
+ # Pretty-print a {Vips::Error}.
564
494
  #
565
- # Don't use this, instead change GLib::logger.level.
566
- def self.set_debug debug
567
- if debug
568
- GLib::logger.level = Logger::DEBUG
569
- end
495
+ # @return [String] The error message
496
+ def to_s
497
+ if @details != nil
498
+ @details
499
+ else
500
+ super.to_s
501
+ end
570
502
  end
571
-
572
- attach_function :version, :vips_version, [:int], :int
573
- attach_function :version_string, :vips_version_string, [], :string
574
-
575
- # True if this is at least libvips x.y
576
- def self.at_least_libvips?(x, y)
577
- major = version(0)
578
- minor = version(1)
579
-
580
- major > x || (major == x && minor >= y)
503
+ end
504
+
505
+ attach_function :vips_init, [:string], :int
506
+
507
+ if Vips::vips_init($0) != 0
508
+ throw Vips::get_error
509
+ end
510
+
511
+ # don't use at_exit to call vips_shutdown, it causes problems with fork, and
512
+ # in any case libvips does this for us
513
+
514
+ attach_function :vips_leak_set, [:int], :void
515
+ attach_function :vips_vector_set_enabled, [:int], :void
516
+ attach_function :vips_concurrency_set, [:int], :void
517
+
518
+ # vips_foreign_get_suffixes was added in libvips 8.8
519
+ begin
520
+ attach_function :vips_foreign_get_suffixes, [], :pointer
521
+ rescue FFI::NotFoundError
522
+ nil
523
+ end
524
+
525
+ # Turn libvips leak testing on and off. Handy for debugging ruby-vips, not
526
+ # very useful for user code.
527
+ def self.leak_set leak
528
+ vips_leak_set((leak ? 1 : 0))
529
+ end
530
+
531
+ attach_function :vips_cache_set_max, [:int], :void
532
+ attach_function :vips_cache_set_max_mem, [:int], :void
533
+ attach_function :vips_cache_set_max_files, [:int], :void
534
+
535
+ # Set the maximum number of operations that libvips should cache. Set 0 to
536
+ # disable the operation cache. The default is 1000.
537
+ def self.cache_set_max size
538
+ vips_cache_set_max size
539
+ end
540
+
541
+ # Set the maximum amount of memory that libvips should use for the operation
542
+ # cache. Set 0 to disable the operation cache. The default is 100mb.
543
+ def self.cache_set_max_mem size
544
+ vips_cache_set_max_mem size
545
+ end
546
+
547
+ # Set the maximum number of files libvips should keep open in the
548
+ # operation cache. Set 0 to disable the operation cache. The default is
549
+ # 100.
550
+ def self.cache_set_max_files size
551
+ vips_cache_set_max_files size
552
+ end
553
+
554
+ # Set the size of the libvips worker pool. This defaults to the number of
555
+ # hardware threads on your computer. Set to 1 to disable threading.
556
+ def self.concurrency_set n
557
+ vips_concurrency_set n
558
+ end
559
+
560
+ # Enable or disable SIMD and the run-time compiler. This can give a nice
561
+ # speed-up, but can also be unstable on some systems or with some versions
562
+ # of the run-time compiler.
563
+ def self.vector_set enabled
564
+ vips_vector_set_enabled(enabled ? 1 : 0)
565
+ end
566
+
567
+ # Deprecated compatibility function.
568
+ #
569
+ # Don't use this, instead change GLib::logger.level.
570
+ def self.set_debug debug
571
+ if debug
572
+ GLib::logger.level = Logger::DEBUG
581
573
  end
574
+ end
575
+
576
+ attach_function :version, :vips_version, [:int], :int
577
+ attach_function :version_string, :vips_version_string, [], :string
578
+
579
+ # True if this is at least libvips x.y
580
+ def self.at_least_libvips?(x, y)
581
+ major = version(0)
582
+ minor = version(1)
583
+
584
+ major > x || (major == x && minor >= y)
585
+ end
586
+
587
+ # Get a list of all supported file suffixes.
588
+ #
589
+ # @return [[String]] array of supported suffixes
590
+ def self.get_suffixes
591
+ # vips_foreign_get_suffixes() was added in libvips 8.8
592
+ return [] unless Vips.respond_to? :vips_foreign_get_suffixes
593
+
594
+ array = Vips::vips_foreign_get_suffixes
595
+
596
+ names = []
597
+ p = array
598
+ until (q = p.read_pointer).null?
599
+ suff = q.read_string
600
+ GLib::g_free q
601
+ names << suff unless names.include? suff
602
+ p += FFI::Type::POINTER.size
603
+ end
604
+ GLib::g_free array
582
605
 
583
- LIBRARY_VERSION = Vips::version_string
606
+ names
607
+ end
584
608
 
585
- # libvips has this arbitrary number as a sanity-check upper bound on image
586
- # size. It's sometimes useful for know whan calculating image ratios.
587
- MAX_COORD = 10000000
609
+ LIBRARY_VERSION = Vips::version_string
588
610
 
611
+ # libvips has this arbitrary number as a sanity-check upper bound on image
612
+ # size. It's sometimes useful for know whan calculating image ratios.
613
+ MAX_COORD = 10000000
589
614
  end
590
615
 
591
616
  require 'vips/object'
@@ -593,5 +618,3 @@ require 'vips/operation'
593
618
  require 'vips/image'
594
619
  require 'vips/interpolate'
595
620
  require 'vips/version'
596
-
597
-