ruby-vips8 0.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 +7 -0
- data/.rspec +1 -0
- data/.yardopts +10 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +84 -0
- data/LICENSE.txt +20 -0
- data/README.md +170 -0
- data/Rakefile +45 -0
- data/TODO +11 -0
- data/VERSION +1 -0
- data/example/annotate.rb +17 -0
- data/example/daltonize8.rb +75 -0
- data/example/example1.rb +84 -0
- data/example/example2.rb +31 -0
- data/example/example3.rb +19 -0
- data/example/example4.rb +18 -0
- data/example/example5.rb +31 -0
- data/example/trim8.rb +41 -0
- data/example/watermark.rb +44 -0
- data/example/wobble.rb +36 -0
- data/lib/vips8.rb +153 -0
- data/lib/vips8/access.rb +14 -0
- data/lib/vips8/align.rb +11 -0
- data/lib/vips8/angle.rb +12 -0
- data/lib/vips8/angle45.rb +16 -0
- data/lib/vips8/argument.rb +163 -0
- data/lib/vips8/bandformat.rb +20 -0
- data/lib/vips8/call.rb +302 -0
- data/lib/vips8/coding.rb +14 -0
- data/lib/vips8/demandstyle.rb +35 -0
- data/lib/vips8/direction.rb +11 -0
- data/lib/vips8/error.rb +30 -0
- data/lib/vips8/extend.rb +22 -0
- data/lib/vips8/foreignflags.rb +20 -0
- data/lib/vips8/image.rb +1383 -0
- data/lib/vips8/interpolate.rb +37 -0
- data/lib/vips8/interpretation.rb +28 -0
- data/lib/vips8/methods.rb +1807 -0
- data/lib/vips8/operation.rb +19 -0
- data/ruby-vips8.gemspec +112 -0
- data/spec/image_spec.rb +515 -0
- data/spec/samples/balloon.v +0 -0
- data/spec/samples/ghost.ppm +405 -0
- data/spec/samples/huge.jpg +0 -0
- data/spec/samples/icc.jpg +0 -0
- data/spec/samples/lcd.icc +0 -0
- data/spec/samples/lion.svg +154 -0
- data/spec/samples/sample.csv +7 -0
- data/spec/samples/sample.exr +0 -0
- data/spec/samples/wagon.jpg +0 -0
- data/spec/samples/wagon.v +0 -0
- data/spec/spec_helper.rb +49 -0
- data/spec/vips_spec.rb +74 -0
- metadata +198 -0
data/example/example1.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'vips8'
|
4
|
+
$vips_debug = true
|
5
|
+
|
6
|
+
puts ""
|
7
|
+
puts "starting up:"
|
8
|
+
|
9
|
+
# this makes vips keep a list of all active objects which we can print out
|
10
|
+
Vips::leak_set true
|
11
|
+
|
12
|
+
# disable the operation cache
|
13
|
+
Vips::cache_set_max 0
|
14
|
+
|
15
|
+
puts ""
|
16
|
+
puts "creating object:"
|
17
|
+
x = Vips::Image.new
|
18
|
+
Vips::Object::print_all
|
19
|
+
|
20
|
+
puts ""
|
21
|
+
puts "freeing object:"
|
22
|
+
x = nil
|
23
|
+
GC.start
|
24
|
+
Vips::Object::print_all
|
25
|
+
|
26
|
+
puts ""
|
27
|
+
puts "creating operation:"
|
28
|
+
op = Vips::Operation.new "black"
|
29
|
+
Vips::Object::print_all
|
30
|
+
op.set_property "width", 200
|
31
|
+
op.set_property "height", 300
|
32
|
+
|
33
|
+
puts ""
|
34
|
+
puts "after operation init:"
|
35
|
+
GC.start
|
36
|
+
Vips::Object::print_all
|
37
|
+
|
38
|
+
puts ""
|
39
|
+
puts "operation lookup:"
|
40
|
+
op2 = Vips::cache_operation_lookup op
|
41
|
+
if op2
|
42
|
+
puts "cache hit"
|
43
|
+
op = op2
|
44
|
+
op2 = nil
|
45
|
+
else
|
46
|
+
puts "cache miss ... building"
|
47
|
+
if not op.build
|
48
|
+
puts "*** build error"
|
49
|
+
end
|
50
|
+
Vips::cache_operation_add op
|
51
|
+
end
|
52
|
+
|
53
|
+
puts ""
|
54
|
+
puts "after build:"
|
55
|
+
GC.start
|
56
|
+
Vips::Object::print_all
|
57
|
+
|
58
|
+
puts ""
|
59
|
+
puts "fetching output:"
|
60
|
+
im = op.get_property "out"
|
61
|
+
GC.start
|
62
|
+
Vips::Object::print_all
|
63
|
+
|
64
|
+
puts ""
|
65
|
+
puts "fetching output again:"
|
66
|
+
im2 = op.get_property "out"
|
67
|
+
GC.start
|
68
|
+
Vips::Object::print_all
|
69
|
+
|
70
|
+
puts ""
|
71
|
+
puts "freeing operation:"
|
72
|
+
op.unref_outputs
|
73
|
+
op = nil
|
74
|
+
op2 = nil
|
75
|
+
GC.start
|
76
|
+
Vips::Object::print_all
|
77
|
+
|
78
|
+
puts ""
|
79
|
+
puts "shutting down:"
|
80
|
+
im = nil
|
81
|
+
im2 = nil
|
82
|
+
GC.start
|
83
|
+
Vips::shutdown
|
84
|
+
GC.start
|
data/example/example2.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'vips8'
|
4
|
+
|
5
|
+
puts ""
|
6
|
+
puts "starting up:"
|
7
|
+
|
8
|
+
# this makes vips keep a list of all active objects which we can print out
|
9
|
+
Vips::leak_set true
|
10
|
+
|
11
|
+
# disable the operation cache
|
12
|
+
Vips::cache_set_max 0
|
13
|
+
|
14
|
+
n = 100
|
15
|
+
|
16
|
+
n.times do |i|
|
17
|
+
puts ""
|
18
|
+
puts "call #{i} ..."
|
19
|
+
out = Vips::call "black", 200, 300
|
20
|
+
if out.width != 200 or out.height != 300
|
21
|
+
puts "bad image result from black"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
puts ""
|
26
|
+
puts "after #{n} calls:"
|
27
|
+
GC.start
|
28
|
+
Vips::Object::print_all
|
29
|
+
|
30
|
+
puts ""
|
31
|
+
puts "shutting down:"
|
data/example/example3.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'vips8'
|
4
|
+
|
5
|
+
# this makes vips keep a list of all active objects
|
6
|
+
# Vips::leak_set true
|
7
|
+
|
8
|
+
# disable the operation cache
|
9
|
+
# Vips::cache_set_max 0
|
10
|
+
|
11
|
+
# turn on debug logging
|
12
|
+
#Vips.set_debug true
|
13
|
+
|
14
|
+
10000.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
|
+
end
|
data/example/example4.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'vips8'
|
4
|
+
|
5
|
+
# this makes vips keep a list of all active objects
|
6
|
+
Vips::leak_set true
|
7
|
+
|
8
|
+
# disable the operation cache
|
9
|
+
#Vips::cache_set_max 0
|
10
|
+
|
11
|
+
# turn on debug logging
|
12
|
+
#Vips.set_debug true
|
13
|
+
|
14
|
+
ARGV.each do |filename|
|
15
|
+
im = Vips::Image.new_from_file filename
|
16
|
+
profile = im.get_value "icc-profile-data"
|
17
|
+
puts "profile has #{profile.length} bytes"
|
18
|
+
end
|
data/example/example5.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'vips8'
|
4
|
+
|
5
|
+
# this makes vips keep a list of all active objects
|
6
|
+
# Vips::leak_set true
|
7
|
+
|
8
|
+
# disable the operation cache
|
9
|
+
# Vips::cache_set_max 0
|
10
|
+
|
11
|
+
# turn on debug logging
|
12
|
+
#Vips.set_debug true
|
13
|
+
|
14
|
+
if ARGV.length < 2
|
15
|
+
raise "usage: #{$PROGRAM_NAME}: input-file output-file"
|
16
|
+
end
|
17
|
+
|
18
|
+
im = Vips::Image.new_from_file ARGV[0], :access => :sequential
|
19
|
+
|
20
|
+
im *= [1, 2, 1]
|
21
|
+
|
22
|
+
# we want to be able to specify a scale for the convolution mask, so we have to
|
23
|
+
# make it ourselves
|
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
|
+
[-1, -1, -1],
|
27
|
+
[-1, 16, -1],
|
28
|
+
[-1, -1, -1]], 8
|
29
|
+
im = im.conv mask
|
30
|
+
|
31
|
+
im.write_to_file ARGV[1]
|
data/example/trim8.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# An equivalent of ImageMagick's -trim in ruby-vips8 ... automatically remove
|
4
|
+
# "boring" image edges.
|
5
|
+
|
6
|
+
# We use .project to sum the rows and columns of a 0/255 mask image, the first
|
7
|
+
# non-zero row or column is the object edge. We make the mask image with an
|
8
|
+
# amount-different-from-background image plus a threshold.
|
9
|
+
|
10
|
+
require 'vips8'
|
11
|
+
|
12
|
+
im = Vips::Image.new_from_file ARGV[0]
|
13
|
+
|
14
|
+
# find the value of the pixel at (0, 0) ... we will search for all pixels
|
15
|
+
# significantly different from this
|
16
|
+
background = im.getpoint(0, 0)
|
17
|
+
|
18
|
+
# we need to smooth the image, subtract the background from every pixel, take
|
19
|
+
# the absolute value of the difference, then threshold
|
20
|
+
mask = (im.median - background).abs > 10
|
21
|
+
|
22
|
+
# sum mask rows and columns, then search for the first non-zero sum in each
|
23
|
+
# direction
|
24
|
+
columns, rows = mask.project
|
25
|
+
|
26
|
+
first_column, first_row = columns.profile
|
27
|
+
left = first_row.min
|
28
|
+
|
29
|
+
first_column, first_row = columns.fliphor.profile
|
30
|
+
right = columns.width - first_row.min
|
31
|
+
|
32
|
+
first_column, first_row = rows.profile
|
33
|
+
top = first_column.min
|
34
|
+
|
35
|
+
first_column, first_row = rows.flipver.profile
|
36
|
+
bottom = rows.height - first_column.min
|
37
|
+
|
38
|
+
# and now crop the original image
|
39
|
+
im = im.crop left, top, right - left, bottom - top
|
40
|
+
|
41
|
+
im.write_to_file ARGV[1]
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'vips8'
|
4
|
+
|
5
|
+
im = Vips::Image.new_from_file ARGV[0], :access => :sequential
|
6
|
+
|
7
|
+
text = Vips::Image.text ARGV[2], :width => 500, :dpi => 300
|
8
|
+
text = (text * 0.3).cast(:uchar)
|
9
|
+
text = text.embed 100, 100, text.width + 200, text.width + 200
|
10
|
+
text = text.replicate 1 + im.width / text.width, 1 + im.height / text.height
|
11
|
+
text = text.crop 0, 0, im.width, im.height
|
12
|
+
|
13
|
+
# we want to blend into the visible part of the image and leave any alpha
|
14
|
+
# channels untouched ... we need to split im into two parts
|
15
|
+
|
16
|
+
# guess how many bands from the start of im contain visible colour information
|
17
|
+
if im.bands >= 4 and im.interpretation == :cmyk
|
18
|
+
# cmyk image
|
19
|
+
n_visible_bands = 4
|
20
|
+
text_colour = [0, 255, 0, 0]
|
21
|
+
elsif im.bands >= 3
|
22
|
+
# rgb image
|
23
|
+
n_visible_bands = 3
|
24
|
+
text_colour = [255, 0, 0]
|
25
|
+
else
|
26
|
+
# mono image
|
27
|
+
n_visible_bands = 1
|
28
|
+
text_colour = 255
|
29
|
+
end
|
30
|
+
|
31
|
+
# split into image and alpha
|
32
|
+
if im.bands - n_visible_bands > 0
|
33
|
+
alpha = im.extract_band n_visible_bands, :n => im.bands - n_visible_bands
|
34
|
+
im = im.extract_band 0, :n => n_visible_bands
|
35
|
+
else
|
36
|
+
alpha = nil
|
37
|
+
end
|
38
|
+
|
39
|
+
marked = text.ifthenelse text_colour, im, :blend => true
|
40
|
+
|
41
|
+
# reattach alpha
|
42
|
+
marked = marked.bandjoin alpha if alpha
|
43
|
+
|
44
|
+
marked.write_to_file ARGV[1]
|
data/example/wobble.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'vips8'
|
4
|
+
|
5
|
+
image = Vips::Image.new_from_file ARGV[0]
|
6
|
+
|
7
|
+
module Vips
|
8
|
+
class Image
|
9
|
+
def wobble
|
10
|
+
# this makes an image where pixel (0, 0) (at the top-left) has
|
11
|
+
# value [0, 0], and pixel (image.width, image.height) at the
|
12
|
+
# bottom-right has value [image.width, image.height]
|
13
|
+
index = Vips::Image.xyz width, height
|
14
|
+
|
15
|
+
# make a version with (0, 0) at the centre, negative values up
|
16
|
+
# and left, positive down and right
|
17
|
+
centre = index - [width / 2, height / 2]
|
18
|
+
|
19
|
+
# to polar space, so each pixel is now distance and angle in degrees
|
20
|
+
polar = centre.polar
|
21
|
+
|
22
|
+
# scale sin(distance) by 1/distance to make a wavey pattern
|
23
|
+
d = ((polar[0] * 3).sin * 10000) / (polar[0] + 1)
|
24
|
+
|
25
|
+
# and back to rectangular coordinates again to make a set of
|
26
|
+
# vectors we can apply to the original index image
|
27
|
+
index += d.bandjoin(polar[1]).rect
|
28
|
+
|
29
|
+
# finally, use our modified index image to distort!
|
30
|
+
mapim index
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
image = image.wobble
|
36
|
+
image.write_to_file ARGV[1]
|
data/lib/vips8.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
# This module provides a set of overrides for the vips image processing library
|
2
|
+
# used via the gobject-introspection gem.
|
3
|
+
#
|
4
|
+
# Author:: John Cupitt (mailto:jcupitt@gmail.com)
|
5
|
+
# License:: MIT
|
6
|
+
|
7
|
+
# @private
|
8
|
+
def log str
|
9
|
+
if $vips_debug
|
10
|
+
puts str
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# copied from ruby-gnome2/gstreamer/lib/gst.rb without much understanding
|
15
|
+
|
16
|
+
require 'pathname'
|
17
|
+
require 'gobject-introspection'
|
18
|
+
|
19
|
+
# pick up a local girepository/lib in preference to the system one
|
20
|
+
base_dir = Pathname.new(__FILE__).dirname.dirname.expand_path
|
21
|
+
vendor_dir = base_dir + "vendor" + "local"
|
22
|
+
vendor_bin_dir = vendor_dir + "bin"
|
23
|
+
GLib.prepend_dll_path(vendor_bin_dir)
|
24
|
+
vendor_girepository_dir = vendor_dir + "lib" + "girepository-1.0"
|
25
|
+
GObjectIntrospection.prepend_typelib_path(vendor_girepository_dir)
|
26
|
+
|
27
|
+
module Vips
|
28
|
+
# @private
|
29
|
+
LOG_DOMAIN = "VIPS"
|
30
|
+
GLib::Log.set_log_domain(LOG_DOMAIN)
|
31
|
+
|
32
|
+
# about as crude as you could get
|
33
|
+
$vips_debug = false
|
34
|
+
|
35
|
+
# Turn debug logging on and off.
|
36
|
+
#
|
37
|
+
# @param dbg [Boolean] Set true to print debug log messages
|
38
|
+
def self.set_debug dbg
|
39
|
+
$vips_debug = dbg
|
40
|
+
end
|
41
|
+
|
42
|
+
class << self
|
43
|
+
# @private
|
44
|
+
def const_missing(name)
|
45
|
+
log "Vips::const_missing: #{name}"
|
46
|
+
|
47
|
+
init()
|
48
|
+
if const_defined?(name)
|
49
|
+
const_get(name)
|
50
|
+
else
|
51
|
+
super
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# @private
|
56
|
+
def method_missing(name, *args, &block)
|
57
|
+
log "Vips::method_missing: #{name}, #{args}, #{block}"
|
58
|
+
|
59
|
+
init()
|
60
|
+
if respond_to?(name)
|
61
|
+
__send__(name, *args, &block)
|
62
|
+
else
|
63
|
+
super
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# @private
|
68
|
+
def init(*argv)
|
69
|
+
log "Vips::init: #{argv}"
|
70
|
+
|
71
|
+
class << self
|
72
|
+
remove_method(:init)
|
73
|
+
remove_method(:const_missing)
|
74
|
+
remove_method(:method_missing)
|
75
|
+
end
|
76
|
+
|
77
|
+
loader = Loader.new(self, argv)
|
78
|
+
begin
|
79
|
+
loader.load("Vips")
|
80
|
+
rescue
|
81
|
+
puts "Unable to load Vips"
|
82
|
+
puts " Check that the vips library has been installed and is"
|
83
|
+
puts " on your library path."
|
84
|
+
puts " Check that the typelib `Vips-8.0.typelib` has been "
|
85
|
+
puts " installed, and that it is on your GI_TYPELIB_PATH."
|
86
|
+
raise
|
87
|
+
end
|
88
|
+
|
89
|
+
require 'vips8/error'
|
90
|
+
require 'vips8/argument'
|
91
|
+
require 'vips8/operation'
|
92
|
+
require 'vips8/call'
|
93
|
+
require 'vips8/image'
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# @private
|
98
|
+
class Loader < GObjectIntrospection::Loader
|
99
|
+
def initialize(base_module, init_arguments)
|
100
|
+
log "Vips::Loader.initialize: #{base_module}, #{init_arguments}"
|
101
|
+
|
102
|
+
super(base_module)
|
103
|
+
@init_arguments = init_arguments
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
def pre_load(repository, namespace)
|
108
|
+
log "Vips::Loader.pre_load: #{repository}, #{namespace}"
|
109
|
+
|
110
|
+
call_init_function(repository, namespace)
|
111
|
+
define_value_modules
|
112
|
+
end
|
113
|
+
|
114
|
+
def call_init_function(repository, namespace)
|
115
|
+
log "Vips::Loader.call_init_function: #{repository}, #{namespace}"
|
116
|
+
|
117
|
+
# call Vips::init
|
118
|
+
init = repository.find(namespace, "init")
|
119
|
+
succeeded, argv, error = init.invoke(:arguments => [$PROGRAM_NAME])
|
120
|
+
|
121
|
+
# TODO get the vips error buffer
|
122
|
+
raise error unless succeeded
|
123
|
+
end
|
124
|
+
|
125
|
+
def define_value_modules
|
126
|
+
@value_functions_module = Module.new
|
127
|
+
@value_methods_module = Module.new
|
128
|
+
@base_module.const_set("ValueFunctions", @value_functions_module)
|
129
|
+
@base_module.const_set("ValueMethods", @value_methods_module)
|
130
|
+
end
|
131
|
+
|
132
|
+
def post_load(repository, namespace)
|
133
|
+
log "Vips::Loader.post_load:"
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
at_exit {
|
140
|
+
Vips::shutdown if Vips.respond_to? :shutdown
|
141
|
+
}
|
142
|
+
|
143
|
+
# this makes vips keep a list of all active objects which we can print out
|
144
|
+
Vips::leak_set true if $vips_debug
|
145
|
+
|
146
|
+
# @private
|
147
|
+
def showall
|
148
|
+
if $vips_debug
|
149
|
+
GC.start
|
150
|
+
Vips::Object::print_all
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|