ruby-vips 0.3.14 → 1.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 +22 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +46 -31
- data/{LICENSE → LICENSE.txt} +1 -1
- data/README.md +101 -145
- data/Rakefile +45 -0
- data/TODO +8 -32
- 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/vips.rb +151 -14
- data/lib/vips/access.rb +14 -0
- data/lib/vips/align.rb +11 -0
- data/lib/vips/angle.rb +12 -0
- data/lib/vips/angle45.rb +16 -0
- data/lib/vips/argument.rb +163 -0
- data/lib/vips/bandformat.rb +20 -0
- data/lib/vips/call.rb +302 -0
- data/lib/vips/coding.rb +14 -0
- data/lib/vips/demandstyle.rb +35 -0
- data/lib/vips/direction.rb +11 -0
- data/lib/vips/error.rb +30 -0
- data/lib/vips/extend.rb +22 -0
- data/lib/vips/foreignflags.rb +20 -0
- data/lib/vips/image.rb +1382 -0
- data/lib/vips/interpolate.rb +37 -0
- data/lib/vips/interpretation.rb +28 -0
- data/lib/vips/methods.rb +1807 -0
- data/lib/vips/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 +110 -70
- data/ext/extconf.rb +0 -31
- data/ext/header.c +0 -457
- data/ext/header.h +0 -9
- data/ext/image.c +0 -629
- data/ext/image.h +0 -72
- data/ext/image_arithmetic.c +0 -936
- data/ext/image_arithmetic.h +0 -38
- data/ext/image_boolean.c +0 -301
- data/ext/image_boolean.h +0 -8
- data/ext/image_colour.c +0 -590
- data/ext/image_colour.h +0 -36
- data/ext/image_conversion.c +0 -884
- data/ext/image_conversion.h +0 -38
- data/ext/image_convolution.c +0 -368
- data/ext/image_convolution.h +0 -13
- data/ext/image_freq_filt.c +0 -740
- data/ext/image_freq_filt.h +0 -27
- data/ext/image_histograms_lut.c +0 -643
- data/ext/image_histograms_lut.h +0 -28
- data/ext/image_morphology.c +0 -327
- data/ext/image_morphology.h +0 -13
- data/ext/image_mosaicing.c +0 -554
- data/ext/image_mosaicing.h +0 -15
- data/ext/image_relational.c +0 -384
- data/ext/image_relational.h +0 -8
- data/ext/image_resample.c +0 -249
- data/ext/image_resample.h +0 -9
- data/ext/interpolator.c +0 -106
- data/ext/interpolator.h +0 -7
- data/ext/mask.c +0 -347
- data/ext/mask.h +0 -18
- data/ext/reader.c +0 -261
- data/ext/reader.h +0 -2
- data/ext/ruby_vips.c +0 -188
- data/ext/ruby_vips.h +0 -72
- data/ext/tags +0 -450
- data/ext/writer.c +0 -371
- data/ext/writer.h +0 -2
- data/lib/vips/reader.rb +0 -272
- data/lib/vips/version.rb +0 -3
- data/lib/vips/writer.rb +0 -342
- data/ruby-vips.gemspec +0 -100
- data/ruby.supp +0 -134
data/example/wobble.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'vips'
|
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/vips.rb
CHANGED
@@ -1,16 +1,153 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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 'vips/error'
|
90
|
+
require 'vips/argument'
|
91
|
+
require 'vips/operation'
|
92
|
+
require 'vips/call'
|
93
|
+
require 'vips/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
|
14
151
|
end
|
15
|
-
end
|
16
152
|
end
|
153
|
+
|
data/lib/vips/access.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Vips
|
2
|
+
# The type of access an operation has to supply.
|
3
|
+
#
|
4
|
+
# * `:random` means requests can come in any order.
|
5
|
+
#
|
6
|
+
# * `:sequential` means requests will be top-to-bottom, but with some
|
7
|
+
# amount of buffering behind the read point for small non-local
|
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
|
13
|
+
end
|
14
|
+
end
|
data/lib/vips/align.rb
ADDED
data/lib/vips/angle.rb
ADDED
data/lib/vips/angle45.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Vips
|
2
|
+
|
3
|
+
# Various fixed 45 degree rotation angles. See {Vips::Image.rot45}.
|
4
|
+
#
|
5
|
+
# * `:d0` no rotate
|
6
|
+
# * `:d45` 45 degrees clockwise
|
7
|
+
# * `:d90` 90 degrees clockwise
|
8
|
+
# * `:d135` 135 degrees clockwise
|
9
|
+
# * `:d180` 180 degrees
|
10
|
+
# * `:d225` 135 degrees anti-clockwise
|
11
|
+
# * `:d270` 90 degrees anti-clockwise
|
12
|
+
# * `:d315` 45 degrees anti-clockwise
|
13
|
+
|
14
|
+
class Angle45
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
|
2
|
+
module Vips
|
3
|
+
|
4
|
+
# This class is used internally to convert Ruby values to arguments to
|
5
|
+
# libvips operations.
|
6
|
+
# @private
|
7
|
+
class Argument
|
8
|
+
attr_reader :op, :name, :flags, :priority, :isset, :prop
|
9
|
+
attr_reader :blurb, :gtype, :type
|
10
|
+
|
11
|
+
# map gobject-introspection's ruby class names to ours
|
12
|
+
@@map_goi_to_vips = {
|
13
|
+
"TrueClass" => "Boolean",
|
14
|
+
"Vips::ArrayDouble" => "Array<Double>",
|
15
|
+
"Vips::ArrayInt" => "Array<Integer>",
|
16
|
+
"Vips::ArrayImage" => "Array<Image>",
|
17
|
+
"Vips::ArrayString" => "Array<String>",
|
18
|
+
}
|
19
|
+
|
20
|
+
def initialize(op, name)
|
21
|
+
@op = op
|
22
|
+
@name = name.tr '-', '_'
|
23
|
+
@prop = op.gtype.to_class.property name
|
24
|
+
@blurb = @prop.blurb
|
25
|
+
@gtype = prop.value_type
|
26
|
+
@flags = op.get_argument_flags name
|
27
|
+
@priority = op.get_argument_priority @name
|
28
|
+
@isset = op.argument_isset @name
|
29
|
+
|
30
|
+
type = GLib::Type[gtype.name].to_class.name
|
31
|
+
type = @@map_goi_to_vips[type] if @@map_goi_to_vips.include? type
|
32
|
+
@type = type
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def self.imageize match_image, value
|
38
|
+
return value if match_image == nil
|
39
|
+
return value if value.is_a? Vips::Image
|
40
|
+
|
41
|
+
# 2D array values become tiny 2D images
|
42
|
+
if value.is_a? Array and value[0].is_a? Array
|
43
|
+
return Vips::Image.new_from_array value
|
44
|
+
end
|
45
|
+
|
46
|
+
# if there's nothing to match to, we also make a 2D image
|
47
|
+
if match_image == nil
|
48
|
+
return Vips::Image.new_from_array value
|
49
|
+
end
|
50
|
+
|
51
|
+
# we have a 1D array ... use that as a pixel constant and expand
|
52
|
+
# to match match_image
|
53
|
+
pixel = (Vips::Image.black(1, 1) + value).cast(match_image.format)
|
54
|
+
pixel = pixel.copy :interpretation => match_image.interpretation,
|
55
|
+
:xres => match_image.xres, :yres => match_image.yres
|
56
|
+
pixel.embed(0, 0, match_image.width, match_image.height,
|
57
|
+
:extend => :copy)
|
58
|
+
end
|
59
|
+
|
60
|
+
# @private
|
61
|
+
class ArrayImageConst < Vips::ArrayImage
|
62
|
+
def self.new(value)
|
63
|
+
if not value.is_a? Array
|
64
|
+
value = [value]
|
65
|
+
end
|
66
|
+
|
67
|
+
match_image = value.find {|x| x.is_a? Vips::Image}
|
68
|
+
if match_image == nil
|
69
|
+
raise Vips::Error,
|
70
|
+
"Argument must contain at least one image."
|
71
|
+
end
|
72
|
+
|
73
|
+
value = value.map {|x| Argument::imageize match_image, x}
|
74
|
+
|
75
|
+
# we'd like to just
|
76
|
+
# super(value)
|
77
|
+
# to construct, but the gobject-introspection gem does not
|
78
|
+
# support new from object array ... instead, we build in stages
|
79
|
+
array = Vips::ArrayImage.empty
|
80
|
+
value.each {|x| array = array.append(x)}
|
81
|
+
|
82
|
+
return array
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# if this gtype needs an array, try to transform the value into one
|
87
|
+
def self.arrayize(gtype, value)
|
88
|
+
arrayize_map = {
|
89
|
+
GLib::Type["VipsArrayDouble"] => Vips::ArrayDouble,
|
90
|
+
GLib::Type["VipsArrayInt"] => Vips::ArrayInt,
|
91
|
+
GLib::Type["VipsArrayImage"] => ArrayImageConst
|
92
|
+
}
|
93
|
+
|
94
|
+
if arrayize_map.has_key? gtype
|
95
|
+
if not value.is_a? Array
|
96
|
+
value = [value]
|
97
|
+
end
|
98
|
+
|
99
|
+
value = arrayize_map[gtype].new(value)
|
100
|
+
end
|
101
|
+
|
102
|
+
value
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.unwrap value
|
106
|
+
[Vips::Blob, Vips::ArrayDouble, Vips::ArrayImage,
|
107
|
+
Vips::ArrayInt, Vips::RefString].each do |cls|
|
108
|
+
if value.is_a? cls
|
109
|
+
value, length = value.get
|
110
|
+
|
111
|
+
# blobs come from gobject-introspection as arrays ...
|
112
|
+
# repack as strings for convenience
|
113
|
+
if value and cls == Vips::Blob
|
114
|
+
value = value.pack("C*")
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
value
|
122
|
+
end
|
123
|
+
|
124
|
+
public
|
125
|
+
|
126
|
+
def set_value(match_image, value)
|
127
|
+
# array-ize
|
128
|
+
value = Argument::arrayize gtype, value
|
129
|
+
|
130
|
+
# blob-ize
|
131
|
+
if gtype.type_is_a? GLib::Type["VipsBlob"]
|
132
|
+
if not value.is_a? Vips::Blob
|
133
|
+
value = Vips::Blob.copy value
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# image-ize
|
138
|
+
if gtype.type_is_a? GLib::Type["VipsImage"]
|
139
|
+
if not value.is_a? Vips::Image
|
140
|
+
value = Argument::imageize match_image, value
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# MODIFY input images need to be copied before assigning them
|
145
|
+
if (flags & :modify) != 0
|
146
|
+
# don't use .copy(): we want to make a new pipeline with no
|
147
|
+
# reference back to the old stuff ... this way we can free the
|
148
|
+
# previous image earlier
|
149
|
+
new_image = Vips::Image.memory
|
150
|
+
value.write new_image
|
151
|
+
value = new_image
|
152
|
+
end
|
153
|
+
|
154
|
+
op.set_property @name, value
|
155
|
+
end
|
156
|
+
|
157
|
+
def get_value
|
158
|
+
Argument::unwrap @op.get_property(@name)
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Vips
|
2
|
+
|
3
|
+
# The format used for each band element. Each corresponds to a native C type
|
4
|
+
# for the current machine.
|
5
|
+
#
|
6
|
+
# * `:notset` invalid setting
|
7
|
+
# * `:uchar` unsigned char format
|
8
|
+
# * `:char` char format
|
9
|
+
# * `:ushort` unsigned short format
|
10
|
+
# * `:short` short format
|
11
|
+
# * `:uint` unsigned int format
|
12
|
+
# * `:int` int format
|
13
|
+
# * `:float` float format
|
14
|
+
# * `:complex` complex (two floats) format
|
15
|
+
# * `:double` double float format
|
16
|
+
# * `:dpcomplex` double complex (two double) format
|
17
|
+
class BandFormat
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|