ruby-vips 2.0.13 → 2.0.14

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +10 -0
  3. data/.rubocop_todo.yml +730 -0
  4. data/.travis.yml +13 -6
  5. data/CHANGELOG.md +8 -0
  6. data/README.md +5 -8
  7. data/Rakefile +6 -0
  8. data/VERSION +1 -1
  9. data/example/annotate.rb +2 -2
  10. data/example/daltonize8.rb +14 -14
  11. data/example/example2.rb +6 -6
  12. data/example/example3.rb +5 -5
  13. data/example/example4.rb +4 -4
  14. data/example/example5.rb +2 -2
  15. data/example/inheritance_with_refcount.rb +207 -207
  16. data/example/thumb.rb +10 -10
  17. data/example/trim8.rb +2 -2
  18. data/example/watermark.rb +14 -35
  19. data/example/wobble.rb +24 -24
  20. data/install-vips.sh +1 -1
  21. data/lib/vips.rb +335 -306
  22. data/lib/vips/access.rb +9 -9
  23. data/lib/vips/align.rb +7 -7
  24. data/lib/vips/angle.rb +8 -8
  25. data/lib/vips/angle45.rb +12 -12
  26. data/lib/vips/bandformat.rb +16 -16
  27. data/lib/vips/blend_mode.rb +34 -0
  28. data/lib/vips/coding.rb +11 -11
  29. data/lib/vips/compass_direction.rb +13 -13
  30. data/lib/vips/direction.rb +7 -7
  31. data/lib/vips/extend.rb +13 -13
  32. data/lib/vips/gobject.rb +94 -94
  33. data/lib/vips/gvalue.rb +232 -232
  34. data/lib/vips/image.rb +1329 -1335
  35. data/lib/vips/interesting.rb +10 -10
  36. data/lib/vips/interpolate.rb +51 -51
  37. data/lib/vips/interpretation.rb +25 -25
  38. data/lib/vips/kernel.rb +18 -18
  39. data/lib/vips/methods.rb +463 -283
  40. data/lib/vips/object.rb +208 -208
  41. data/lib/vips/operation.rb +323 -323
  42. data/lib/vips/operationboolean.rb +10 -10
  43. data/lib/vips/operationcomplex.rb +8 -8
  44. data/lib/vips/operationcomplex2.rb +6 -6
  45. data/lib/vips/operationcomplexget.rb +7 -7
  46. data/lib/vips/operationmath.rb +14 -14
  47. data/lib/vips/operationmath2.rb +6 -6
  48. data/lib/vips/operationrelational.rb +11 -11
  49. data/lib/vips/operationround.rb +7 -7
  50. data/lib/vips/size.rb +9 -9
  51. data/lib/vips/version.rb +1 -1
  52. data/ruby-vips.gemspec +6 -2
  53. metadata +29 -6
@@ -7,25 +7,25 @@
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
30
 
31
31
 
@@ -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
 
@@ -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]
@@ -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
@@ -1,6 +1,6 @@
1
1
  #!/bin/bash
2
2
 
3
- vips_site=https://github.com/jcupitt/libvips/releases/download
3
+ vips_site=https://github.com/libvips/libvips/releases/download
4
4
  version=$VIPS_VERSION_MAJOR.$VIPS_VERSION_MINOR.$VIPS_VERSION_MICRO
5
5
 
6
6
  set -e
@@ -7,157 +7,157 @@
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
 
115
+ end
116
+
117
117
  end
118
118
 
119
119
  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"
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
154
 
155
155
  end
156
156
 
157
157
  require 'vips/gobject'
158
158
  require 'vips/gvalue'
159
159
 
160
- # This module provides a binding for the [libvips image processing
160
+ # This module provides a binding for the [libvips image processing
161
161
  # library](https://jcupitt.github.io/libvips/).
162
162
  #
163
163
  # # Example
@@ -183,8 +183,8 @@ require 'vips/gvalue'
183
183
  # im.write_to_file ARGV[1]
184
184
  # ```
185
185
  #
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.
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.
188
188
  #
189
189
  # Reading this example line by line, we have:
190
190
  #
@@ -198,9 +198,9 @@ require 'vips/gvalue'
198
198
  # default mode is `:random`: this allows for full random access to image pixels,
199
199
  # but is slower and needs more memory. See {Access}
200
200
  # for full details
201
- # on the various modes available.
201
+ # on the various modes available.
202
202
  #
