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
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.0
|
1
|
+
2.1.0
|
data/example/annotate.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
|
3
|
-
require
|
3
|
+
require "vips"
|
4
4
|
|
5
|
-
im = Vips::Image.new_from_file ARGV[0], :
|
5
|
+
im = Vips::Image.new_from_file ARGV[0], access: :sequential
|
6
6
|
|
7
|
-
left_text = Vips::Image.text "left corner", :
|
8
|
-
left = left_text.embed 50, 50, im.width, 150
|
7
|
+
left_text = Vips::Image.text "left corner", dpi: 300
|
8
|
+
left = left_text.embed 50, 50, im.width, 150
|
9
9
|
|
10
|
-
right_text = Vips::Image.text "right corner", :
|
10
|
+
right_text = Vips::Image.text "right corner", dpi: 300
|
11
11
|
right = right_text.embed im.width - right_text.width - 50, 50, im.width, 150
|
12
12
|
|
13
|
-
footer = (left | right).ifthenelse(0, [255, 0, 0], :
|
13
|
+
footer = (left | right).ifthenelse(0, [255, 0, 0], blend: true)
|
14
14
|
|
15
|
-
im = im.insert footer, 0, im.height, :
|
15
|
+
im = im.insert footer, 0, im.height, expand: true
|
16
16
|
|
17
17
|
im.write_to_file ARGV[1]
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require "vips"
|
4
|
+
require "down/http"
|
5
|
+
|
6
|
+
# byte_source = File.open ARGV[0], "rb"
|
7
|
+
# eg. https://images.unsplash.com/photo-1491933382434-500287f9b54b
|
8
|
+
byte_source = Down::Http.open(ARGV[0])
|
9
|
+
|
10
|
+
source = Vips::SourceCustom.new
|
11
|
+
source.on_read do |length|
|
12
|
+
puts "reading #{length} bytes ..."
|
13
|
+
byte_source.read length
|
14
|
+
end
|
15
|
+
source.on_seek do |offset, whence|
|
16
|
+
puts "seeking to #{offset}, #{whence}"
|
17
|
+
byte_source.seek(offset, whence)
|
18
|
+
end
|
19
|
+
|
20
|
+
byte_target = File.open ARGV[1], "wb"
|
21
|
+
target = Vips::TargetCustom.new
|
22
|
+
target.on_write { |chunk| byte_target.write(chunk) }
|
23
|
+
target.on_finish { byte_target.close }
|
24
|
+
|
25
|
+
image = Vips::Image.new_from_source source, "", access: :sequential
|
26
|
+
image.write_to_target target, ".jpg"
|
data/example/daltonize8.rb
CHANGED
@@ -7,20 +7,20 @@
|
|
7
7
|
# http://libvips.blogspot.co.uk/2013/05/daltonize-in-ruby-vips-carrierwave-and.html
|
8
8
|
# for a discussion of this code
|
9
9
|
|
10
|
-
require
|
10
|
+
require "vips"
|
11
11
|
|
12
|
-
#Vips.set_debug true
|
12
|
+
# Vips.set_debug true
|
13
13
|
|
14
14
|
# matrices to convert D65 XYZ to and from bradford cone space
|
15
15
|
xyz_to_brad = [
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
[0.8951, 0.2664, -0.1614],
|
17
|
+
[-0.7502, 1.7135, 0.0367],
|
18
|
+
[0.0389, -0.0685, 1.0296]
|
19
19
|
]
|
20
20
|
brad_to_xyz = [
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
[0.987, -0.147, 0.16],
|
22
|
+
[0.432, 0.5184, 0.0493],
|
23
|
+
[-0.0085, 0.04, 0.968]
|
24
24
|
]
|
25
25
|
|
26
26
|
im = Vips::Image.new_from_file ARGV[0]
|
@@ -28,48 +28,46 @@ im = Vips::Image.new_from_file ARGV[0]
|
|
28
28
|
# remove any alpha channel before processing
|
29
29
|
alpha = nil
|
30
30
|
if im.bands == 4
|
31
|
-
|
32
|
-
|
31
|
+
alpha = im[3]
|
32
|
+
im = im.extract_band 0, n: 3
|
33
33
|
end
|
34
34
|
|
35
35
|
begin
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
# import to XYZ with lcms
|
37
|
+
# if there's no profile there, we'll fall back to the thing below
|
38
|
+
xyz = im.icc_import embedded: true, pcs: :xyz
|
39
39
|
rescue Vips::Error
|
40
|
-
|
41
|
-
|
40
|
+
# nope .. use the built-in converter instead
|
41
|
+
xyz = im.colourspace :xyz
|
42
42
|
end
|
43
43
|
|
44
|
-
brad = xyz.recomb xyz_to_brad
|
44
|
+
brad = xyz.recomb xyz_to_brad
|
45
45
|
|
46
46
|
# through the Deuteranope matrix
|
47
47
|
# we need rows to sum to 1 in Bradford space --- the matrix in the original
|
48
48
|
# Python code sums to 1.742
|
49
49
|
deut = brad.recomb [
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
[1, 0, 0],
|
51
|
+
[0.7, 0, 0.3],
|
52
|
+
[0, 0, 1]
|
53
53
|
]
|
54
54
|
|
55
|
-
xyz = deut.recomb brad_to_xyz
|
55
|
+
xyz = deut.recomb brad_to_xyz
|
56
56
|
|
57
|
-
# .. and back to sRGB
|
57
|
+
# .. and back to sRGB
|
58
58
|
rgb = xyz.colourspace :srgb
|
59
59
|
|
60
|
-
# so this is the colour error
|
60
|
+
# so this is the colour error
|
61
61
|
err = im - rgb
|
62
62
|
|
63
63
|
# add the error back to other channels to make a compensated image
|
64
|
-
im
|
65
|
-
|
66
|
-
|
67
|
-
[0.7, 0, 1]
|
68
|
-
])
|
64
|
+
im += err.recomb([[0, 0, 0],
|
65
|
+
[0.7, 1, 0],
|
66
|
+
[0.7, 0, 1]])
|
69
67
|
|
70
68
|
# reattach any alpha we saved above
|
71
69
|
if alpha
|
72
|
-
|
70
|
+
im = im.bandjoin(alpha)
|
73
71
|
end
|
74
72
|
|
75
|
-
im.write_to_file ARGV[1]
|
73
|
+
im.write_to_file ARGV[1]
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require "vips"
|
4
|
+
|
5
|
+
# load and stream into memory
|
6
|
+
image = Vips::Image.new_from_file(ARGV[0], access: :sequential).copy_memory
|
7
|
+
|
8
|
+
starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
9
|
+
|
10
|
+
lines = image
|
11
|
+
(0..1).step 0.01 do |i|
|
12
|
+
lines = lines.draw_line 255, lines.width * i, 0, 0, lines.height * (1 - i)
|
13
|
+
end
|
14
|
+
|
15
|
+
ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
16
|
+
puts "non-destructive took #{ending - starting}s"
|
17
|
+
|
18
|
+
starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
19
|
+
|
20
|
+
lines = image
|
21
|
+
lines = lines.mutate do |x|
|
22
|
+
(0..1).step 0.01 do |i|
|
23
|
+
x.draw_line! 255, x.width * i, 0, 0, x.height * (1 - i)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
28
|
+
puts "mutate took #{ending - starting}s"
|
29
|
+
|
30
|
+
lines.write_to_file ARGV[1]
|
data/example/example1.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
|
-
#!/usr/bin/
|
1
|
+
#!/usr/bin/ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "logger"
|
4
|
+
require "vips"
|
5
5
|
|
6
|
-
GLib
|
6
|
+
GLib.logger.level = Logger::DEBUG
|
7
7
|
|
8
|
-
|
8
|
+
Vips::Operation.new "black"
|
9
9
|
|
10
|
-
op = nil
|
11
10
|
GC.start
|
12
11
|
Vips::Operation.print_all
|
data/example/example2.rb
CHANGED
@@ -1,34 +1,34 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "logger"
|
4
|
+
require "vips"
|
5
5
|
|
6
6
|
puts ""
|
7
7
|
puts "starting up:"
|
8
8
|
|
9
9
|
# this makes vips keep a list of all active objects which we can print out
|
10
|
-
Vips
|
10
|
+
Vips.leak_set true
|
11
11
|
|
12
12
|
# disable the operation cache
|
13
|
-
Vips
|
13
|
+
Vips.cache_set_max 0
|
14
14
|
|
15
15
|
# GLib::logger.level = Logger::DEBUG
|
16
16
|
|
17
17
|
n = 10000
|
18
18
|
|
19
19
|
n.times do |i|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
puts ""
|
21
|
+
puts "call #{i} ..."
|
22
|
+
out = Vips::Operation.call "black", [200, 300]
|
23
|
+
if out.width != 200 || out.height != 300
|
24
|
+
puts "bad image result from black"
|
25
|
+
end
|
26
26
|
end
|
27
27
|
|
28
28
|
puts ""
|
29
29
|
puts "after #{n} calls:"
|
30
30
|
GC.start
|
31
|
-
Vips::Object
|
31
|
+
Vips::Object.print_all
|
32
32
|
|
33
33
|
puts ""
|
34
34
|
puts "shutting down:"
|
data/example/example3.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
|
3
|
-
require
|
3
|
+
require "vips"
|
4
4
|
|
5
|
-
# this makes vips keep a list of all active objects
|
6
|
-
Vips
|
5
|
+
# this makes vips keep a list of all active objects
|
6
|
+
Vips.leak_set true
|
7
7
|
|
8
8
|
# disable the operation cache
|
9
9
|
# Vips::cache_set_max 0
|
10
10
|
|
11
11
|
# turn on debug logging
|
12
|
-
GLib
|
12
|
+
GLib.logger.level = Logger::DEBUG
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
10.times do |i|
|
15
|
+
puts "loop #{i} ..."
|
16
|
+
im = Vips::Image.new_from_file ARGV[0]
|
17
|
+
im = im.embed 100, 100, 3000, 3000, extend: :mirror
|
18
|
+
im.write_to_file "x.v"
|
19
19
|
end
|
data/example/example4.rb
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
|
3
|
-
require
|
3
|
+
require "vips"
|
4
4
|
|
5
|
-
# this makes vips keep a list of all active objects
|
6
|
-
Vips
|
5
|
+
# this makes vips keep a list of all active objects
|
6
|
+
Vips.leak_set true
|
7
7
|
|
8
8
|
# disable the operation cache
|
9
|
-
#Vips::cache_set_max 0
|
9
|
+
# Vips::cache_set_max 0
|
10
10
|
|
11
11
|
# turn on debug logging
|
12
|
-
#Vips.set_debug true
|
12
|
+
# Vips.set_debug true
|
13
13
|
|
14
14
|
ARGV.each do |filename|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
im = Vips::Image.new_from_file filename
|
16
|
+
profile = im.get_value "icc-profile-data"
|
17
|
+
puts "profile has #{profile.length} bytes"
|
18
18
|
end
|
data/example/example5.rb
CHANGED
@@ -1,31 +1,30 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
|
3
|
-
require
|
3
|
+
require "vips"
|
4
4
|
|
5
|
-
# this makes vips keep a list of all active objects
|
5
|
+
# this makes vips keep a list of all active objects
|
6
6
|
# Vips::leak_set true
|
7
7
|
|
8
8
|
# disable the operation cache
|
9
9
|
# Vips::cache_set_max 0
|
10
10
|
|
11
11
|
# turn on debug logging
|
12
|
-
#Vips.set_debug true
|
12
|
+
# Vips.set_debug true
|
13
13
|
|
14
14
|
if ARGV.length < 2
|
15
|
-
|
15
|
+
raise "usage: #{$PROGRAM_NAME}: input-file output-file"
|
16
16
|
end
|
17
17
|
|
18
|
-
im = Vips::Image.new_from_file ARGV[0], :
|
18
|
+
im = Vips::Image.new_from_file ARGV[0], access: :sequential
|
19
19
|
|
20
20
|
im *= [1, 2, 1]
|
21
21
|
|
22
22
|
# we want to be able to specify a scale for the convolution mask, so we have to
|
23
23
|
# make it ourselves
|
24
24
|
# if you are OK with scale=1, you can just pass the array directly to .conv()
|
25
|
-
mask = Vips::Image.new_from_array [
|
26
|
-
|
27
|
-
|
28
|
-
[-1, -1, -1]], 8
|
25
|
+
mask = Vips::Image.new_from_array [[-1, -1, -1],
|
26
|
+
[-1, 16, -1],
|
27
|
+
[-1, -1, -1]], 8
|
29
28
|
im = im.conv mask
|
30
29
|
|
31
30
|
im.write_to_file ARGV[1]
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "ffi"
|
4
|
+
require "forwardable"
|
5
5
|
|
6
6
|
# this is really very crude logging
|
7
7
|
|
@@ -10,277 +10,259 @@ $vips_debug = true
|
|
10
10
|
|
11
11
|
# @private
|
12
12
|
def log str
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
if $vips_debug
|
14
|
+
puts str
|
15
|
+
end
|
16
16
|
end
|
17
17
|
|
18
18
|
def set_debug debug
|
19
|
-
|
19
|
+
$vips_debug = debug
|
20
20
|
end
|
21
21
|
|
22
22
|
module Libc
|
23
|
-
|
24
|
-
|
23
|
+
extend FFI::Library
|
24
|
+
ffi_lib FFI::Library::LIBC
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
attach_function :malloc, [:size_t], :pointer
|
27
|
+
attach_function :free, [:pointer], :void
|
28
28
|
end
|
29
29
|
|
30
30
|
module GLib
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
layout :g_type_instance, :pointer,
|
74
|
-
:ref_count, :uint,
|
75
|
-
:qdata, :pointer
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
# the struct with unref ... manage object lifetime with this
|
81
|
-
class ManagedStruct < FFI::ManagedStruct
|
82
|
-
include GObjectLayout
|
83
|
-
|
84
|
-
def initialize(ptr)
|
85
|
-
log "GLib::GObject::ManagedStruct.new: #{ptr}"
|
86
|
-
super
|
87
|
-
end
|
88
|
-
|
89
|
-
def self.release(ptr)
|
90
|
-
log "GLib::GObject::ManagedStruct.release: unreffing #{ptr}"
|
91
|
-
GLib::g_object_unref(ptr) unless ptr.null?
|
92
|
-
end
|
93
|
-
|
31
|
+
extend FFI::Library
|
32
|
+
ffi_lib "gobject-2.0"
|
33
|
+
|
34
|
+
def self.set_log_domain(_domain)
|
35
|
+
# FIXME: this needs hooking up
|
36
|
+
end
|
37
|
+
|
38
|
+
# we have a set of things we need to inherit in different ways:
|
39
|
+
#
|
40
|
+
# - we want to be able to subclass GObject in a simple way
|
41
|
+
# - the layouts of the nested structs
|
42
|
+
# - casting between structs which share a base
|
43
|
+
# - gobject refcounting
|
44
|
+
#
|
45
|
+
# the solution is to split the class into four areas which we treat
|
46
|
+
# differently:
|
47
|
+
#
|
48
|
+
# - we have a "wrapper" Ruby class to allow easy subclassing ... this has a
|
49
|
+
# @struct member which holds the actual pointer
|
50
|
+
# - we use "forwardable" to forward the various ffi methods on to the
|
51
|
+
# @struct member ... we arrange things so that subclasses do not need to
|
52
|
+
# do the forwarding themselves
|
53
|
+
# - we have two versions of the struct: a plain one which we can use for
|
54
|
+
# casting that will not change the refcounts
|
55
|
+
# - and a managed one with an unref which we just use for .new
|
56
|
+
# - we separate the struct layout into a separate module to avoid repeating
|
57
|
+
# ourselves
|
58
|
+
|
59
|
+
class GObject
|
60
|
+
extend Forwardable
|
61
|
+
extend SingleForwardable
|
62
|
+
|
63
|
+
def_instance_delegators :@struct, :[], :to_ptr
|
64
|
+
def_single_delegators :ffi_struct, :ptr
|
65
|
+
|
66
|
+
# the layout of the GObject struct
|
67
|
+
module GObjectLayout
|
68
|
+
def self.included(base)
|
69
|
+
base.class_eval do
|
70
|
+
layout :g_type_instance, :pointer,
|
71
|
+
:ref_count, :uint,
|
72
|
+
:qdata, :pointer
|
94
73
|
end
|
74
|
+
end
|
75
|
+
end
|
95
76
|
|
96
|
-
|
97
|
-
|
98
|
-
|
77
|
+
# the struct with unref ... manage object lifetime with this
|
78
|
+
class ManagedStruct < FFI::ManagedStruct
|
79
|
+
include GObjectLayout
|
99
80
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
81
|
+
def initialize(ptr)
|
82
|
+
log "GLib::GObject::ManagedStruct.new: #{ptr}"
|
83
|
+
super
|
84
|
+
end
|
104
85
|
|
105
|
-
|
86
|
+
def self.release(ptr)
|
87
|
+
log "GLib::GObject::ManagedStruct.release: unreffing #{ptr}"
|
88
|
+
GLib.g_object_unref(ptr) unless ptr.null?
|
89
|
+
end
|
90
|
+
end
|
106
91
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
# here we use ManagedStruct, not Struct, since this is the ref that will
|
111
|
-
# need the unref
|
112
|
-
def initialize(ptr)
|
113
|
-
log "GLib::GObject.initialize: ptr = #{ptr}"
|
114
|
-
@struct = ffi_managed_struct.new(ptr)
|
115
|
-
end
|
92
|
+
# the plain struct ... cast with this
|
93
|
+
class Struct < FFI::Struct
|
94
|
+
include GObjectLayout
|
116
95
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
96
|
+
def initialize(ptr)
|
97
|
+
log "GLib::GObject::Struct.new: #{ptr}"
|
98
|
+
super
|
99
|
+
end
|
100
|
+
end
|
121
101
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
102
|
+
# don't allow ptr == nil, we never want to allocate a GObject struct
|
103
|
+
# ourselves, we just want to wrap GLib-allocated GObjects
|
104
|
+
#
|
105
|
+
# here we use ManagedStruct, not Struct, since this is the ref that will
|
106
|
+
# need the unref
|
107
|
+
def initialize(ptr)
|
108
|
+
log "GLib::GObject.initialize: ptr = #{ptr}"
|
109
|
+
@struct = ffi_managed_struct.new(ptr)
|
110
|
+
end
|
127
111
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
112
|
+
# access to the cast struct for this class
|
113
|
+
def ffi_struct
|
114
|
+
self.class.ffi_struct
|
115
|
+
end
|
132
116
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
117
|
+
class << self
|
118
|
+
def ffi_struct
|
119
|
+
const_get(:Struct)
|
120
|
+
end
|
121
|
+
end
|
138
122
|
|
123
|
+
# access to the lifetime managed struct for this class
|
124
|
+
def ffi_managed_struct
|
125
|
+
self.class.ffi_managed_struct
|
139
126
|
end
|
140
127
|
|
141
|
-
|
142
|
-
|
128
|
+
class << self
|
129
|
+
def ffi_managed_struct
|
130
|
+
const_get(:ManagedStruct)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
143
134
|
|
135
|
+
# :gtype will usually be 64-bit, but will be 32-bit on 32-bit Windows
|
136
|
+
typedef :ulong, :GType
|
144
137
|
end
|
145
138
|
|
146
139
|
module Vips
|
147
|
-
|
148
|
-
|
140
|
+
extend FFI::Library
|
141
|
+
ffi_lib "vips"
|
149
142
|
|
150
|
-
|
151
|
-
|
143
|
+
LOG_DOMAIN = "VIPS"
|
144
|
+
GLib.set_log_domain(LOG_DOMAIN)
|
152
145
|
|
153
|
-
|
154
|
-
|
146
|
+
# need to repeat this
|
147
|
+
typedef :ulong, :GType
|
155
148
|
|
156
|
-
|
157
|
-
|
149
|
+
attach_function :vips_init, [:string], :int
|
150
|
+
attach_function :vips_shutdown, [], :void
|
158
151
|
|
159
|
-
|
160
|
-
|
152
|
+
attach_function :vips_error_buffer, [], :string
|
153
|
+
attach_function :vips_error_clear, [], :void
|
161
154
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
155
|
+
def self.get_error
|
156
|
+
errstr = Vips.vips_error_buffer
|
157
|
+
Vips.vips_error_clear
|
158
|
+
errstr
|
159
|
+
end
|
167
160
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
161
|
+
if Vips.vips_init($0) != 0
|
162
|
+
puts Vips.get_error
|
163
|
+
exit 1
|
164
|
+
end
|
172
165
|
|
173
|
-
|
174
|
-
|
175
|
-
|
166
|
+
at_exit do
|
167
|
+
Vips.vips_shutdown
|
168
|
+
end
|
176
169
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
def self.showall
|
181
|
-
if $vips_debug
|
182
|
-
GC.start
|
183
|
-
vips_object_print_all
|
184
|
-
end
|
185
|
-
end
|
170
|
+
attach_function :vips_object_print_all, [], :void
|
171
|
+
attach_function :vips_leak_set, [:int], :void
|
186
172
|
|
173
|
+
def self.showall
|
187
174
|
if $vips_debug
|
188
|
-
|
175
|
+
GC.start
|
176
|
+
vips_object_print_all
|
189
177
|
end
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
178
|
+
end
|
179
|
+
|
180
|
+
if $vips_debug
|
181
|
+
vips_leak_set 1
|
182
|
+
end
|
183
|
+
|
184
|
+
class VipsObject < GLib::GObject
|
185
|
+
# the layout of the VipsObject struct
|
186
|
+
module VipsObjectLayout
|
187
|
+
def self.included(base)
|
188
|
+
base.class_eval do
|
189
|
+
# don't actually need most of these, remove them later
|
190
|
+
layout :parent, GLib::GObject::Struct,
|
191
|
+
:constructed, :int,
|
192
|
+
:static_object, :int,
|
193
|
+
:argument_table, :pointer,
|
194
|
+
:nickname, :string,
|
195
|
+
:description, :string,
|
196
|
+
:preclose, :int,
|
197
|
+
:close, :int,
|
198
|
+
:postclose, :int,
|
199
|
+
:local_memory, :size_t
|
210
200
|
end
|
211
|
-
|
212
|
-
class Struct < GLib::GObject::Struct
|
213
|
-
include VipsObjectLayout
|
214
|
-
|
215
|
-
def initialize(ptr)
|
216
|
-
log "Vips::VipsObject::Struct.new: #{ptr}"
|
217
|
-
super
|
218
|
-
end
|
219
|
-
|
220
|
-
end
|
221
|
-
|
222
|
-
class ManagedStruct < GLib::GObject::ManagedStruct
|
223
|
-
include VipsObjectLayout
|
224
|
-
|
225
|
-
def initialize(ptr)
|
226
|
-
log "Vips::VipsObject::ManagedStruct.new: #{ptr}"
|
227
|
-
super
|
228
|
-
end
|
229
|
-
|
230
|
-
end
|
231
|
-
|
201
|
+
end
|
232
202
|
end
|
233
203
|
|
234
|
-
class
|
235
|
-
|
236
|
-
# the layout of the VipsImage struct
|
237
|
-
module VipsImageLayout
|
238
|
-
def self.included(base)
|
239
|
-
base.class_eval do
|
240
|
-
layout :parent, VipsObject::Struct
|
241
|
-
# rest opaque
|
242
|
-
end
|
243
|
-
end
|
244
|
-
end
|
204
|
+
class Struct < GLib::GObject::Struct
|
205
|
+
include VipsObjectLayout
|
245
206
|
|
246
|
-
|
247
|
-
|
207
|
+
def initialize(ptr)
|
208
|
+
log "Vips::VipsObject::Struct.new: #{ptr}"
|
209
|
+
super
|
210
|
+
end
|
211
|
+
end
|
248
212
|
|
249
|
-
|
250
|
-
|
251
|
-
super
|
252
|
-
end
|
213
|
+
class ManagedStruct < GLib::GObject::ManagedStruct
|
214
|
+
include VipsObjectLayout
|
253
215
|
|
216
|
+
def initialize(ptr)
|
217
|
+
log "Vips::VipsObject::ManagedStruct.new: #{ptr}"
|
218
|
+
super
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
class VipsImage < VipsObject
|
224
|
+
# the layout of the VipsImage struct
|
225
|
+
module VipsImageLayout
|
226
|
+
def self.included(base)
|
227
|
+
base.class_eval do
|
228
|
+
layout :parent, VipsObject::Struct
|
229
|
+
# rest opaque
|
254
230
|
end
|
231
|
+
end
|
232
|
+
end
|
255
233
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
def initialize(ptr)
|
260
|
-
log "Vips::VipsImage::ManagedStruct.new: #{ptr}"
|
261
|
-
super
|
262
|
-
end
|
234
|
+
class Struct < VipsObject::Struct
|
235
|
+
include VipsImageLayout
|
263
236
|
|
264
|
-
|
237
|
+
def initialize(ptr)
|
238
|
+
log "Vips::VipsImage::Struct.new: #{ptr}"
|
239
|
+
super
|
240
|
+
end
|
241
|
+
end
|
265
242
|
|
266
|
-
|
267
|
-
|
268
|
-
end
|
243
|
+
class ManagedStruct < VipsObject::ManagedStruct
|
244
|
+
include VipsImageLayout
|
269
245
|
|
246
|
+
def initialize(ptr)
|
247
|
+
log "Vips::VipsImage::ManagedStruct.new: #{ptr}"
|
248
|
+
super
|
249
|
+
end
|
270
250
|
end
|
271
251
|
|
272
|
-
|
252
|
+
def self.new_partial
|
253
|
+
VipsImage.new(Vips.vips_image_new)
|
254
|
+
end
|
255
|
+
end
|
273
256
|
|
257
|
+
attach_function :vips_image_new, [], :pointer
|
274
258
|
end
|
275
259
|
|
276
260
|
puts "creating image"
|
277
|
-
begin
|
278
|
-
x = Vips::VipsImage.new_partial
|
279
|
-
puts "x = #{x}"
|
280
|
-
puts ""
|
281
|
-
puts "x[:parent] = #{x[:parent]}"
|
282
|
-
puts ""
|
283
|
-
puts "x[:parent][:description] = #{x[:parent][:description]}"
|
284
|
-
puts ""
|
285
|
-
end
|
286
261
|
|
262
|
+
x = Vips::VipsImage.new_partial
|
263
|
+
puts "x = #{x}"
|
264
|
+
puts ""
|
265
|
+
puts "x[:parent] = #{x[:parent]}"
|
266
|
+
puts ""
|
267
|
+
puts "x[:parent][:description] = #{x[:parent][:description]}"
|
268
|
+
puts ""
|