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/lib/vips/object.rb CHANGED
@@ -7,238 +7,229 @@
7
7
  require 'ffi'
8
8
 
9
9
  module Vips
10
- private
11
-
12
- # debugging support
13
- attach_function :vips_object_print_all, [], :void
14
-
15
- # we must init these by hand, since they are usually made on first image
16
- # create
17
- attach_function :vips_band_format_get_type, [], :GType
18
- attach_function :vips_interpretation_get_type, [], :GType
19
- attach_function :vips_coding_get_type, [], :GType
20
-
21
- public
22
-
23
- # some handy gtypes
24
- IMAGE_TYPE = GObject::g_type_from_name "VipsImage"
25
- ARRAY_INT_TYPE = GObject::g_type_from_name "VipsArrayInt"
26
- ARRAY_DOUBLE_TYPE = GObject::g_type_from_name "VipsArrayDouble"
27
- ARRAY_IMAGE_TYPE = GObject::g_type_from_name "VipsArrayImage"
28
- REFSTR_TYPE = GObject::g_type_from_name "VipsRefString"
29
- BLOB_TYPE = GObject::g_type_from_name "VipsBlob"
30
-
31
- BAND_FORMAT_TYPE = Vips::vips_band_format_get_type
32
- INTERPRETATION_TYPE = Vips::vips_interpretation_get_type
33
- CODING_TYPE = Vips::vips_coding_get_type
34
-
35
- if Vips::at_least_libvips?(8, 6)
36
- attach_function :vips_blend_mode_get_type, [], :GType
37
- BLEND_MODE_TYPE = Vips::vips_blend_mode_get_type
38
- else
39
- BLEND_MODE_TYPE = nil
10
+ private
11
+
12
+ # debugging support
13
+ attach_function :vips_object_print_all, [], :void
14
+
15
+ # we must init these by hand, since they are usually made on first image
16
+ # create
17
+ attach_function :vips_band_format_get_type, [], :GType
18
+ attach_function :vips_interpretation_get_type, [], :GType
19
+ attach_function :vips_coding_get_type, [], :GType
20
+
21
+ public
22
+
23
+ # some handy gtypes
24
+ IMAGE_TYPE = GObject::g_type_from_name "VipsImage"
25
+ ARRAY_INT_TYPE = GObject::g_type_from_name "VipsArrayInt"
26
+ ARRAY_DOUBLE_TYPE = GObject::g_type_from_name "VipsArrayDouble"
27
+ ARRAY_IMAGE_TYPE = GObject::g_type_from_name "VipsArrayImage"
28
+ REFSTR_TYPE = GObject::g_type_from_name "VipsRefString"
29
+ BLOB_TYPE = GObject::g_type_from_name "VipsBlob"
30
+
31
+ BAND_FORMAT_TYPE = Vips::vips_band_format_get_type
32
+ INTERPRETATION_TYPE = Vips::vips_interpretation_get_type
33
+ CODING_TYPE = Vips::vips_coding_get_type
34
+
35
+ if Vips::at_least_libvips?(8, 6)
36
+ attach_function :vips_blend_mode_get_type, [], :GType
37
+ BLEND_MODE_TYPE = Vips::vips_blend_mode_get_type
38
+ else
39
+ BLEND_MODE_TYPE = nil
40
+ end
41
+
42
+ private
43
+
44
+ attach_function :vips_enum_from_nick, [:string, :GType, :string], :int
45
+ attach_function :vips_enum_nick, [:GType, :int], :string
46
+
47
+ attach_function :vips_value_set_ref_string,
48
+ [GObject::GValue.ptr, :string], :void
49
+ attach_function :vips_value_set_array_double,
50
+ [GObject::GValue.ptr, :pointer, :int], :void
51
+ attach_function :vips_value_set_array_int,
52
+ [GObject::GValue.ptr, :pointer, :int], :void
53
+ attach_function :vips_value_set_array_image,
54
+ [GObject::GValue.ptr, :int], :void
55
+ callback :free_fn, [:pointer], :void
56
+ attach_function :vips_value_set_blob,
57
+ [GObject::GValue.ptr, :free_fn, :pointer, :size_t], :void
58
+
59
+ class SizeStruct < FFI::Struct
60
+ layout :value, :size_t
61
+ end
62
+
63
+ class IntStruct < FFI::Struct
64
+ layout :value, :int
65
+ end
66
+
67
+ attach_function :vips_value_get_ref_string,
68
+ [GObject::GValue.ptr, SizeStruct.ptr], :string
69
+ attach_function :vips_value_get_array_double,
70
+ [GObject::GValue.ptr, IntStruct.ptr], :pointer
71
+ attach_function :vips_value_get_array_int,
72
+ [GObject::GValue.ptr, IntStruct.ptr], :pointer
73
+ attach_function :vips_value_get_array_image,
74
+ [GObject::GValue.ptr, IntStruct.ptr], :pointer
75
+ attach_function :vips_value_get_blob,
76
+ [GObject::GValue.ptr, SizeStruct.ptr], :pointer
77
+
78
+ attach_function :type_find, :vips_type_find, [:string, :string], :GType
79
+
80
+ class Object < GObject::GObject
81
+ # print all active VipsObjects, with their reference counts. Handy for
82
+ # debugging ruby-vips.
83
+ def self.print_all
84
+ GC.start
85
+ Vips::vips_object_print_all
40
86
  end