203
- # You can also load formatted images from
203
+ # You can also load formatted images from
204
204
  # memory buffers, create images that wrap C-style memory arrays, or make images
205
205
  # from constants.
206
206
  #
@@ -226,13 +226,13 @@ require 'vips/gvalue'
226
226
  # ```
227
227
  #
228
228
  # {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.
229
+ # the end sets the scale: the amount to divide the image by after
230
+ # integer convolution.
231
231
  #
232
232
  # See the libvips API docs for `vips_conv()` (the operation
233
233
  # 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.
234
+ # it computes with a float mask, but `:integer` is fine for this case, and is
235
+ # much faster.
236
236
  #
237
237
  # Finally:
238
238
  #
@@ -240,10 +240,10 @@ require 'vips/gvalue'
240
240
  # im.write_to_file ARGV[1]
241
241
  # ```
242
242
  #
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.
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.
247
247
  #
248
248
  # # How it works
249
249
  #
@@ -251,30 +251,30 @@ require 'vips/gvalue'
251
251
  # shared library. When you call a method on the image class, it uses libvips
252
252
  # introspection system (based on GObject) to search the
253
253
  # library for an operation of that name, transforms the arguments to a form
254
- # libvips can digest, and runs the operation.
254
+ # libvips can digest, and runs the operation.
255
255
  #
256
256
  # This means ruby-vips always presents the API implemented by the libvips shared
257
- # library. It should update itself as new features are added.
257
+ # library. It should update itself as new features are added.
258
258
  #
259
259
  # # Automatic wrapping
260
260
  #
261
261
  # `ruby-vips` adds a {Image.method_missing} handler to {Image} and uses
262
262
  # 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}.
263
+ # appears in C as `vips_add()`, appears in Ruby as {Image#add}.
264
264
  #
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
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
267
267
  # image, such as {Image.black}, appear as class methods. The remainder of
268
268
  # the arguments you supply in the function call are used to set the other
269
269
  # required input arguments. Any trailing keyword arguments are used to set
270
270
  # options on the operation.
271
- #
272
- # The result is the required output
271
+ #
272
+ # The result is the required output
273
273
  # argument if there is only one result, or an array of values if the operation
274
274
  # produces several results. If the operation has optional output objects, they
275
275
  # are returned as a final hash.
276
276
  #
277
- # For example, {Image#min}, the vips operation that searches an image for
277
+ # For example, {Image#min}, the vips operation that searches an image for
278
278
  # the minimum value, has a large number of optional arguments. You can use it to
279
279
  # find the minimum value like this:
280
280
  #
@@ -283,14 +283,14 @@ require 'vips/gvalue'
283
283
  # ```
284
284
  #
285
285
  # You can ask it to return the position of the minimum with `:x` and `:y`.
286
- #
286
+ #
287
287
  # ```ruby
288
288
  # min_value, opts = min x: true, y: true
289
289
  # x_pos = opts['x']
290
290
  # y_pos = opts['y']
291
291
  # ```
292
292
  #
293
- # Now `x_pos` and `y_pos` will have the coordinates of the minimum value.
293
+ # Now `x_pos` and `y_pos` will have the coordinates of the minimum value.
294
294
  # There's actually a convenience method for this, {Image#minpos}.
295
295
  #
296
296
  # You can also ask for the top *n* minimum, for example:
@@ -301,7 +301,7 @@ require 'vips/gvalue'
301
301
  # y_pos = opts['y_array']
302
302
  # ```
303
303
  #
304
- # Now `x_pos` and `y_pos` will be 10-element arrays.
304
+ # Now `x_pos` and `y_pos` will be 10-element arrays.
305
305
  #
306
306
  # Because operations are member functions and return the result image, you can
307
307
  # chain them. For example, you can write:
@@ -310,30 +310,30 @@ require 'vips/gvalue'
310
310
  # result_image = image.real.cos
311
311
  # ```
312
312
  #
313
- # to calculate the cosine of the real part of a complex image.
313
+ # to calculate the cosine of the real part of a complex image.
314
314
  # There are also a full set
315
315
  # of arithmetic operator overloads, see below.
316
316
  #
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
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
323
323
  # will be converted for you. You can write:
324
324
  #
325
325
  # ```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]
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]
330
330
  # ```
331
331
  #
332
332
  # And so on. A set of overloads are defined for {Image#linear}, see below.
