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/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