41
87
 
42
- private
43
-
44
- attach_function :vips_enum_from_nick, [:string, :GType, :string], :int
45
- attach_function :vips_enum_nick, [:GType, :int], :string
46
-
47
- attach_function :vips_value_set_ref_string,
48
- [GObject::GValue.ptr, :string], :void
49
- attach_function :vips_value_set_array_double,
50
- [GObject::GValue.ptr, :pointer, :int], :void
51
- attach_function :vips_value_set_array_int,
52
- [GObject::GValue.ptr, :pointer, :int], :void
53
- attach_function :vips_value_set_array_image,
54
- [GObject::GValue.ptr, :int], :void
55
- callback :free_fn, [:pointer], :void
56
- attach_function :vips_value_set_blob,
57
- [GObject::GValue.ptr, :free_fn, :pointer, :size_t], :void
58
-
59
- class SizeStruct < FFI::Struct
60
- layout :value, :size_t
88
+ # the layout of the VipsObject struct
89
+ module ObjectLayout
90
+ def self.included base
91
+ base.class_eval do
92
+ # don't actually need most of these
93
+ layout :parent, GObject::GObject::Struct,
94
+ :constructed, :int,
95
+ :static_object, :int,
96
+ :argument_table, :pointer,
97
+ :nickname, :string,
98
+ :description, :string,
99
+ :preclose, :int,
100
+ :close, :int,
101
+ :postclose, :int,
102
+ :local_memory, :size_t
103
+ end
104
+ end
61
105
  end
62
106
 
63
- class IntStruct < FFI::Struct
64
- layout :value, :int
107
+ class Struct < GObject::GObject::Struct
108
+ include ObjectLayout
65
109
  end
66
110
 
67
- attach_function :vips_value_get_ref_string,
68
- [GObject::GValue.ptr, SizeStruct.ptr], :string
69
- attach_function :vips_value_get_array_double,
70
- [GObject::GValue.ptr, IntStruct.ptr], :pointer
71
- attach_function :vips_value_get_array_int,
72
- [GObject::GValue.ptr, IntStruct.ptr], :pointer
73
- attach_function :vips_value_get_array_image,
74
- [GObject::GValue.ptr, IntStruct.ptr], :pointer
75
- attach_function :vips_value_get_blob,
76
- [GObject::GValue.ptr, SizeStruct.ptr], :pointer
77
-
78
- attach_function :type_find, :vips_type_find, [:string, :string], :GType
79
-
80
- class Object < GObject::GObject
81
-
82
- # print all active VipsObjects, with their reference counts. Handy for
83
- # debugging ruby-vips.
84
- def self.print_all
85
- GC.start
86
- Vips::vips_object_print_all
87
- end
88
-
89
- # the layout of the VipsObject struct
90
- module ObjectLayout
91
- def self.included base
92
- base.class_eval do
93
- # don't actually need most of these
94
- layout :parent, GObject::GObject::Struct,
95
- :constructed, :int,
96
- :static_object, :int,
97
- :argument_table, :pointer,
98
- :nickname, :string,
99
- :description, :string,
100
- :preclose, :int,
101
- :close, :int,
102
- :postclose, :int,
103
- :local_memory, :size_t
104
- end
105
- end
106
- end
107
-
108
- class Struct < GObject::GObject::Struct
109
- include ObjectLayout
110
-
111
- end
112
-
113
- class ManagedStruct < GObject::GObject::ManagedStruct
114
- include ObjectLayout
115
-
116
- end
117
-
118
- # return a pspec, or nil ... nil wil leave a message in the error log
119
- # which you must clear
120
- def get_pspec name
121
- pspec = GObject::GParamSpecPtr.new
122
- argument_class = Vips::ArgumentClassPtr.new
123
- argument_instance = Vips::ArgumentInstancePtr.new
124
-
125
- result = Vips::vips_object_get_argument self, name,
126
- pspec, argument_class, argument_instance
127
- return nil if result != 0
128
-
129
- pspec
130
- end
131
-
132
- # return a gtype, raise an error on not found
133
- def get_typeof_error name
134
- pspec = get_pspec name
135
- raise Vips::Error unless pspec
136
-
137
- pspec[:value][:value_type]
138
- end
139
-
140
- # return a gtype, 0 on not found
141
- def get_typeof name
142
- pspec = get_pspec name
143
- unless pspec
144
- Vips::vips_error_clear
145
- return 0
146
- end
147
-
148
- pspec[:value][:value_type]
149
- end
150
-
151
- def get name
152
- gtype = get_typeof_error name
153
- gvalue = GObject::GValue.alloc
154
- gvalue.init gtype
155
- GObject::g_object_get_property self, name, gvalue
156
- result = gvalue.get
157
-
158
- GLib::logger.debug("Vips::Object.get") {"#{name} == #{result}"}
159
-
160
- return result
161
- end
162
-
163
- def set name, value
164
- GLib::logger.debug("Vips::Object.set") {"#{name} = #{value}"}
165
-
166
- gtype = get_typeof_error name
167
- gvalue = GObject::GValue.alloc
168
- gvalue.init gtype
169
- gvalue.set value
170
- GObject::g_object_set_property self, name, gvalue
171
- end
172
-
111
+ class ManagedStruct < GObject::GObject::ManagedStruct
112
+ include ObjectLayout
173
113
  end
