ruby-vips 1.0.6 → 2.0.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/.travis.yml +9 -12
- data/CHANGELOG.md +5 -1
- data/README.md +32 -115
- data/TODO +4 -6
- data/VERSION +1 -1
- data/example/inheritance_with_refcount.rb +286 -0
- data/lib/ruby-vips.rb +1 -0
- data/lib/vips.rb +425 -93
- data/lib/vips/access.rb +1 -4
- data/lib/vips/align.rb +2 -2
- data/lib/vips/angle.rb +2 -2
- data/lib/vips/angle45.rb +2 -2
- data/lib/vips/bandformat.rb +1 -1
- data/lib/vips/coding.rb +1 -1
- data/lib/vips/direction.rb +2 -2
- data/lib/vips/extend.rb +8 -13
- data/lib/vips/gobject.rb +121 -0
- data/lib/vips/gvalue.rb +251 -0
- data/lib/vips/image.rb +487 -585
- data/lib/vips/interesting.rb +1 -1
- data/lib/vips/interpolate.rb +31 -6
- data/lib/vips/interpretation.rb +1 -1
- data/lib/vips/kernel.rb +1 -1
- data/lib/vips/methods.rb +339 -334
- data/lib/vips/object.rb +204 -0
- data/lib/vips/operation.rb +358 -14
- data/lib/vips/operationboolean.rb +14 -0
- data/lib/vips/operationcomplex.rb +12 -0
- data/lib/vips/operationcomplex2.rb +10 -0
- data/lib/vips/operationcomplexget.rb +11 -0
- data/lib/vips/operationmath.rb +18 -0
- data/lib/vips/operationmath2.rb +10 -0
- data/lib/vips/operationrelational.rb +15 -0
- data/lib/vips/operationround.rb +11 -0
- data/lib/vips/size.rb +2 -1
- data/lib/vips/version.rb +1 -1
- data/ruby-vips.gemspec +2 -6
- metadata +19 -11
- data/lib/vips/argument.rb +0 -159
- data/lib/vips/call.rb +0 -370
- data/lib/vips/demandstyle.rb +0 -35
- data/lib/vips/error.rb +0 -30
- data/lib/vips/foreignflags.rb +0 -20
data/lib/vips/access.rb
CHANGED
@@ -6,9 +6,6 @@ module Vips
|
|
6
6
|
# * `:sequential` means requests will be top-to-bottom, but with some
|
7
7
|
# amount of buffering behind the read point for small non-local
|
8
8
|
# accesses.
|
9
|
-
|
10
|
-
# * `:sequential_unbuffered` means requests will be strictly
|
11
|
-
# top-to-bottom with no read-behind. This can save some memory.
|
12
|
-
class Access
|
9
|
+
class Access < Symbol
|
13
10
|
end
|
14
11
|
end
|
data/lib/vips/align.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
module Vips
|
2
2
|
|
3
|
-
# Various types of alignment. See {
|
3
|
+
# Various types of alignment. See {Image#join}, for example.
|
4
4
|
#
|
5
5
|
# * `:low` Align on the low coordinate edge
|
6
6
|
# * `:centre` Align on the centre
|
7
7
|
# * `:high` Align on the high coordinate edge
|
8
8
|
|
9
|
-
class Align
|
9
|
+
class Align < Symbol
|
10
10
|
end
|
11
11
|
end
|
data/lib/vips/angle.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
module Vips
|
2
2
|
|
3
|
-
# Various fixed 90 degree rotation angles. See {
|
3
|
+
# Various fixed 90 degree rotation angles. See {Image#rot}.
|
4
4
|
#
|
5
5
|
# * `:d0` no rotate
|
6
6
|
# * `:d90` 90 degrees clockwise
|
7
7
|
# * `:d180` 180 degrees
|
8
8
|
# * `:d270` 90 degrees anti-clockwise
|
9
9
|
|
10
|
-
class Angle
|
10
|
+
class Angle < Symbol
|
11
11
|
end
|
12
12
|
end
|
data/lib/vips/angle45.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Vips
|
2
2
|
|
3
|
-
# Various fixed 45 degree rotation angles. See {
|
3
|
+
# Various fixed 45 degree rotation angles. See {Image#rot45}.
|
4
4
|
#
|
5
5
|
# * `:d0` no rotate
|
6
6
|
# * `:d45` 45 degrees clockwise
|
@@ -11,6 +11,6 @@ module Vips
|
|
11
11
|
# * `:d270` 90 degrees anti-clockwise
|
12
12
|
# * `:d315` 45 degrees anti-clockwise
|
13
13
|
|
14
|
-
class Angle45
|
14
|
+
class Angle45 < Symbol
|
15
15
|
end
|
16
16
|
end
|
data/lib/vips/bandformat.rb
CHANGED
data/lib/vips/coding.rb
CHANGED
data/lib/vips/direction.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
module Vips
|
2
2
|
|
3
|
-
# Operations like {
|
3
|
+
# Operations like {Image#flip} need to be told whether to flip
|
4
4
|
# left-right or top-bottom.
|
5
5
|
#
|
6
6
|
# * `:horizontal` left-right
|
7
7
|
# * `:vertical` top-bottom
|
8
8
|
|
9
|
-
class Direction
|
9
|
+
class Direction < Symbol
|
10
10
|
end
|
11
11
|
end
|
data/lib/vips/extend.rb
CHANGED
@@ -2,21 +2,16 @@ module Vips
|
|
2
2
|
|
3
3
|
# When the edges of an image are extended, you can specify
|
4
4
|
# how you want the extension done.
|
5
|
-
# See {
|
5
|
+
# See {Image#embed}, {Image#conv}, {Image#affine} and
|
6
6
|
# so on.
|
7
7
|
#
|
8
|
-
# *
|
9
|
-
#
|
10
|
-
# *
|
11
|
-
#
|
12
|
-
# *
|
13
|
-
#
|
14
|
-
# * `:mirror` the image is reflected and tiled to reduce hash edges
|
15
|
-
#
|
16
|
-
# * `:white` new pixels are white, ie. all bits are set
|
17
|
-
#
|
18
|
-
# * `:background` colour set from the @background property
|
8
|
+
# * `:black` new pixels are black, ie. all bits are zero.
|
9
|
+
# * `:copy` each new pixel takes the value of the nearest edge pixel
|
10
|
+
# * `:repeat` the image is tiled to fill the new area
|
11
|
+
# * `:mirror` the image is reflected and tiled to reduce hash edges
|
12
|
+
# * `:white` new pixels are white, ie. all bits are set
|
13
|
+
# * `:background` colour set from the @background property
|
19
14
|
|
20
|
-
class Extend
|
15
|
+
class Extend < Symbol
|
21
16
|
end
|
22
17
|
end
|
data/lib/vips/gobject.rb
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
# This module provides an interface to the top level bits of GObject
|
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 GObject
|
11
|
+
|
12
|
+
# we have a number of things we need to inherit in different ways:
|
13
|
+
#
|
14
|
+
# - we want to be able to subclass GObject in Ruby in a simple way
|
15
|
+
# - the layouts of the nested structs need to inherit
|
16
|
+
# - we need to be able to cast between structs which share a base struct
|
17
|
+
# without creating new wrappers or messing up refcounting
|
18
|
+
# - we need automatic gobject refcounting
|
19
|
+
#
|
20
|
+
# the solution is to split the class into four areas which we treat
|
21
|
+
# differently:
|
22
|
+
#
|
23
|
+
# - we have a "wrapper" Ruby class to allow easy subclassing ... this has a
|
24
|
+
# @struct member which holds the actual pointer
|
25
|
+
# - we use "forwardable" to forward the various ffi methods on to the
|
26
|
+
# @struct member ... we arrange things so that subclasses do not need to
|
27
|
+
# do the forwarding themselves
|
28
|
+
# - we have two versions of the struct: a plain one which we can use for
|
29
|
+
# casting that will not change the refcounts
|
30
|
+
# - and a managed one with an unref which we just use for .new
|
31
|
+
# - we separate the struct layout into a separate module to avoid repeating
|
32
|
+
# ourselves
|
33
|
+
|
34
|
+
class GObject
|
35
|
+
extend Forwardable
|
36
|
+
extend SingleForwardable
|
37
|
+
|
38
|
+
def_instance_delegators :@struct, :[], :to_ptr
|
39
|
+
def_single_delegators :ffi_struct, :ptr
|
40
|
+
|
41
|
+
# the layout of the GObject struct
|
42
|
+
module GObjectLayout
|
43
|
+
def self.included base
|
44
|
+
base.class_eval do
|
45
|
+
layout :g_type_instance, :pointer,
|
46
|
+
:ref_count, :uint,
|
47
|
+
:qdata, :pointer
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# the struct with unref ... manage object lifetime with this
|
53
|
+
class ManagedStruct < FFI::ManagedStruct
|
54
|
+
include GObjectLayout
|
55
|
+
|
56
|
+
def self.release ptr
|
57
|
+
# Vips::log "GObject::GObject::ManagedStruct.release: " +
|
58
|
+
# "unreffing #{ptr}"
|
59
|
+
GObject::g_object_unref ptr
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# the plain struct ... cast with this
|
64
|
+
class Struct < FFI::Struct
|
65
|
+
include GObjectLayout
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
# don't allow ptr == nil, we never want to allocate a GObject struct
|
70
|
+
# ourselves, we just want to wrap GLib-allocated GObjects
|
71
|
+
#
|
72
|
+
# here we use ManagedStruct, not Struct, since this is the ref that will
|
73
|
+
# need the unref
|
74
|
+
def initialize ptr
|
75
|
+
# Vips::log "GObject::GObject.initialize: ptr = #{ptr}"
|
76
|
+
@struct = ffi_managed_struct.new ptr
|
77
|
+
end
|
78
|
+
|
79
|
+
# access to the casting struct for this class
|
80
|
+
def ffi_struct
|
81
|
+
self.class.ffi_struct
|
82
|
+
end
|
83
|
+
|
84
|
+
class << self
|
85
|
+
def ffi_struct
|
86
|
+
self.const_get :Struct
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# access to the managed struct for this class
|
91
|
+
def ffi_managed_struct
|
92
|
+
self.class.ffi_managed_struct
|
93
|
+
end
|
94
|
+
|
95
|
+
class << self
|
96
|
+
def ffi_managed_struct
|
97
|
+
self.const_get :ManagedStruct
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
class GParamSpec < FFI::Struct
|
104
|
+
# the first few public fields
|
105
|
+
layout :g_type_instance, :pointer,
|
106
|
+
:name, :string,
|
107
|
+
:flags, :uint,
|
108
|
+
:value_type, :GType,
|
109
|
+
:owner_type, :GType
|
110
|
+
end
|
111
|
+
|
112
|
+
attach_function :g_param_spec_get_blurb, [GParamSpec.ptr], :string
|
113
|
+
|
114
|
+
attach_function :g_object_ref, [:pointer], :void
|
115
|
+
attach_function :g_object_unref, [:pointer], :void
|
116
|
+
|
117
|
+
class GParamSpecPtr < FFI::Struct
|
118
|
+
layout :value, GParamSpec.ptr
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
data/lib/vips/gvalue.rb
ADDED
@@ -0,0 +1,251 @@
|
|
1
|
+
# This module provides an interface GValue via ruby-ffi.
|
2
|
+
#
|
3
|
+
# Author:: John Cupitt (mailto:jcupitt@gmail.com)
|
4
|
+
# License:: MIT
|
5
|
+
|
6
|
+
require 'ffi'
|
7
|
+
|
8
|
+
module GObject
|
9
|
+
|
10
|
+
# Represent a GValue. Example use:
|
11
|
+
#
|
12
|
+
# ```ruby
|
13
|
+
# gvalue = GValue::alloc
|
14
|
+
# gvalue.init GObject::GDOUBLE_TYPE
|
15
|
+
# gvalue.set 3.1415
|
16
|
+
# value = gvalue.get
|
17
|
+
# ```
|
18
|
+
#
|
19
|
+
# Lifetime is managed automatically. It doesn't know about all GType values,
|
20
|
+
# but it does know the ones that libvips uses.
|
21
|
+
|
22
|
+
class GValue < FFI::ManagedStruct
|
23
|
+
layout :gtype, :GType,
|
24
|
+
:data, [:ulong_long, 2]
|
25
|
+
|
26
|
+
def self.release ptr
|
27
|
+
# Vips::log "GObject::GValue::release ptr = #{ptr}"
|
28
|
+
::GObject::g_value_unset ptr
|
29
|
+
end
|
30
|
+
|
31
|
+
# Allocate memory for a GValue and return a class wrapper. Memory will
|
32
|
+
# be freed automatically when it goes out of scope. The GValue is inited
|
33
|
+
# to 0, use {GValue.init} to set a type.
|
34
|
+
#
|
35
|
+
# @return [GValue] a new gvalue set to 0
|
36
|
+
def self.alloc
|
37
|
+
# allocate memory
|
38
|
+
memory = FFI::MemoryPointer.new GValue
|
39
|
+
|
40
|
+
# make this alloc autorelease ... we mustn't release in
|
41
|
+
# GValue::release, since we are used to wrap GValue pointers
|
42
|
+
# made by other people
|
43
|
+
pointer = FFI::Pointer.new GValue, memory
|
44
|
+
|
45
|
+
# ... and wrap in a GValue
|
46
|
+
return GValue.new pointer
|
47
|
+
end
|
48
|
+
|
49
|
+
# Set the type of thing a gvalue can hold.
|
50
|
+
#
|
51
|
+
# @param gtype [GType] the type of thing this GValue can hold.
|
52
|
+
def init gtype
|
53
|
+
::GObject::g_value_init self, gtype
|
54
|
+
end
|
55
|
+
|
56
|
+
# Set the value of a GValue. The value is converted to the type of the
|
57
|
+
# GValue, if possible.
|
58
|
+
#
|
59
|
+
# @param value [Any] The value to set
|
60
|
+
def set value
|
61
|
+
# Vips::log "GObject::GValue.set: value = #{value.inspect[0..50]}"
|
62
|
+
|
63
|
+
gtype = self[:gtype]
|
64
|
+
fundamental = ::GObject::g_type_fundamental gtype
|
65
|
+
|
66
|
+
case gtype
|
67
|
+
when GBOOL_TYPE
|
68
|
+
::GObject::g_value_set_boolean self, (value ? 1 : 0)
|
69
|
+
|
70
|
+
when GINT_TYPE
|
71
|
+
::GObject::g_value_set_int self, value
|
72
|
+
|
73
|
+
when GDOUBLE_TYPE
|
74
|
+
::GObject::g_value_set_double self, value
|
75
|
+
|
76
|
+
when GSTR_TYPE
|
77
|
+
# set_string takes a copy, no lifetime worries
|
78
|
+
::GObject::g_value_set_string self, value
|
79
|
+
|
80
|
+
when Vips::ARRAY_INT_TYPE
|
81
|
+
value = [value] if not value.is_a? Array
|
82
|
+
|
83
|
+
Vips::vips_value_set_array_int self, nil, value.length
|
84
|
+
ptr = Vips::vips_value_get_array_int self, nil
|
85
|
+
ptr.write_array_of_int32 value
|
86
|
+
|
87
|
+
when Vips::ARRAY_DOUBLE_TYPE
|
88
|
+
value = [value] if not value.is_a? Array
|
89
|
+
|
90
|
+
# this will allocate an array in the gvalue
|
91
|
+
Vips::vips_value_set_array_double self, nil, value.length
|
92
|
+
|
93
|
+
# pull the array out and fill it
|
94
|
+
ptr = Vips::vips_value_get_array_double self, nil
|
95
|
+
|
96
|
+
ptr.write_array_of_double value
|
97
|
+
|
98
|
+
when Vips::ARRAY_IMAGE_TYPE
|
99
|
+
value = [value] if not value.is_a? Array
|
100
|
+
|
101
|
+
Vips::vips_value_set_array_image self, value.length
|
102
|
+
ptr = Vips::vips_value_get_array_image self, nil
|
103
|
+
ptr.write_array_of_pointer value
|
104
|
+
|
105
|
+
# the gvalue needs a ref on each of the images
|
106
|
+
value.each {|image| ::GObject::g_object_ref image}
|
107
|
+
|
108
|
+
when Vips::BLOB_TYPE
|
109
|
+
len = value.length
|
110
|
+
ptr = GLib::g_malloc len
|
111
|
+
Vips::vips_value_set_blob self, GLib::G_FREE, ptr, len
|
112
|
+
ptr.write_bytes value
|
113
|
+
|
114
|
+
else
|
115
|
+
case fundamental
|
116
|
+
when GFLAGS_TYPE
|
117
|
+
::GObject::g_value_set_flags self, value
|
118
|
+
|
119
|
+
when GENUM_TYPE
|
120
|
+
value = value.to_s if value.is_a? Symbol
|
121
|
+
|
122
|
+
if value.is_a? String
|
123
|
+
value = Vips::vips_enum_from_nick "ruby-vips",
|
124
|
+
self[:gtype], value
|
125
|
+
if value == -1
|
126
|
+
raise Vips::Error
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
::GObject::g_value_set_enum self, value
|
131
|
+
|
132
|
+
when GOBJECT_TYPE
|
133
|
+
::GObject::g_value_set_object self, value
|
134
|
+
|
135
|
+
else
|
136
|
+
raise Vips::Error, "unimplemented gtype for set: #{gtype}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Get the value of a GValue. The value is converted to a Ruby type in
|
142
|
+
# the obvious way.
|
143
|
+
#
|
144
|
+
# @return [Any] the value held by the GValue
|
145
|
+
def get
|
146
|
+
gtype = self[:gtype]
|
147
|
+
fundamental = ::GObject::g_type_fundamental gtype
|
148
|
+
result = nil
|
149
|
+
|
150
|
+
case gtype
|
151
|
+
when GBOOL_TYPE
|
152
|
+
result = ::GObject::g_value_get_boolean(self) != 0 ? true : false
|
153
|
+
|
154
|
+
when GINT_TYPE
|
155
|
+
result = ::GObject::g_value_get_int self
|
156
|
+
|
157
|
+
when GDOUBLE_TYPE
|
158
|
+
result = ::GObject::g_value_get_double self
|
159
|
+
|
160
|
+
when GSTR_TYPE
|
161
|
+
# FIXME do we need to strdup here?
|
162
|
+
result = ::GObject::g_value_get_string self
|
163
|
+
|
164
|
+
when Vips::ARRAY_INT_TYPE
|
165
|
+
len = Vips::IntStruct.new
|
166
|
+
array = Vips::vips_value_get_array_int self, len
|
167
|
+
result = array.get_array_of_int32 0, len[:value]
|
168
|
+
|
169
|
+
when Vips::ARRAY_DOUBLE_TYPE
|
170
|
+
len = Vips::IntStruct.new
|
171
|
+
array = Vips::vips_value_get_array_double self, len
|
172
|
+
result = array.get_array_of_double 0, len[:value]
|
173
|
+
|
174
|
+
when Vips::ARRAY_IMAGE_TYPE
|
175
|
+
len = Vips::IntStruct.new
|
176
|
+
array = Vips::vips_value_get_array_image self, len
|
177
|
+
result = array.get_array_of_pointer 0, len[:value]
|
178
|
+
result.map! do |pointer|
|
179
|
+
::GObject::g_object_ref pointer
|
180
|
+
Vips::Image.new pointer
|
181
|
+
end
|
182
|
+
|
183
|
+
when Vips::BLOB_TYPE
|
184
|
+
len = Vips::SizeStruct.new
|
185
|
+
array = Vips::vips_value_get_blob self, len
|
186
|
+
result = array.get_bytes 0, len[:value]
|
187
|
+
|
188
|
+
else
|
189
|
+
case fundamental
|
190
|
+
when GFLAGS_TYPE
|
191
|
+
result = ::GObject::g_value_get_flags self
|
192
|
+
|
193
|
+
when GENUM_TYPE
|
194
|
+
enum_value = ::GObject::g_value_get_enum self
|
195
|
+
# this returns a static string, no need to worry about
|
196
|
+
# lifetime
|
197
|
+
enum_name = Vips::vips_enum_nick self[:gtype], enum_value
|
198
|
+
if enum_name == nil
|
199
|
+
raise Vips::Error
|
200
|
+
end
|
201
|
+
result = enum_name.to_sym
|
202
|
+
|
203
|
+
when GOBJECT_TYPE
|
204
|
+
obj = ::GObject::g_value_get_object self
|
205
|
+
# g_value_get_object() does not add a ref ... we need to add
|
206
|
+
# one to match the unref in gobject release
|
207
|
+
::GObject::g_object_ref obj
|
208
|
+
result = Vips::Image.new obj
|
209
|
+
|
210
|
+
else
|
211
|
+
raise Vips::Error, "unimplemented gtype for get: #{gtype}"
|
212
|
+
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
# Vips::log "GObject::GValue.get: result = #{result.inspect[0..50]}"
|
217
|
+
|
218
|
+
return result
|
219
|
+
end
|
220
|
+
|
221
|
+
end
|
222
|
+
|
223
|
+
attach_function :g_value_init, [GValue.ptr, :GType], :void
|
224
|
+
|
225
|
+
# we must use a plain :pointer here, since we call this from #release, which
|
226
|
+
# just gives us the unwrapped pointer, not the ruby class
|
227
|
+
attach_function :g_value_unset, [:pointer], :void
|
228
|
+
|
229
|
+
attach_function :g_value_set_boolean, [GValue.ptr, :int], :void
|
230
|
+
attach_function :g_value_set_int, [GValue.ptr, :int], :void
|
231
|
+
attach_function :g_value_set_double, [GValue.ptr, :double], :void
|
232
|
+
attach_function :g_value_set_enum, [GValue.ptr, :int], :void
|
233
|
+
attach_function :g_value_set_flags, [GValue.ptr, :uint], :void
|
234
|
+
attach_function :g_value_set_string, [GValue.ptr, :string], :void
|
235
|
+
attach_function :g_value_set_object, [GValue.ptr, :pointer], :void
|
236
|
+
|
237
|
+
attach_function :g_value_get_boolean, [GValue.ptr], :int
|
238
|
+
attach_function :g_value_get_int, [GValue.ptr], :int
|
239
|
+
attach_function :g_value_get_double, [GValue.ptr], :double
|
240
|
+
attach_function :g_value_get_enum, [GValue.ptr], :int
|
241
|
+
attach_function :g_value_get_flags, [GValue.ptr], :int
|
242
|
+
attach_function :g_value_get_string, [GValue.ptr], :string
|
243
|
+
attach_function :g_value_get_object, [GValue.ptr], :pointer
|
244
|
+
|
245
|
+
# use :pointer rather than GObject.ptr to avoid casting later
|
246
|
+
attach_function :g_object_set_property,
|
247
|
+
[:pointer, :string, GValue.ptr], :void
|
248
|
+
attach_function :g_object_get_property,
|
249
|
+
[:pointer, :string, GValue.ptr], :void
|
250
|
+
|
251
|
+
end
|