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.
- checksums.yaml +4 -4
- data/.rubocop.yml +10 -0
- data/.rubocop_todo.yml +730 -0
- data/.travis.yml +13 -6
- data/CHANGELOG.md +8 -0
- data/README.md +5 -8
- data/Rakefile +6 -0
- data/VERSION +1 -1
- data/example/annotate.rb +2 -2
- data/example/daltonize8.rb +14 -14
- data/example/example2.rb +6 -6
- data/example/example3.rb +5 -5
- data/example/example4.rb +4 -4
- data/example/example5.rb +2 -2
- data/example/inheritance_with_refcount.rb +207 -207
- data/example/thumb.rb +10 -10
- data/example/trim8.rb +2 -2
- data/example/watermark.rb +14 -35
- data/example/wobble.rb +24 -24
- data/install-vips.sh +1 -1
- data/lib/vips.rb +335 -306
- data/lib/vips/access.rb +9 -9
- data/lib/vips/align.rb +7 -7
- data/lib/vips/angle.rb +8 -8
- data/lib/vips/angle45.rb +12 -12
- data/lib/vips/bandformat.rb +16 -16
- data/lib/vips/blend_mode.rb +34 -0
- data/lib/vips/coding.rb +11 -11
- data/lib/vips/compass_direction.rb +13 -13
- data/lib/vips/direction.rb +7 -7
- data/lib/vips/extend.rb +13 -13
- data/lib/vips/gobject.rb +94 -94
- data/lib/vips/gvalue.rb +232 -232
- data/lib/vips/image.rb +1329 -1335
- data/lib/vips/interesting.rb +10 -10
- data/lib/vips/interpolate.rb +51 -51
- data/lib/vips/interpretation.rb +25 -25
- data/lib/vips/kernel.rb +18 -18
- data/lib/vips/methods.rb +463 -283
- data/lib/vips/object.rb +208 -208
- data/lib/vips/operation.rb +323 -323
- data/lib/vips/operationboolean.rb +10 -10
- data/lib/vips/operationcomplex.rb +8 -8
- data/lib/vips/operationcomplex2.rb +6 -6
- data/lib/vips/operationcomplexget.rb +7 -7
- data/lib/vips/operationmath.rb +14 -14
- data/lib/vips/operationmath2.rb +6 -6
- data/lib/vips/operationrelational.rb +11 -11
- data/lib/vips/operationround.rb +7 -7
- data/lib/vips/size.rb +9 -9
- data/lib/vips/version.rb +1 -1
- data/ruby-vips.gemspec +6 -2
- metadata +29 -6
data/lib/vips/object.rb
CHANGED
@@ -7,237 +7,237 @@
|
|
7
7
|
require 'ffi'
|
8
8
|
|
9
9
|
module Vips
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
+
|
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
|
40
87
|
end
|
41
88
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
-
|
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]
|
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
|
149
104
|
end
|
105
|
+
end
|
106
|
+
end
|
150
107
|
|
151
|
-
|
152
|
-
|
153
|
-
gvalue = GObject::GValue.alloc
|
154
|
-
gvalue.init gtype
|
155
|
-
GObject::g_object_get_property self, name, gvalue
|
156
|
-
result = gvalue.get
|
108
|
+
class Struct < GObject::GObject::Struct
|
109
|
+
include ObjectLayout
|
157
110
|
|
158
|
-
|
111
|
+
end
|
159
112
|
|
160
|
-
|
161
|
-
|
113
|
+
class ManagedStruct < GObject::GObject::ManagedStruct
|
114
|
+
include ObjectLayout
|
162
115
|
|
163
|
-
|
164
|
-
GLib::logger.debug("Vips::Object.set") {"#{name} = #{value}"}
|
116
|
+
end
|
165
117
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
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
|
172
124
|
|
173
|
-
|
125
|
+
result = Vips::vips_object_get_argument self, name,
|
126
|
+
pspec, argument_class, argument_instance
|
127
|
+
return nil if result != 0
|
174
128
|
|
175
|
-
|
176
|
-
# opaque
|
129
|
+
pspec
|
177
130
|
end
|
178
131
|
|
179
|
-
|
180
|
-
|
181
|
-
|
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
|
182
136
|
|
183
|
-
|
184
|
-
layout :parent, Argument
|
185
|
-
# rest opaque
|
137
|
+
pspec[:value][:value_type]
|
186
138
|
end
|
187
139
|
|
188
|
-
#
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
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
|
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
|
216
147
|
|
217
|
-
|
218
|
-
layout :value, ArgumentClass.ptr
|
148
|
+
pspec[:value][:value_type]
|
219
149
|
end
|
220
150
|
|
221
|
-
|
222
|
-
|
223
|
-
|
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
|
224
157
|
|
225
|
-
|
226
|
-
# subclasses
|
227
|
-
attach_function :vips_object_get_argument,
|
228
|
-
[:pointer, :string,
|
229
|
-
GObject::GParamSpecPtr.ptr,
|
230
|
-
ArgumentClassPtr.ptr, ArgumentInstancePtr.ptr],
|
231
|
-
:int
|
158
|
+
GLib::logger.debug("Vips::Object.get") {"#{name} == #{result}"}
|
232
159
|
|
233
|
-
|
160
|
+
return result
|
161
|
+
end
|
234
162
|
|
235
|
-
|
163
|
+
def set name, value
|
164
|
+
GLib::logger.debug("Vips::Object.set") {"#{name} = #{value}"}
|
236
165
|
|
237
|
-
|
238
|
-
|
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
|
239
172
|
|
240
|
-
|
173
|
+
end
|
174
|
+
|
175
|
+
class ObjectClass < FFI::Struct
|
176
|
+
# opaque
|
177
|
+
end
|
178
|
+
|
179
|
+
class Argument < FFI::Struct
|
180
|
+
layout :pspec, GObject::GParamSpec.ptr
|
181
|
+
end
|
182
|
+
|
183
|
+
class ArgumentInstance < Argument
|
184
|
+
layout :parent, Argument
|
185
|
+
# rest opaque
|
186
|
+
end
|
187
|
+
|
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
|
216
|
+
|
217
|
+
class ArgumentClassPtr < FFI::Struct
|
218
|
+
layout :value, ArgumentClass.ptr
|
219
|
+
end
|
220
|
+
|
221
|
+
class ArgumentInstancePtr < FFI::Struct
|
222
|
+
layout :value, ArgumentInstance.ptr
|
223
|
+
end
|
224
|
+
|
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
|
232
|
+
|
233
|
+
attach_function :vips_object_print_all, [], :void
|
234
|
+
|
235
|
+
attach_function :vips_object_set_from_string, [:pointer, :string], :int
|
236
|
+
|
237
|
+
callback :type_map_fn, [:GType, :pointer], :pointer
|
238
|
+
attach_function :vips_type_map, [:GType, :type_map_fn, :pointer], :pointer
|
239
|
+
|
240
|
+
attach_function :vips_object_get_description, [:pointer], :string
|
241
241
|
|
242
242
|
end
|
243
243
|
|
data/lib/vips/operation.rb
CHANGED
@@ -7,361 +7,361 @@
|
|
7
7
|
require 'ffi'
|
8
8
|
|
9
9
|
module Vips
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
+
|
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
|
48
46
|
end
|
47
|
+
end
|
48
|
+
end
|
49
49
|
|
50
|
-
|
51
|
-
|
50
|
+
class Struct < Object::Struct
|
51
|
+
include OperationLayout
|
52
52
|
|
53
|
-
|
53
|
+
end
|
54
54
|
|
55
|
-
|
56
|
-
|
55
|
+
class ManagedStruct < Object::ManagedStruct
|
56
|
+
include OperationLayout
|
57
57
|
|
58
|
-
|
58
|
+
end
|
59
59
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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
|
67
67
|
|
68
|
-
|
69
|
-
|
68
|
+
super value
|
69
|
+
end
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
71
|
+
def build
|
72
|
+
op = Vips::vips_cache_operation_build self
|
73
|
+
if op == nil
|
74
|
+
raise Vips::Error
|
75
|
+
end
|
76
76
|
|
77
|
-
|
78
|
-
|
77
|
+
return Operation.new op
|
78
|
+
end
|
79
79
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
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
|
84
84
|
|
85
|
-
|
86
|
-
|
85
|
+
Vips::vips_argument_map self, fn, nil, nil
|
86
|
+
end
|
87
|
+
|
88
|
+
def get_flags
|
89
|
+
Vips::vips_operation_get_flags self
|
90
|
+
end
|
91
|
+
|
92
|
+
# not quick! try to call this infrequently
|
93
|
+
def get_construct_args
|
94
|
+
args = []
|
87
95
|
|
88
|
-
|
89
|
-
|
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("-", "_")
|
102
|
+
|
103
|
+
args << [name, flags]
|
90
104
|
end
|
105
|
+
end
|
106
|
+
|
107
|
+
return args
|
108
|
+
end
|
109
|
+
|
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
|
91
114
|
|
92
|
-
|
93
|
-
|
94
|
-
|
115
|
+
if object.is_a? Enumerable
|
116
|
+
object.find {|value| block.call value, block}
|
117
|
+
end
|
95
118
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
119
|
+
return nil
|
120
|
+
end
|
121
|
+
|
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
|
136
|
+
end
|
102
137
|
|
103
|
-
|
104
|
-
|
105
|
-
|
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
|
106
142
|
|
107
|
-
|
143
|
+
if gtype == IMAGE_TYPE
|
144
|
+
value = Operation::imageize match_image, value
|
145
|
+
|
146
|
+
if (flags & ARGUMENT_MODIFY) != 0
|
147
|
+
# make sure we have a unique copy
|
148
|
+
value = value.copy.copy_memory
|
108
149
|
end
|
150
|
+
elsif gtype == ARRAY_IMAGE_TYPE
|
151
|
+
value = value.map {|x| Operation::imageize match_image, x}
|
152
|
+
end
|
109
153
|
|
110
|
-
|
111
|
-
|
112
|
-
def self.find_inside object, &block
|
113
|
-
return object if block.call object
|
154
|
+
super name, value
|
155
|
+
end
|
114
156
|
|
115
|
-
|
116
|
-
|
117
|
-
|
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
|
118
250
|
|
119
|
-
|
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
|
120
260
|
end
|
121
261
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
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
|
136
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
|
137
316
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
gtype = get_typeof name
|
317
|
+
# set all optional inputs
|
318
|
+
optional.each do |key, value|
|
319
|
+
next if value.nil?
|
142
320
|
|
143
|
-
|
144
|
-
value = Operation::imageize match_image, value
|
321
|
+
arg_name = key.to_s
|
145
322
|
|
146
|
-
|
147
|
-
|
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
|
323
|
+
if optional_input.has_key? arg_name
|
324
|
+
flags = optional_input[arg_name]
|
153
325
|
|
154
|
-
|
326
|
+
op.set arg_name, value, match_image, flags
|
155
327
|
end
|
328
|
+
end
|
156
329
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
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
|
-
next if value.nil?
|
320
|
-
|
321
|
-
arg_name = key.to_s
|
322
|
-
|
323
|
-
if optional_input.has_key? arg_name
|
324
|
-
flags = optional_input[arg_name]
|
325
|
-
|
326
|
-
op.set arg_name, value, match_image, flags
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
|
-
op = op.build
|
331
|
-
|
332
|
-
# get all required results
|
333
|
-
result = []
|
334
|
-
required_output.each do |arg_name, flags|
|
335
|
-
result << op.get(arg_name)
|
336
|
-
end
|
337
|
-
|
338
|
-
# fetch all optional ones
|
339
|
-
optional_results = {}
|
340
|
-
optional.each do |key, value|
|
341
|
-
arg_name = key.to_s
|
342
|
-
|
343
|
-
if optional_output.has_key? arg_name
|
344
|
-
flags = optional_output[arg_name]
|
345
|
-
|
346
|
-
optional_results[arg_name] = op.get arg_name
|
347
|
-
end
|
348
|
-
end
|
349
|
-
|
350
|
-
result << optional_results if optional_results != {}
|
351
|
-
|
352
|
-
if result.length == 1
|
353
|
-
result = result.first
|
354
|
-
elsif result.length == 0
|
355
|
-
result = nil
|
356
|
-
end
|
357
|
-
|
358
|
-
GLib::logger.debug("Vips::Operation.call") {"result = #{result}"}
|
359
|
-
|
360
|
-
Vips::vips_object_unref_outputs op
|
361
|
-
|
362
|
-
return result
|
330
|
+
op = op.build
|
331
|
+
|
332
|
+
# get all required results
|
333
|
+
result = []
|
334
|
+
required_output.each do |arg_name, flags|
|
335
|
+
result << op.get(arg_name)
|
336
|
+
end
|
337
|
+
|
338
|
+
# fetch all optional ones
|
339
|
+
optional_results = {}
|
340
|
+
optional.each do |key, value|
|
341
|
+
arg_name = key.to_s
|
342
|
+
|
343
|
+
if optional_output.has_key? arg_name
|
344
|
+
flags = optional_output[arg_name]
|
345
|
+
|
346
|
+
optional_results[arg_name] = op.get arg_name
|
363
347
|
end
|
348
|
+
end
|
349
|
+
|
350
|
+
result << optional_results if optional_results != {}
|
364
351
|
|
352
|
+
if result.length == 1
|
353
|
+
result = result.first
|
354
|
+
elsif result.length == 0
|
355
|
+
result = nil
|
356
|
+
end
|
357
|
+
|
358
|
+
GLib::logger.debug("Vips::Operation.call") {"result = #{result}"}
|
359
|
+
|
360
|
+
Vips::vips_object_unref_outputs op
|
361
|
+
|
362
|
+
return result
|
365
363
|
end
|
366
364
|
|
365
|
+
end
|
366
|
+
|
367
367
|
end
|