174
114
 
175
- class ObjectClass < FFI::Struct
176
- # opaque
177
- end
115
+ # return a pspec, or nil ... nil wil leave a message in the error log
116
+ # which you must clear
117
+ def get_pspec name
118
+ pspec = GObject::GParamSpecPtr.new
119
+ argument_class = Vips::ArgumentClassPtr.new
120
+ argument_instance = Vips::ArgumentInstancePtr.new
178
121
 
179
- class Argument < FFI::Struct
180
- layout :pspec, GObject::GParamSpec.ptr
181
- end
122
+ result = Vips::vips_object_get_argument self, name,
123
+ pspec, argument_class, argument_instance
124
+ return nil if result != 0
182
125
 
183
- class ArgumentInstance < Argument
184
- layout :parent, Argument
185
- # rest opaque
126
+ pspec
186
127
  end
187
128
 
188
- # enum VipsArgumentFlags
189
- ARGUMENT_REQUIRED = 1
190
- ARGUMENT_CONSTRUCT = 2
191
- ARGUMENT_SET_ONCE = 4
192
- ARGUMENT_SET_ALWAYS = 8
193
- ARGUMENT_INPUT = 16
194
- ARGUMENT_OUTPUT = 32
195
- ARGUMENT_DEPRECATED = 64
196
- ARGUMENT_MODIFY = 128
197
-
198
- ARGUMENT_FLAGS = {
199
- :required => ARGUMENT_REQUIRED,
200
- :construct => ARGUMENT_CONSTRUCT,
201
- :set_once => ARGUMENT_SET_ONCE,
202
- :set_always => ARGUMENT_SET_ALWAYS,
203
- :input => ARGUMENT_INPUT,
204
- :output => ARGUMENT_OUTPUT,
205
- :deprecated => ARGUMENT_DEPRECATED,
206
- :modify => ARGUMENT_MODIFY
207
- }
208
-
209
- class ArgumentClass < Argument
210
- layout :parent, Argument,
211
- :object_class, ObjectClass.ptr,
212
- :flags, :uint,
213
- :priority, :int,
214
- :offset, :ulong_long
215
- end
129
+ # return a gtype, raise an error on not found
130
+ def get_typeof_error name
131
+ pspec = get_pspec name
132
+ raise Vips::Error unless pspec
216
133
 
217
- class ArgumentClassPtr < FFI::Struct
218
- layout :value, ArgumentClass.ptr
134
+ pspec[:value][:value_type]
219
135
  end
220
136
 
221
- class ArgumentInstancePtr < FFI::Struct
222
- layout :value, ArgumentInstance.ptr
223
- end
137
+ # return a gtype, 0 on not found
138
+ def get_typeof name
139
+ pspec = get_pspec name
140
+ unless pspec
141
+ Vips::vips_error_clear
142
+ return 0
143
+ end
224
144
 
225
- # just use :pointer, not VipsObject.ptr, to avoid casting gobject
226
- # subclasses
227
- attach_function :vips_object_get_argument,
228
- [:pointer, :string,
229
- GObject::GParamSpecPtr.ptr,
230
- ArgumentClassPtr.ptr, ArgumentInstancePtr.ptr],
231
- :int
145
+ pspec[:value][:value_type]
146
+ end
232
147
 
233
- attach_function :vips_object_print_all, [], :void
148
+ def get name
149
+ gtype = get_typeof_error name
150
+ gvalue = GObject::GValue.alloc
151
+ gvalue.init gtype
152
+ GObject::g_object_get_property self, name, gvalue
153
+ result = gvalue.get
234
154
 
235
- attach_function :vips_object_set_from_string, [:pointer, :string], :int
155
+ GLib::logger.debug("Vips::Object.get") { "#{name} == #{result}" }
236
156
 
237
- callback :type_map_fn, [:GType, :pointer], :pointer
238
- attach_function :vips_type_map, [:GType, :type_map_fn, :pointer], :pointer
157
+ return result
158
+ end
239
159
 
240
- attach_function :vips_object_get_description, [:pointer], :string
160
+ def set name, value
161
+ GLib::logger.debug("Vips::Object.set") { "#{name} = #{value}" }
241
162
 
