ruby-vips 2.0.13 → 2.1.0
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/.github/ISSUE_TEMPLATE/bug_report.md +42 -0
- data/.github/workflows/test.yml +80 -0
- data/.standard.yml +17 -0
- data/.yardopts +0 -1
- data/CHANGELOG.md +44 -0
- data/Gemfile +3 -1
- data/README.md +45 -47
- data/Rakefile +13 -15
- data/TODO +19 -10
- data/VERSION +1 -1
- data/example/annotate.rb +7 -7
- data/example/connection.rb +26 -0
- data/example/daltonize8.rb +27 -29
- data/example/draw_lines.rb +30 -0
- data/example/example1.rb +5 -6
- data/example/example2.rb +11 -11
- data/example/example3.rb +9 -9
- data/example/example4.rb +8 -8
- data/example/example5.rb +8 -9
- data/example/inheritance_with_refcount.rb +203 -221
- data/example/progress.rb +30 -0
- data/example/thumb.rb +12 -14
- data/example/trim8.rb +7 -7
- data/example/watermark.rb +15 -36
- data/example/wobble.rb +25 -25
- data/lib/ruby-vips.rb +1 -1
- data/lib/vips.rb +473 -338
- data/lib/vips/access.rb +9 -9
- data/lib/vips/align.rb +7 -8
- data/lib/vips/angle.rb +8 -9
- data/lib/vips/angle45.rb +12 -13
- data/lib/vips/bandformat.rb +16 -18
- data/lib/vips/blend_mode.rb +36 -0
- data/lib/vips/coding.rb +11 -12
- data/lib/vips/compass_direction.rb +13 -14
- data/lib/vips/connection.rb +46 -0
- data/lib/vips/direction.rb +7 -8
- data/lib/vips/extend.rb +13 -14
- data/lib/vips/gobject.rb +111 -100
- data/lib/vips/gvalue.rb +243 -237
- data/lib/vips/image.rb +1501 -1338
- data/lib/vips/interesting.rb +10 -11
- data/lib/vips/interpolate.rb +50 -54
- data/lib/vips/interpretation.rb +25 -26
- data/lib/vips/kernel.rb +18 -19
- data/lib/vips/methods.rb +929 -309
- data/lib/vips/mutableimage.rb +154 -0
- data/lib/vips/object.rb +318 -208
- data/lib/vips/operation.rb +467 -320
- data/lib/vips/operationboolean.rb +10 -11
- data/lib/vips/operationcomplex.rb +8 -9
- data/lib/vips/operationcomplex2.rb +6 -7
- data/lib/vips/operationcomplexget.rb +7 -8
- data/lib/vips/operationmath.rb +14 -15
- data/lib/vips/operationmath2.rb +6 -7
- data/lib/vips/operationrelational.rb +11 -12
- data/lib/vips/operationround.rb +7 -8
- data/lib/vips/region.rb +73 -0
- data/lib/vips/size.rb +9 -10
- data/lib/vips/source.rb +88 -0
- data/lib/vips/sourcecustom.rb +89 -0
- data/lib/vips/target.rb +86 -0
- data/lib/vips/targetcustom.rb +77 -0
- data/lib/vips/version.rb +1 -2
- data/ruby-vips.gemspec +29 -20
- metadata +51 -40
- data/.travis.yml +0 -55
- data/install-vips.sh +0 -26
@@ -0,0 +1,154 @@
|
|
1
|
+
# This module provides an interface to the vips image processing library
|
2
|
+
# via ruby-ffi.
|
3
|
+
#
|
4
|
+
# Author:: John Cupitt (mailto:jcupitt@gmail.com)
|
5
|
+
# License:: MIT
|
6
|
+
|
7
|
+
require "ffi"
|
8
|
+
require "forwardable"
|
9
|
+
|
10
|
+
module Vips
|
11
|
+
# This class represents a libvips image which can be modified. See
|
12
|
+
# {Vips::Image#mutate}.
|
13
|
+
class MutableImage < Vips::Object
|
14
|
+
extend Forwardable
|
15
|
+
alias_method :parent_get_typeof, :get_typeof
|
16
|
+
def_instance_delegators :@image, :width, :height, :bands, :format,
|
17
|
+
:interpretation, :filename, :xoffset, :yoffset, :xres, :yres, :size,
|
18
|
+
:get, :get_typeof, :get_fields
|
19
|
+
|
20
|
+
# layout is exactly as {Image} (since we are also wrapping a VipsImage
|
21
|
+
# object)
|
22
|
+
module MutableImageLayout
|
23
|
+
def self.included base
|
24
|
+
base.class_eval do
|
25
|
+
layout :parent, Vips::Object::Struct
|
26
|
+
# rest opaque
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Struct < Vips::Object::Struct
|
32
|
+
include MutableImageLayout
|
33
|
+
end
|
34
|
+
|
35
|
+
class ManagedStruct < Vips::Object::ManagedStruct
|
36
|
+
include MutableImageLayout
|
37
|
+
end
|
38
|
+
|
39
|
+
# Get the {Image} this {MutableImage} is modifying. Only use this once you
|
40
|
+
# have finished all modifications.
|
41
|
+
#
|
42
|
+
# This is for internal use only. See {Vips::Image#mutate} for the
|
43
|
+
# user-facing interface.
|
44
|
+
attr_reader :image
|
45
|
+
|
46
|
+
# Make a {MutableImage} from a regular {Image}.
|
47
|
+
#
|
48
|
+
# This is for internal use only. See {Vips::Image#mutate} for the
|
49
|
+
# user-facing interface.
|
50
|
+
def initialize(image)
|
51
|
+
# We take a copy of the regular Image to ensure we have an unshared
|
52
|
+
# (unique) object. We forward things like #width and #height to this, and
|
53
|
+
# it's the thing we return at the end of the mutate block.
|
54
|
+
copy_image = image.copy
|
55
|
+
|
56
|
+
# use ptr since we need the raw unwrapped pointer inside the image ...
|
57
|
+
# and make the ref that gobject will unref when it finishes
|
58
|
+
pointer = copy_image.ptr
|
59
|
+
::GObject.g_object_ref pointer
|
60
|
+
super pointer
|
61
|
+
|
62
|
+
# and save the copy ready for when we finish mutating
|
63
|
+
@image = copy_image
|
64
|
+
end
|
65
|
+
|
66
|
+
def inspect
|
67
|
+
"#<MutableImage #{width}x#{height} #{format}, #{bands} bands, #{interpretation}>"
|
68
|
+
end
|
69
|
+
|
70
|
+
def respond_to? name, include_all = false
|
71
|
+
# To support keyword args, we need to tell Ruby that final image
|
72
|
+
# arguments cannot be hashes of keywords.
|
73
|
+
#
|
74
|
+
# https://makandracards.com/makandra/
|
75
|
+
# 36013-heads-up-ruby-implicitly-converts-a-hash-to-keyword-arguments
|
76
|
+
return false if name == :to_hash
|
77
|
+
|
78
|
+
super
|
79
|
+
end
|
80
|
+
|
81
|
+
def respond_to_missing? name, include_all = false
|
82
|
+
# respond to all vips operations by nickname
|
83
|
+
return true if Vips.type_find("VipsOperation", name.to_s) != 0
|
84
|
+
|
85
|
+
super
|
86
|
+
end
|
87
|
+
|
88
|
+
# Invoke a vips operation with {Vips::Operation#call}, using self as
|
89
|
+
# the first input argument. {Vips::Operation#call} will only allow
|
90
|
+
# operations that modify self when passed a {MutableImage}.
|
91
|
+
#
|
92
|
+
# @param name [String] vips operation to call
|
93
|
+
# @return result of vips operation
|
94
|
+
def method_missing name, *args, **options
|
95
|
+
Vips::Operation.call name.to_s, [self, *args], options
|
96
|
+
end
|
97
|
+
|
98
|
+
# Create a metadata item on an image of the specifed type. Ruby types
|
99
|
+
# are automatically transformed into the matching glib type (eg.
|
100
|
+
# {GObject::GINT_TYPE}), if possible.
|
101
|
+
#
|
102
|
+
# For example, you can use this to set an image's ICC profile:
|
103
|
+
#
|
104
|
+
# ```ruby
|
105
|
+
# x.set_type! Vips::BLOB_TYPE, "icc-profile-data", profile
|
106
|
+
# ```
|
107
|
+
#
|
108
|
+
# where `profile` is an ICC profile held as a binary string object.
|
109
|
+
#
|
110
|
+
# @see set!
|
111
|
+
# @param gtype [Integer] GType of item
|
112
|
+
# @param name [String] Metadata field to set
|
113
|
+
# @param value [Object] Value to set
|
114
|
+
def set_type! gtype, name, value
|
115
|
+
gvalue = GObject::GValue.alloc
|
116
|
+
gvalue.init gtype
|
117
|
+
gvalue.set value
|
118
|
+
Vips.vips_image_set self, name, gvalue
|
119
|
+
gvalue.unset
|
120
|
+
end
|
121
|
+
|
122
|
+
# Set the value of a metadata item on an image. The metadata item must
|
123
|
+
# already exist. Ruby types are automatically transformed into the
|
124
|
+
# matching {GObject::GValue}, if possible.
|
125
|
+
#
|
126
|
+
# For example, you can use this to set an image's ICC profile:
|
127
|
+
#
|
128
|
+
# ```
|
129
|
+
# x.set! "icc-profile-data", profile
|
130
|
+
# ```
|
131
|
+
#
|
132
|
+
# where `profile` is an ICC profile held as a binary string object.
|
133
|
+
#
|
134
|
+
# @see set_type!
|
135
|
+
# @param name [String] Metadata field to set
|
136
|
+
# @param value [Object] Value to set
|
137
|
+
def set! name, value
|
138
|
+
set_type! get_typeof(name), name, value
|
139
|
+
end
|
140
|
+
|
141
|
+
# Remove a metadata item from an image.
|
142
|
+
#
|
143
|
+
# For example:
|
144
|
+
#
|
145
|
+
# ```
|
146
|
+
# x.remove! "icc-profile-data"
|
147
|
+
# ```
|
148
|
+
#
|
149
|
+
# @param name [String] Metadata field to remove
|
150
|
+
def remove! name
|
151
|
+
Vips.vips_image_remove self, name
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
data/lib/vips/object.rb
CHANGED
@@ -4,241 +4,351 @@
|
|
4
4
|
# Author:: John Cupitt (mailto:jcupitt@gmail.com)
|
5
5
|
# License:: MIT
|
6
6
|
|
7
|
-
require
|
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
|
+
class Progress < FFI::Struct
|
45
|
+
layout :im, :pointer,
|
46
|
+
:run, :int,
|
47
|
+
:eta, :int,
|
48
|
+
:tpels, :int64_t,
|
49
|
+
:npels, :int64_t,
|
50
|
+
:percent, :int,
|
51
|
+
:start, :pointer
|
52
|
+
end
|
53
|
+
|
54
|
+
# Our signal marshalers.
|
55
|
+
#
|
56
|
+
# These are functions which take the handler as a param and return a
|
57
|
+
# closure with the right FFI signature for g_signal_connect for this
|
58
|
+
# specific signal.
|
59
|
+
#
|
60
|
+
# ruby-ffi makes it hard to use the g_signal_connect user data param
|
61
|
+
# to pass the function pointer through, unfortunately.
|
62
|
+
#
|
63
|
+
# We can't throw exceptions across C, so we must catch everything.
|
64
|
+
|
65
|
+
MARSHAL_PROGRESS = proc do |handler|
|
66
|
+
FFI::Function.new(:void, [:pointer, :pointer, :pointer]) do |vi, prog, cb|
|
67
|
+
begin
|
68
|
+
handler.call(Progress.new(prog))
|
69
|
+
rescue Exception => e
|
70
|
+
puts "progress: #{e}"
|
71
|
+
end
|
40
72
|
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
73
|
+
end
|
74
|
+
|
75
|
+
MARSHAL_READ = proc do |handler|
|
76
|
+
FFI::Function.new(:int64_t, [:pointer, :pointer, :int64_t]) do |i, p, len|
|
77
|
+
begin
|
78
|
+
result = handler.call(p, len)
|
79
|
+
rescue Exception => e
|
80
|
+
puts "read: #{e}"
|
81
|
+
result = 0
|
82
|
+
end
|
83
|
+
|
84
|
+
result
|
61
85
|
end
|
62
|
-
|
63
|
-
|
64
|
-
|
86
|
+
end
|
87
|
+
|
88
|
+
MARSHAL_SEEK = proc do |handler|
|
89
|
+
FFI::Function.new(:int64_t, [:pointer, :int64_t, :int]) do |i, off, whence|
|
90
|
+
begin
|
91
|
+
result = handler.call(off, whence)
|
92
|
+
rescue Exception => e
|
93
|
+
puts "seek: #{e}"
|
94
|
+
result = -1
|
95
|
+
end
|
96
|
+
|
97
|
+
result
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
MARSHAL_WRITE = proc do |handler|
|
102
|
+
FFI::Function.new(:int64_t, [:pointer, :pointer, :int64_t]) do |i, p, len|
|
103
|
+
begin
|
104
|
+
result = handler.call(p, len)
|
105
|
+
rescue Exception => e
|
106
|
+
puts "write: #{e}"
|
107
|
+
result = 0
|
108
|
+
end
|
109
|
+
|
110
|
+
result
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
MARSHAL_FINISH = proc do |handler|
|
115
|
+
FFI::Function.new(:void, [:pointer, :pointer]) do |i, cb|
|
116
|
+
begin
|
117
|
+
handler.call
|
118
|
+
rescue Exception => e
|
119
|
+
puts "finish: #{e}"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# map signal name to marshal proc
|
125
|
+
MARSHAL_ALL = {
|
126
|
+
preeval: MARSHAL_PROGRESS,
|
127
|
+
eval: MARSHAL_PROGRESS,
|
128
|
+
posteval: MARSHAL_PROGRESS,
|
129
|
+
read: MARSHAL_READ,
|
130
|
+
seek: MARSHAL_SEEK,
|
131
|
+
write: MARSHAL_WRITE,
|
132
|
+
finish: MARSHAL_FINISH
|
133
|
+
}
|
134
|
+
|
135
|
+
attach_function :vips_enum_from_nick, [:string, :GType, :string], :int
|
136
|
+
attach_function :vips_enum_nick, [:GType, :int], :string
|
137
|
+
|
138
|
+
attach_function :vips_value_set_ref_string,
|
139
|
+
[GObject::GValue.ptr, :string], :void
|
140
|
+
attach_function :vips_value_set_array_double,
|
141
|
+
[GObject::GValue.ptr, :pointer, :int], :void
|
142
|
+
attach_function :vips_value_set_array_int,
|
143
|
+
[GObject::GValue.ptr, :pointer, :int], :void
|
144
|
+
attach_function :vips_value_set_array_image,
|
145
|
+
[GObject::GValue.ptr, :int], :void
|
146
|
+
callback :free_fn, [:pointer], :void
|
147
|
+
attach_function :vips_value_set_blob,
|
148
|
+
[GObject::GValue.ptr, :free_fn, :pointer, :size_t], :void
|
149
|
+
|
150
|
+
class SizeStruct < FFI::Struct
|
151
|
+
layout :value, :size_t
|
152
|
+
end
|
153
|
+
|
154
|
+
class IntStruct < FFI::Struct
|
155
|
+
layout :value, :int
|
156
|
+
end
|
157
|
+
|
158
|
+
attach_function :vips_value_get_ref_string,
|
159
|
+
[GObject::GValue.ptr, SizeStruct.ptr], :string
|
160
|
+
attach_function :vips_value_get_array_double,
|
161
|
+
[GObject::GValue.ptr, IntStruct.ptr], :pointer
|
162
|
+
attach_function :vips_value_get_array_int,
|
163
|
+
[GObject::GValue.ptr, IntStruct.ptr], :pointer
|
164
|
+
attach_function :vips_value_get_array_image,
|
165
|
+
[GObject::GValue.ptr, IntStruct.ptr], :pointer
|
166
|
+
attach_function :vips_value_get_blob,
|
167
|
+
[GObject::GValue.ptr, SizeStruct.ptr], :pointer
|
168
|
+
|
169
|
+
attach_function :type_find, :vips_type_find, [:string, :string], :GType
|
170
|
+
|
171
|
+
class Object < GObject::GObject
|
172
|
+
# print all active VipsObjects, with their reference counts. Handy for
|
173
|
+
# debugging ruby-vips.
|
174
|
+
def self.print_all
|
175
|
+
GC.start
|
176
|
+
Vips.vips_object_print_all
|
65
177
|
end
|
66
178
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
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]
|
179
|
+
# the layout of the VipsObject struct
|
180
|
+
module ObjectLayout
|
181
|
+
def self.included base
|
182
|
+
base.class_eval do
|
183
|
+
# don't actually need most of these
|
184
|
+
layout :parent, GObject::GObject::Struct,
|
185
|
+
:constructed, :int,
|
186
|
+
:static_object, :int,
|
187
|
+
:argument_table, :pointer,
|
188
|
+
:nickname, :string,
|
189
|
+
:description, :string,
|
190
|
+
:preclose, :int,
|
191
|
+
:close, :int,
|
192
|
+
:postclose, :int,
|
193
|
+
:local_memory, :size_t
|
138
194
|
end
|
195
|
+
end
|
196
|
+
end
|
139
197
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
unless pspec
|
144
|
-
Vips::vips_error_clear
|
145
|
-
return 0
|
146
|
-
end
|
147
|
-
|
148
|
-
pspec[:value][:value_type]
|
149
|
-
end
|
198
|
+
class Struct < GObject::GObject::Struct
|
199
|
+
include ObjectLayout
|
200
|
+
end
|
150
201
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
gvalue.init gtype
|
155
|
-
GObject::g_object_get_property self, name, gvalue
|
156
|
-
result = gvalue.get
|
202
|
+
class ManagedStruct < GObject::GObject::ManagedStruct
|
203
|
+
include ObjectLayout
|
204
|
+
end
|
157
205
|
|
158
|
-
|
206
|
+
# return a pspec, or nil ... nil wil leave a message in the error log
|
207
|
+
# which you must clear
|
208
|
+
def get_pspec name
|
209
|
+
ppspec = GObject::GParamSpecPtr.new
|
210
|
+
argument_class = Vips::ArgumentClassPtr.new
|
211
|
+
argument_instance = Vips::ArgumentInstancePtr.new
|
159
212
|
|
160
|
-
|
161
|
-
|
213
|
+
result = Vips.vips_object_get_argument self, name,
|
214
|
+
ppspec, argument_class, argument_instance
|
215
|
+
return nil if result != 0
|
162
216
|
|
163
|
-
|
164
|
-
|
217
|
+
ppspec[:value]
|
218
|
+
end
|
165
219
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
GObject::g_object_set_property self, name, gvalue
|
171
|
-
end
|
220
|
+
# return a gtype, raise an error on not found
|
221
|
+
def get_typeof_error name
|
222
|
+
pspec = get_pspec name
|
223
|
+
raise Vips::Error unless pspec
|
172
224
|
|
225
|
+
pspec[:value_type]
|
173
226
|
end
|
174
227
|
|
175
|
-
|
176
|
-
|
177
|
-
|
228
|
+
# return a gtype, 0 on not found
|
229
|
+
def get_typeof name
|
230
|
+
pspec = get_pspec name
|
231
|
+
unless pspec
|
232
|
+
Vips.vips_error_clear
|
233
|
+
return 0
|
234
|
+
end
|
178
235
|
|
179
|
-
|
180
|
-
layout :pspec, GObject::GParamSpec.ptr
|
236
|
+
pspec[:value_type]
|
181
237
|
end
|
182
238
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
239
|
+
def get name
|
240
|
+
gtype = get_typeof_error name
|
241
|
+
gvalue = GObject::GValue.alloc
|
242
|
+
gvalue.init gtype
|
243
|
+
GObject.g_object_get_property self, name, gvalue
|
244
|
+
result = gvalue.get
|
245
|
+
gvalue.unset
|
187
246
|
|
188
|
-
|
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
|
247
|
+
GLib.logger.debug("Vips::Object.get") { "#{name} == #{result}" }
|
216
248
|
|
217
|
-
|
218
|
-
layout :value, ArgumentClass.ptr
|
249
|
+
result
|
219
250
|
end
|
220
251
|
|
221
|
-
|
222
|
-
|
223
|
-
end
|
252
|
+
def set name, value
|
253
|
+
GLib.logger.debug("Vips::Object.set") { "#{name} = #{value}" }
|
224
254
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
255
|
+
gtype = get_typeof_error name
|
256
|
+
gvalue = GObject::GValue.alloc
|
257
|
+
gvalue.init gtype
|
258
|
+
gvalue.set value
|
259
|
+
GObject.g_object_set_property self, name, gvalue
|
260
|
+
gvalue.unset
|
261
|
+
end
|
232
262
|
|
233
|
-
|
263
|
+
def signal_connect name, handler = nil, &block
|
264
|
+
marshal = MARSHAL_ALL[name.to_sym]
|
265
|
+
raise Vips::Error, "unsupported signal #{name}" if marshal.nil?
|
234
266
|
|
235
|
-
|
267
|
+
if block
|
268
|
+
# our block as a Proc
|
269
|
+
prc = block
|
270
|
+
elsif handler
|
271
|
+
# We assume the hander is a Proc (perhaps we should test)
|
272
|
+
prc = handler
|
273
|
+
else
|
274
|
+
raise Vips::Error, "must supply either block or handler"
|
275
|
+
end
|
236
276
|
|
237
|
-
|
238
|
-
|
277
|
+
# The marshal function will make a closure with the right type signature
|
278
|
+
# for the selected signal
|
279
|
+
callback = marshal.call(prc)
|
239
280
|
|
240
|
-
|
281
|
+
# we need to make sure this is not GCd while self is alive
|
282
|
+
@references << callback
|
241
283
|
|
284
|
+
GObject.g_signal_connect_data(self, name.to_s, callback, nil, nil, 0)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
class ObjectClass < FFI::Struct
|
289
|
+
# opaque
|
290
|
+
end
|
291
|
+
|
292
|
+
class Argument < FFI::Struct
|
293
|
+
layout :pspec, GObject::GParamSpec.ptr
|
294
|
+
end
|
295
|
+
|
296
|
+
class ArgumentInstance < Argument
|
297
|
+
layout :parent, Argument
|
298
|
+
# rest opaque
|
299
|
+
end
|
300
|
+
|
301
|
+
# enum VipsArgumentFlags
|
302
|
+
ARGUMENT_REQUIRED = 1
|
303
|
+
ARGUMENT_CONSTRUCT = 2
|
304
|
+
ARGUMENT_SET_ONCE = 4
|
305
|
+
ARGUMENT_SET_ALWAYS = 8
|
306
|
+
ARGUMENT_INPUT = 16
|
307
|
+
ARGUMENT_OUTPUT = 32
|
308
|
+
ARGUMENT_DEPRECATED = 64
|
309
|
+
ARGUMENT_MODIFY = 128
|
310
|
+
|
311
|
+
ARGUMENT_FLAGS = {
|
312
|
+
required: ARGUMENT_REQUIRED,
|
313
|
+
construct: ARGUMENT_CONSTRUCT,
|
314
|
+
set_once: ARGUMENT_SET_ONCE,
|
315
|
+
set_always: ARGUMENT_SET_ALWAYS,
|
316
|
+
input: ARGUMENT_INPUT,
|
317
|
+
output: ARGUMENT_OUTPUT,
|
318
|
+
deprecated: ARGUMENT_DEPRECATED,
|
319
|
+
modify: ARGUMENT_MODIFY
|
320
|
+
}
|
321
|
+
|
322
|
+
class ArgumentClass < Argument
|
323
|
+
layout :parent, Argument,
|
324
|
+
:object_class, ObjectClass.ptr,
|
325
|
+
:flags, :uint,
|
326
|
+
:priority, :int,
|
327
|
+
:offset, :ulong_long
|
328
|
+
end
|
329
|
+
|
330
|
+
class ArgumentClassPtr < FFI::Struct
|
331
|
+
layout :value, ArgumentClass.ptr
|
332
|
+
end
|
333
|
+
|
334
|
+
class ArgumentInstancePtr < FFI::Struct
|
335
|
+
layout :value, ArgumentInstance.ptr
|
336
|
+
end
|
337
|
+
|
338
|
+
# just use :pointer, not VipsObject.ptr, to avoid casting gobject
|
339
|
+
# subclasses
|
340
|
+
attach_function :vips_object_get_argument,
|
341
|
+
[:pointer, :string,
|
342
|
+
GObject::GParamSpecPtr.ptr,
|
343
|
+
ArgumentClassPtr.ptr, ArgumentInstancePtr.ptr],
|
344
|
+
:int
|
345
|
+
|
346
|
+
attach_function :vips_object_print_all, [], :void
|
347
|
+
|
348
|
+
attach_function :vips_object_set_from_string, [:pointer, :string], :int
|
349
|
+
|
350
|
+
callback :type_map_fn, [:GType, :pointer], :pointer
|
351
|
+
attach_function :vips_type_map, [:GType, :type_map_fn, :pointer], :pointer
|
352
|
+
|
353
|
+
attach_function :vips_object_get_description, [:pointer], :string
|
242
354
|
end
|
243
|
-
|
244
|
-
|