333
333
  #
334
334
  # It does a couple of more ambitious conversions. It will automatically convert
335
335
  # 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:
336
+ # example, you can read the ICC profile out of an image like this:
337
337
  #
338
338
  # ```ruby
339
339
  # profile = im.get_value "icc-profile-data"
@@ -343,7 +343,7 @@ require 'vips/gvalue'
343
343
  #
344
344
  # If an operation takes several input images, you can use a constant for all but
345
345
  # 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
346
+ # example, {Image#ifthenelse} uses a condition image to pick pixels
347
347
  # between a then and an else image:
348
348
  #
349
349
  # ```ruby
@@ -360,7 +360,7 @@ require 'vips/gvalue'
360
360
  #
361
361
  # Will make an image where true pixels are green and false pixels are red.
362
362
  #
363
- # This is useful for {Image#bandjoin}, the thing to join two or more
363
+ # This is useful for {Image#bandjoin}, the thing to join two or more
364
364
  # images up bandwise. You can write:
365
365
  #
366
366
  # ```ruby
@@ -377,39 +377,39 @@ require 'vips/gvalue'
377
377
  # result_image = image1.bandjoin [image2, 255]
378
378
  # ```
379
379
  #
380
- # and so on.
380
+ # and so on.
381
381
  #
382
382
  # # Logging
383
383
  #
384
- # Libvips uses g_log() to log warning, debug, info and (some) error messages.
384
+ # Libvips uses g_log() to log warning, debug, info and (some) error messages.
385
385
  #
386
386
  # https://developer.gnome.org/glib/stable/glib-Message-Logging.html
387
387
  #
388
388
  # You can disable wanrings by defining the `VIPS_WARNING` environment variable.
389
- # You can enable info output by defining `VIPS_INFO`.
389
+ # You can enable info output by defining `VIPS_INFO`.
390
390
  #
391
391
  # # Exceptions
392
392
  #
393
393
  # The wrapper spots errors from vips operations and raises the {Vips::Error}
394
- # exception. You can catch it in the usual way.
394
+ # exception. You can catch it in the usual way.
395
395
  #
396
396
  # # Automatic YARD documentation
397
397
  #
398
- # The bulk of these API docs are generated automatically by
398
+ # The bulk of these API docs are generated automatically by
399
399
  # {Vips::generate_yard}. It examines
400
400
  # 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)
401
+ # that that operation expects.
402
+ #
403
+ # Use the [C API
404
+ # docs](https://jcupitt.github.io/libvips/API/current)
405
405
  # for more detail.
406
406
  #
407
407
  # # Enums
408
408
  #
409
409
  # The libvips enums, such as `VipsBandFormat` appear in ruby-vips as Symbols
410
410
  # like `:uchar`. They are documented as a set of classes for convenience, see
411
- # the class list.
412
- #
411
+ # the class list.
412
+ #
413
413
  # # Draw operations
414
414
  #
415
415
  # Paint operations like {Image#draw_circle} and {Image#draw_line}
@@ -421,7 +421,7 @@ require 'vips/gvalue'
421
421
  # image in memory before calling the operation. This stops crashes, but it does
422
422
  # make it inefficient. If you draw 100 lines on an image, for example, you'll
423
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.
424
+ # where possible, so you won't have 100 copies in memory.
425
425
  #
426
426
  # If you want to avoid the copies, you'll need to call drawing operations
427
427
  # yourself.
@@ -438,7 +438,7 @@ require 'vips/gvalue'
438
438
  #
439
439
  # # Expansions
440
440
  #
441
- # Some vips operators take an enum to select an action, for example
441
+ # Some vips operators take an enum to select an action, for example
442
442
  # {Image#math} can be used to calculate sine of every pixel like this:
443
443
  #
444
444
  # ```ruby
@@ -454,137 +454,166 @@ require 'vips/gvalue'
454
454
  #
455
455
  # # Convenience functions
456
456
  #
457
- # The wrapper defines a few extra useful utility functions:
458
- # {Image#get_value}, {Image#set_value}, {Image#bandsplit},
459
- # {Image#maxpos}, {Image#minpos},
457
+ # The wrapper defines a few extra useful utility functions:
458
+ # {Image#get_value}, {Image#set_value}, {Image#bandsplit},
459
+ # {Image#maxpos}, {Image#minpos},
460
460
  # {Image#median}.
461
461
 