163
+ gtype = get_typeof_error name
164
+ gvalue = GObject::GValue.alloc
165
+ gvalue.init gtype
166
+ gvalue.set value
167
+ GObject::g_object_set_property self, name, gvalue
168
+ end
169
+ end
170
+
171
+ class ObjectClass < FFI::Struct
172
+ # opaque
173
+ end
174
+
175
+ class Argument < FFI::Struct
176
+ layout :pspec, GObject::GParamSpec.ptr
177
+ end
178
+
179
+ class ArgumentInstance < Argument
180
+ layout :parent, Argument
181
+ # rest opaque
182
+ end
183
+
184
+ # enum VipsArgumentFlags
185
+ ARGUMENT_REQUIRED = 1
186
+ ARGUMENT_CONSTRUCT = 2
187
+ ARGUMENT_SET_ONCE = 4
188
+ ARGUMENT_SET_ALWAYS = 8
189
+ ARGUMENT_INPUT = 16
190
+ ARGUMENT_OUTPUT = 32
191
+ ARGUMENT_DEPRECATED = 64
192
+ ARGUMENT_MODIFY = 128
193
+
194
+ ARGUMENT_FLAGS = {
195
+ required: ARGUMENT_REQUIRED,
196
+ construct: ARGUMENT_CONSTRUCT,
197
+ set_once: ARGUMENT_SET_ONCE,
198
+ set_always: ARGUMENT_SET_ALWAYS,
199
+ input: ARGUMENT_INPUT,
200
+ output: ARGUMENT_OUTPUT,
201
+ deprecated: ARGUMENT_DEPRECATED,
202
+ modify: ARGUMENT_MODIFY
203
+ }
204
+
205
+ class ArgumentClass < Argument
206
+ layout :parent, Argument,
207
+ :object_class, ObjectClass.ptr,
208
+ :flags, :uint,
209
+ :priority, :int,
210
+ :offset, :ulong_long
211
+ end
212
+
213
+ class ArgumentClassPtr < FFI::Struct
214
+ layout :value, ArgumentClass.ptr
215
+ end
216
+
217
+ class ArgumentInstancePtr < FFI::Struct
218
+ layout :value, ArgumentInstance.ptr
219
+ end
220
+
221
+ # just use :pointer, not VipsObject.ptr, to avoid casting gobject
222
+ # subclasses
223
+ attach_function :vips_object_get_argument,
224
+ [:pointer, :string,
225
+ GObject::GParamSpecPtr.ptr,
226
+ ArgumentClassPtr.ptr, ArgumentInstancePtr.ptr],
227
+ :int
228
+
229
+ attach_function :vips_object_set_from_string, [:pointer, :string], :int
230
+
231
+ callback :type_map_fn, [:GType, :pointer], :pointer
232
+ attach_function :vips_type_map, [:GType, :type_map_fn, :pointer], :pointer
233
+
234
+ attach_function :vips_object_get_description, [:pointer], :string
242
235
  end
243
-
244
-
@@ -7,359 +7,353 @@
7
7
  require 'ffi'
8
8
 
9
9
  module Vips
10
- private
11
-
12
- attach_function :vips_operation_new, [:string], :pointer
13
-
14
- attach_function :vips_cache_operation_build, [:pointer], :pointer
15
- attach_function :vips_object_unref_outputs, [:pointer], :void
16
-
17
- callback :argument_map_fn, [:pointer,
18
- GObject::GParamSpec.ptr,
19
- ArgumentClass.ptr,
20
- ArgumentInstance.ptr,
21
- :pointer, :pointer], :pointer
22
- attach_function :vips_argument_map, [:pointer,
23
- :argument_map_fn,
24
- :pointer, :pointer], :pointer
25
-
26
- OPERATION_SEQUENTIAL = 1
27
- OPERATION_NOCACHE = 4
28
- OPERATION_DEPRECATED = 8
29
-
30
- OPERATION_FLAGS = {
31
- :sequential => OPERATION_SEQUENTIAL,
32
- :nocache => OPERATION_NOCACHE,
33
- :deprecated => OPERATION_DEPRECATED
34
- }
35
-
36
- attach_function :vips_operation_get_flags, [:pointer], :int
37
-
38
- class Operation < Object
39
-
40
- # the layout of the VipsOperation struct
41
- module OperationLayout
42
- def self.included base
43
- base.class_eval do
44
- layout :parent, Object::Struct
45
- # rest opaque
46
- end
47
- end
10
+ private
11
+
12
+ attach_function :vips_operation_new, [:string], :pointer
13
+
14
+ attach_function :vips_cache_operation_build, [:pointer], :pointer
15
+ attach_function :vips_object_unref_outputs, [:pointer], :void
16
+
17
+ callback :argument_map_fn, [:pointer,
18
+ GObject::GParamSpec.ptr,
19
+ ArgumentClass.ptr,
20
+ ArgumentInstance.ptr,
21
+ :pointer, :pointer], :pointer
22
+ attach_function :vips_argument_map, [:pointer,
23
+ :argument_map_fn,
24
+ :pointer, :pointer], :pointer
25
+
26
+ OPERATION_SEQUENTIAL = 1
27
+ OPERATION_NOCACHE = 4
28
+ OPERATION_DEPRECATED = 8
29
+
30
+ OPERATION_FLAGS = {
31
+ sequential: OPERATION_SEQUENTIAL,
32
+ nocache: OPERATION_NOCACHE,
33
+ deprecated: OPERATION_DEPRECATED
34
+ }
35
+
36
+ attach_function :vips_operation_get_flags, [:pointer], :int
37
+
38
+ class Operation < Object
39
+ # the layout of the VipsOperation struct
40
+ module OperationLayout
41
+ def self.included base
42
+ base.class_eval do
43
+ layout :parent, Object::Struct
44
+ # rest opaque
48
45
  end
