ruby-vips 0.3.14 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|