vips 8.6.3.2 → 8.8.2

Sign up to get free protection for your applications and to get access to all the features.
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
-