46
+ end
47
+ end
49
48
 
50
- class Struct < Object::Struct
51
- include OperationLayout
49
+ class Struct < Object::Struct
50
+ include OperationLayout
51
+ end
52
52
 
53
- end
53
+ class ManagedStruct < Object::ManagedStruct
54
+ include OperationLayout
55
+ end
54
56
 
55
- class ManagedStruct < Object::ManagedStruct
56
- include OperationLayout
57
+ def initialize value
58
+ # allow init with a pointer so we can wrap the return values from
59
+ # things like _build
60
+ if value.is_a? String
61
+ value = Vips::vips_operation_new value
62
+ raise Vips::Error if value == nil
63
+ end
57
64
 
58
- end
65
+ super value
66
+ end
59
67
 
60
- def initialize value
61
- # allow init with a pointer so we can wrap the return values from
62
- # things like _build
63
- if value.is_a? String
64
- value = Vips::vips_operation_new value
65
- raise Vips::Error if value == nil
66
- end
68
+ def build
69
+ op = Vips::vips_cache_operation_build self
70
+ if op == nil
71
+ raise Vips::Error
72
+ end
67
73
 
68
- super value
69
- end
74
+ return Operation.new op
75
+ end
70
76
 
71
- def build
72
- op = Vips::vips_cache_operation_build self
73
- if op == nil
74
- raise Vips::Error
75
- end
77
+ def argument_map &block
78
+ fn = Proc.new do |_op, pspec, argument_class, argument_instance, _a, _b|
79
+ block.call pspec, argument_class, argument_instance
80
+ end
76
81
 
77
- return Operation.new op
78
- end
82
+ Vips::vips_argument_map self, fn, nil, nil
83
+ end
84
+
85
+ def get_flags
86
+ Vips::vips_operation_get_flags self
87
+ end
79
88
 
80
- def argument_map &block
81
- fn = Proc.new do |op, pspec, argument_class, argument_instance, a, b|
82
- block.call pspec, argument_class, argument_instance
83
- end
89
+ # not quick! try to call this infrequently
90
+ def get_construct_args
91
+ args = []
84
92
 
85
- Vips::vips_argument_map self, fn, nil, nil
86
- end
93
+ argument_map do |pspec, argument_class, _argument_instance|
94
+ flags = argument_class[:flags]
95
+ if (flags & ARGUMENT_CONSTRUCT) != 0
96
+ # names can include - as punctuation, but we always use _ in
97
+ # Ruby
98
+ name = pspec[:name].tr("-", "_")
87
99
 
88
- def get_flags
89
- Vips::vips_operation_get_flags self
100
+ args << [name, flags]
90
101
  end
102
+ end
91
103
 
92
- # not quick! try to call this infrequently
93
- def get_construct_args
94
- args = []
104
+ return args
105
+ end
95
106
 
96
- argument_map do |pspec, argument_class, argument_instance|
97
- flags = argument_class[:flags]
98
- if (flags & ARGUMENT_CONSTRUCT) != 0
99
- # names can include - as punctuation, but we always use _ in
100
- # Ruby
101
- name = pspec[:name].tr("-", "_")
107
+ # search array for the first element to match a predicate ...
108
+ # search inside subarrays and sub-hashes
109
+ def self.find_inside object, &block
110
+ return object if block.call object
102
111
 
103
- args << [name, flags]
104
- end
105
- end
112
+ if object.is_a? Enumerable
113
+ object.find { |value| block.call value, block }
114
+ end
106
115
 
107
- return args
108
- end
116
+ return nil
117
+ end
118
+
119
+ # expand a constant into an image
120
+ def self.imageize match_image, value
121
+ return value if value.is_a? Image
122
+
123
+ # 2D array values become tiny 2D images
124
+ # if there's nothing to match to, we also make a 2D image
125
+ if (value.is_a?(Array) && value[0].is_a?(Array)) ||
126
+ match_image == nil
127
+ return Image.new_from_array value
128
+ else
129
+ # we have a 1D array ... use that as a pixel constant and
130
+ # expand to match match_image
131
+ return match_image.new_from_image value
132
+ end
133
+ end
134
+
135
+ # set an operation argument, expanding constants and copying images as
136
+ # required
137
+ def set name, value, match_image = nil, flags = 0
138
+ gtype = get_typeof name
109
139
 
110
- # search array for the first element to match a predicate ...
111
- # search inside subarrays and sub-hashes
112
- def self.find_inside object, &block
113
- return object if block.call object
140
+ if gtype == IMAGE_TYPE
141
+ value = Operation::imageize match_image, value
114
142
 