462
462
  module Vips
463
- extend FFI::Library
464
-
465
- if FFI::Platform.windows?
466
- vips_libname = 'libvips-42.dll'
467
- else
468
- vips_libname = 'vips'
463
+ extend FFI::Library
464
+
465
+ if FFI::Platform.windows?
466
+ vips_libname = 'libvips-42.dll'
467
+ else
468
+ vips_libname = 'vips'
469
+ end
470
+
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
469
494
  end
470
495
 
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
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
548
505
  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
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
+ # vips_foreign_get_suffixes was added in libvips 8.8
522
+ begin
523
+ attach_function :vips_foreign_get_suffixes, [], :pointer
524
+ rescue FFI::NotFoundError
525
+ nil
526
+ end
527
+
528
+ # Turn libvips leak testing on and off. Handy for debugging ruby-vips, not
529
+ # very useful for user code.
530
+ def self.leak_set leak
531
+ vips_leak_set (leak ? 1 : 0)
532
+ end
533
+
534
+ attach_function :vips_cache_set_max, [:int], :void
535
+ attach_function :vips_cache_set_max_mem, [:int], :void
536
+ attach_function :vips_cache_set_max_files, [:int], :void
537
+
538
+ # Set the maximum number of operations that libvips should cache. Set 0 to
539
+ # disable the operation cache. The default is 1000.
540
+ def self.cache_set_max size
541
+ vips_cache_set_max size
542
+ end
543
+
544
+ # Set the maximum amount of memory that libvips should use for the operation
545
+ # cache. Set 0 to disable the operation cache. The default is 100mb.
546
+ def self.cache_set_max_mem size
547
+ vips_cache_set_max_mem size
548
+ end
549
+
550
+ # Set the maximum number of files libvips should keep open in the
551
+ # operation cache. Set 0 to disable the operation cache. The default is
552
+ # 100.
553
+ def self.cache_set_max_files size
554
+ vips_cache_set_max_files size
555
+ end
556
+
557
+ # Set the size of the libvips worker pool. This defaults to the number of
558
+ # hardware threads on your computer. Set to 1 to disable threading.
559
+ def self.concurrency_set n
560
+ vips_concurrency_set n
561
+ end
562
+
563
+ # Enable or disable SIMD and the run-time compiler. This can give a nice
564
+ # speed-up, but can also be unstable on some systems or with some versions
565
+ # of the run-time compiler.
566
+ def self.vector_set enabled
567
+ vips_vector_set_enabled(enabled ? 1 : 0)
568
+ end
569
+
570
+ # Deprecated compatibility function.
571
+ #
572
+ # Don't use this, instead change GLib::logger.level.
573
+ def self.set_debug debug
574
+ if debug
575
+ GLib::logger.level = Logger::DEBUG
554
576
  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)
577
+ end
578
+
579
+ attach_function :version, :vips_version, [:int], :int
580
+ attach_function :version_string, :vips_version_string, [], :string
581
+
582
+ # True if this is at least libvips x.y
583
+ def self.at_least_libvips?(x, y)
584
+ major = version(0)
585
+ minor = version(1)
586
+
587
+ major > x || (major == x && minor >= y)
588
+ end
589
+
590
+ # Get a list of all supported file suffixes.
591
+ #
592
+ # @return [[String]] array of supported suffixes
593
+ def self.get_suffixes
594
+ # vips_foreign_get_suffixes() was added in libvips 8.8
595
+ return [] unless Vips.respond_to? :vips_foreign_get_suffixes
596
+
597
+ array = Vips::vips_foreign_get_suffixes
598
+
599
+ names = []
600
+ p = array
601
+ until (q = p.read_pointer).null?
602
+ suff = q.read_string
603
+ GLib::g_free q
604
+ names << suff unless names.include? suff
605
+ p += FFI::Type::POINTER.size
561
606
  end
607
+ GLib::g_free array
562
608
 
563
- # Deprecated compatibility function.
564
- #
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
570
- 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)
581
- end
609
+ names
610
+ end
582
611
 
583
- LIBRARY_VERSION = Vips::version_string
612
+ LIBRARY_VERSION = Vips::version_string
584
613
 
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
614
+ # libvips has this arbitrary number as a sanity-check upper bound on image
615
+ # size. It's sometimes useful for know whan calculating image ratios.
616
+ MAX_COORD = 10000000
588
617
 
589
618
  end
590
619