115
- if object.is_a? Enumerable
116
- object.find {|value| block.call value, block}
117
- end
143
+ if (flags & ARGUMENT_MODIFY) != 0
144
+ # make sure we have a unique copy
145
+ value = value.copy.copy_memory
146
+ end
147
+ elsif gtype == ARRAY_IMAGE_TYPE
148
+ value = value.map { |x| Operation::imageize match_image, x }
149
+ end
150
+
151
+ super name, value
152
+ end
118
153
 
119
- return nil
154
+ public
155
+
156
+ # This is the public entry point for the vips binding. {call} will run
157
+ # any vips operation, for example:
158
+ #
159
+ # ```ruby
160
+ # out = Vips::Operation.call "black", [100, 100], {:bands => 12}
161
+ # ```
162
+ #
163
+ # will call the C function
164
+ #
165
+ # ```C
166
+ # vips_black( &out, 100, 100, "bands", 12, NULL );
167
+ # ```
168
+ #
169
+ # There are {Image#method_missing} hooks which will run {call} for you
170
+ # on {Image} for undefined instance or class methods. So you can also
171
+ # write:
172
+ #
173
+ # ```ruby
174
+ # out = Vips::Image.black 100, 100, bands: 12
175
+ # ```
176
+ #
177
+ # Or perhaps:
178
+ #
179
+ # ```ruby
180
+ # x = Vips::Image.black 100, 100
181
+ # y = x.invert
182
+ # ```
183
+ #
184
+ # to run the `vips_invert()` operator.
185
+ #
186
+ # There are also a set of operator overloads and some convenience
187
+ # functions, see {Image}.
188
+ #
189
+ # If the operator needs a vector constant, {call} will turn a scalar
190
+ # into a
191
+ # vector for you. So for `x.linear a, b`, which calculates
192
+ # `x * a + b` where `a` and `b` are vector constants, you can write:
193
+ #
194
+ # ```ruby
195
+ # x = Vips::Image.black 100, 100, bands: 3
196
+ # y = x.linear 1, 2
197
+ # y = x.linear [1], 4
198
+ # y = x.linear [1, 2, 3], 4
199
+ # ```
200
+ #
201
+ # or any other combination. The operator overloads use this facility to
202
+ # support all the variations on:
203
+ #
204
+ # ```ruby
205
+ # x = Vips::Image.black 100, 100, bands: 3
206
+ # y = x * 2
207
+ # y = x + [1,2,3]
208
+ # y = x % [1]
209
+ # ```
210
+ #
211
+ # Similarly, wherever an image is required, you can use a constant. The
212
+ # constant will be expanded to an image matching the first input image
213
+ # argument. For example, you can write:
214
+ #
215
+ # ```
216
+ # x = Vips::Image.black 100, 100, bands: 3
217
+ # y = x.bandjoin 255
218
+ # ```
219
+ #
220
+ # to add an extra band to the image where each pixel in the new band has
221
+ # the constant value 255.
222
+
223
+ def self.call name, supplied, optional = {}, option_string = ""
224
+ GLib::logger.debug("Vips::VipsOperation.call") {
225
+ "name = #{name}, supplied = #{supplied}, " +
226
+ "optional = #{optional}, option_string = #{option_string}"
227
+ }
228
+
229
+ op = Operation.new name
230
+
231
+ # find and classify all the arguments the operator can take
232
+ args = op.get_construct_args
233
+ required_input = []
234
+ optional_input = {}
235
+ required_output = []
236
+ optional_output = {}
237
+ args.each do |arg_name, flags|
238
+ next if (flags & ARGUMENT_DEPRECATED) != 0
239
+
240
+ if (flags & ARGUMENT_INPUT) != 0
241
+ if (flags & ARGUMENT_REQUIRED) != 0
242
+ required_input << [arg_name, flags]
243
+ else
244
+ optional_input[arg_name] = flags
245
+ end
120
246
  end
121
247
 
122
- # expand a constant into an image
123
- def self.imageize match_image, value
124
- return value if value.is_a? Image
125
-
126
- # 2D array values become tiny 2D images
127
- # if there's nothing to match to, we also make a 2D image
128
- if (value.is_a?(Array) && value[0].is_a?(Array)) ||
129
- match_image == nil
130
- return Image.new_from_array value
131
- else
132
- # we have a 1D array ... use that as a pixel constant and
133
- # expand to match match_image
134
- return match_image.new_from_image value
135
- end
248
+ # MODIFY INPUT args count as OUTPUT as well
249
+ if (flags & ARGUMENT_OUTPUT) != 0 ||
250
+ ((flags & ARGUMENT_INPUT) != 0 &&
251
+ (flags & ARGUMENT_MODIFY) != 0)
252
+ if (flags & ARGUMENT_REQUIRED) != 0
253
+ required_output << [arg_name, flags]
254
+ else
255
+ optional_output[arg_name] = flags
256
+ end
136
257
  end
258
+ end
259
+
260
+ # so we should have been supplied with n_required_input values, or
261
+ # n_required_input + 1 if there's a hash of options at the end
262
+ unless supplied.is_a? Array
263
+ raise Vips::Error, "unable to call #{name}: " +
264
+ "argument array is not an array"
265
+ end
266
+ unless optional.is_a? Hash
267
+ raise Vips::Error, "unable to call #{name}: " +
268
+ "optional arguments are not a hash"
269
+ end
270
+ if supplied.length != required_input.length
271
+ raise Vips::Error, "unable to call #{name}: " +
272
+ "you supplied #{supplied.length} arguments, " +
273
+ "but operation needs #{required_input.length}."
274
+ end
275
+
276
+ # very that all supplied_optional keys are in optional_input or
277
+ # optional_output
278
+ optional.each do |key, _value|
279
+ arg_name = key.to_s
280
+
281
+ unless optional_input.has_key?(arg_name) ||
282
+ optional_output.has_key?(arg_name)
283
+ raise Vips::Error, "unable to call #{name}: " +
284
+ "unknown option #{arg_name}"
285
+ end
286
+ end
287
+
288
+ # the first image arg is the thing we expand constants to match ...
289
+ # we need to find it
290
+ #
291
+ # look inside array and hash arguments, since we may be passing an
292
+ # array of images
293
+ match_image = find_inside(supplied) do |value|
294
+ value.is_a? Image
295
+ end
296
+
297
+ # set any string args first so they can't be overridden
298
+ if option_string != nil
299
+ if Vips::vips_object_set_from_string(op, option_string) != 0
300
+ raise Vips::Error
301
+ end
302
+ end
303
+
304
+ # set all required inputs
305
+ required_input.each_index do |i|
306
+ arg_name = required_input[i][0]
307
+ flags = required_input[i][1]
308
+ value = supplied[i]
309
+
310
+ op.set arg_name, value, match_image, flags
311
+ end
137
312
 
138
- # set an operation argument, expanding constants and copying images as
139
- # required
140
- def set name, value, match_image = nil, flags = 0
141
- gtype = get_typeof name
313
+ # set all optional inputs
314
+ optional.each do |key, value|
315
+ next if value.nil?
142
316
 
143
- if gtype == IMAGE_TYPE
144
- value = Operation::imageize match_image, value
317
+ arg_name = key.to_s
145
318
 
146
- if (flags & ARGUMENT_MODIFY) != 0
147
- # make sure we have a unique copy
148
- value = value.copy.copy_memory
149
- end
150
- elsif gtype == ARRAY_IMAGE_TYPE
151
- value = value.map {|x| Operation::imageize match_image, x}
152
- end
319
+ if optional_input.has_key? arg_name
320
+ flags = optional_input[arg_name]
153
321
 
154
- super name, value
322
+ op.set arg_name, value, match_image, flags
155
323
  end
324
+ end
156
325
 
157
- public
158
-
159
- # This is the public entry point for the vips binding. {call} will run
160
- # any vips operation, for example:
161
- #
162
- # ```ruby
163
- # out = Vips::Operation.call "black", [100, 100], {:bands => 12}
164
- # ```
165
- #
166
- # will call the C function
167
- #
168
- # ```C
169
- # vips_black( &out, 100, 100, "bands", 12, NULL );
170
- # ```
171
- #
172
- # There are {Image#method_missing} hooks which will run {call} for you
173
- # on {Image} for undefined instance or class methods. So you can also
174
- # write:
175
- #
176
- # ```ruby
177
- # out = Vips::Image.black 100, 100, bands: 12
178
- # ```
179
- #
180
- # Or perhaps:
181
- #
182
- # ```ruby
183
- # x = Vips::Image.black 100, 100
184
- # y = x.invert
185
- # ```
186
- #
187
- # to run the `vips_invert()` operator.
188
- #
189
- # There are also a set of operator overloads and some convenience
190
- # functions, see {Image}.
191
- #
192
- # If the operator needs a vector constant, {call} will turn a scalar
193
- # into a
194
- # vector for you. So for `x.linear a, b`, which calculates
195
- # `x * a + b` where `a` and `b` are vector constants, you can write:
196
- #
197
- # ```ruby
198
- # x = Vips::Image.black 100, 100, bands: 3
199
- # y = x.linear 1, 2
200
- # y = x.linear [1], 4
201
- # y = x.linear [1, 2, 3], 4
202
- # ```
203
- #
204
- # or any other combination. The operator overloads use this facility to
205
- # support all the variations on:
206
- #
207
- # ```ruby
208
- # x = Vips::Image.black 100, 100, bands: 3
209
- # y = x * 2
210
- # y = x + [1,2,3]
211
- # y = x % [1]
212
- # ```
213
- #
214
- # Similarly, wherever an image is required, you can use a constant. The
215
- # constant will be expanded to an image matching the first input image
216
- # argument. For example, you can write:
217
- #
218
- # ```
219
- # x = Vips::Image.black 100, 100, bands: 3
220
- # y = x.bandjoin 255
221
- # ```
222
- #
223
- # to add an extra band to the image where each pixel in the new band has
224
- # the constant value 255.
225
-
226
- def self.call name, supplied, optional = {}, option_string = ""
227
- GLib::logger.debug("Vips::VipsOperation.call") {
228
- "name = #{name}, supplied = #{supplied}, " +
229
- "optional = #{optional}, option_string = #{option_string}"
230
- }
231
-
232
- op = Operation.new name
233
-
234
- # find and classify all the arguments the operator can take
235
- args = op.get_construct_args
236
- required_input = []
237
- optional_input = {}
238
- required_output = []
239
- optional_output = {}
240
- args.each do |name, flags|
241
- next if (flags & ARGUMENT_DEPRECATED) != 0
242
-
243
- if (flags & ARGUMENT_INPUT) != 0
244
- if (flags & ARGUMENT_REQUIRED) != 0
245
- required_input << [name, flags]
246
- else
247
- optional_input[name] = flags
248
- end
249
- end
250
-
251
- # MODIFY INPUT args count as OUTPUT as well
252
- if (flags & ARGUMENT_OUTPUT) != 0 ||
253
- ((flags & ARGUMENT_INPUT) != 0 &&
254
- (flags & ARGUMENT_MODIFY) != 0)
255
- if (flags & ARGUMENT_REQUIRED) != 0
256
- required_output << [name, flags]
257
- else
258
- optional_output[name] = flags
259
- end
260
- end
261
-
262
- end
263
-
264
- # so we should have been supplied with n_required_input values, or
265
- # n_required_input + 1 if there's a hash of options at the end
266
- unless supplied.is_a? Array
267
- raise Vips::Error, "unable to call #{name}: " +
268
- "argument array is not an array"
269
- end
270
- unless optional.is_a? Hash
271
- raise Vips::Error, "unable to call #{name}: " +
272
- "optional arguments are not a hash"
273
- end
274
- if supplied.length != required_input.length
275
- raise Vips::Error, "unable to call #{name}: " +
276
- "you supplied #{supplied.length} arguments, " +
277
- "but operation needs #{required_input.length}."
278
- end
279
-
280
- # very that all supplied_optional keys are in optional_input or
281
- # optional_output
282
- optional.each do |key, value|
283
- arg_name = key.to_s
284
-
285
- unless optional_input.has_key?(arg_name) ||
286
- optional_output.has_key?(arg_name)
287
- raise Vips::Error, "unable to call #{name}: " +
288
- "unknown option #{arg_name}"
289
- end
290
- end
291
-
292
- # the first image arg is the thing we expand constants to match ...
293
- # we need to find it
294
- #
295
- # look inside array and hash arguments, since we may be passing an
296
- # array of images
297
- match_image = find_inside(supplied) do |value|
298
- value.is_a? Image
299
- end
300
-
301
- # set any string args first so they can't be overridden
302
- if option_string != nil
303
- if Vips::vips_object_set_from_string(op, option_string) != 0
304
- raise Vips::Error
305
- end
306
- end
307
-
308
- # set all required inputs
309
- required_input.each_index do |i|
310
- arg_name = required_input[i][0]
311
- flags = required_input[i][1]
312
- value = supplied[i]
313
-
314
- op.set arg_name, value, match_image, flags
315
- end
316
-
317
- # set all optional inputs
318
- optional.each do |key, value|
319
- arg_name = key.to_s
320
-
321
- if optional_input.has_key? arg_name
322
- flags = optional_input[arg_name]
323
-
324
- op.set arg_name, value, match_image, flags
325
- end
326
- end
327
-
328
- op = op.build
329
-
330
- # get all required results
331
- result = []
332
- required_output.each do |arg_name, flags|
333
- result << op.get(arg_name)
334
- end
335
-
336
- # fetch all optional ones
337
- optional_results = {}
338
- optional.each do |key, value|
339
- arg_name = key.to_s
340
-
341
- if optional_output.has_key? arg_name
342
- flags = optional_output[arg_name]
343
-
344
- optional_results[arg_name] = op.get arg_name
345
- end
346
- end
347
-
348
- result << optional_results if optional_results != {}
349
-
350
- if result.length == 1
351
- result = result.first
352
- elsif result.length == 0
353
- result = nil
354
- end
355
-
356
- GLib::logger.debug("Vips::Operation.call") {"result = #{result}"}
357
-
358
- Vips::vips_object_unref_outputs op
359
-
360
- return result
326
+ op = op.build
327
+
328
+ # get all required results
329
+ result = []
330
+ required_output.each do |arg_name, _flags|
331
+ result << op.get(arg_name)
332
+ end
333
+
334
+ # fetch all optional ones
335
+ optional_results = {}
336
+ optional.each do |key, _value|
337
+ arg_name = key.to_s
338
+
339
+ if optional_output.has_key? arg_name
340
+ optional_results[arg_name] = op.get arg_name
361
341
  end
342
+ end
362
343
 
363
- end
344
+ result << optional_results if optional_results != {}
364
345
 
346
+ if result.length == 1
347
+ result = result.first
348
+ elsif result.length == 0
349
+ result = nil
350
+ end
351
+
352
+ GLib::logger.debug("Vips::Operation.call") { "result = #{result}" }
353
+
354
+ Vips::vips_object_unref_outputs op
355
+
356
+ return result
357
+ end
358
+ end
365
359
  end