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.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +22 -0
  3. data/CHANGELOG.md +4 -0
  4. data/Gemfile +15 -0
  5. data/Gemfile.lock +46 -31
  6. data/{LICENSE → LICENSE.txt} +1 -1
  7. data/README.md +101 -145
  8. data/Rakefile +45 -0
  9. data/TODO +8 -32
  10. data/VERSION +1 -0
  11. data/example/annotate.rb +17 -0
  12. data/example/daltonize8.rb +75 -0
  13. data/example/example1.rb +84 -0
  14. data/example/example2.rb +31 -0
  15. data/example/example3.rb +19 -0
  16. data/example/example4.rb +18 -0
  17. data/example/example5.rb +31 -0
  18. data/example/trim8.rb +41 -0
  19. data/example/watermark.rb +44 -0
  20. data/example/wobble.rb +36 -0
  21. data/lib/vips.rb +151 -14
  22. data/lib/vips/access.rb +14 -0
  23. data/lib/vips/align.rb +11 -0
  24. data/lib/vips/angle.rb +12 -0
  25. data/lib/vips/angle45.rb +16 -0
  26. data/lib/vips/argument.rb +163 -0
  27. data/lib/vips/bandformat.rb +20 -0
  28. data/lib/vips/call.rb +302 -0
  29. data/lib/vips/coding.rb +14 -0
  30. data/lib/vips/demandstyle.rb +35 -0
  31. data/lib/vips/direction.rb +11 -0
  32. data/lib/vips/error.rb +30 -0
  33. data/lib/vips/extend.rb +22 -0
  34. data/lib/vips/foreignflags.rb +20 -0
  35. data/lib/vips/image.rb +1382 -0
  36. data/lib/vips/interpolate.rb +37 -0
  37. data/lib/vips/interpretation.rb +28 -0
  38. data/lib/vips/methods.rb +1807 -0
  39. data/lib/vips/operation.rb +19 -0
  40. data/ruby-vips8.gemspec +112 -0
  41. data/spec/image_spec.rb +515 -0
  42. data/spec/samples/balloon.v +0 -0
  43. data/spec/samples/ghost.ppm +405 -0
  44. data/spec/samples/huge.jpg +0 -0
  45. data/spec/samples/icc.jpg +0 -0
  46. data/spec/samples/lcd.icc +0 -0
  47. data/spec/samples/lion.svg +154 -0
  48. data/spec/samples/sample.csv +7 -0
  49. data/spec/samples/sample.exr +0 -0
  50. data/spec/samples/wagon.jpg +0 -0
  51. data/spec/samples/wagon.v +0 -0
  52. data/spec/spec_helper.rb +49 -0
  53. data/spec/vips_spec.rb +74 -0
  54. metadata +110 -70
  55. data/ext/extconf.rb +0 -31
  56. data/ext/header.c +0 -457
  57. data/ext/header.h +0 -9
  58. data/ext/image.c +0 -629
  59. data/ext/image.h +0 -72
  60. data/ext/image_arithmetic.c +0 -936
  61. data/ext/image_arithmetic.h +0 -38
  62. data/ext/image_boolean.c +0 -301
  63. data/ext/image_boolean.h +0 -8
  64. data/ext/image_colour.c +0 -590
  65. data/ext/image_colour.h +0 -36
  66. data/ext/image_conversion.c +0 -884
  67. data/ext/image_conversion.h +0 -38
  68. data/ext/image_convolution.c +0 -368
  69. data/ext/image_convolution.h +0 -13
  70. data/ext/image_freq_filt.c +0 -740
  71. data/ext/image_freq_filt.h +0 -27
  72. data/ext/image_histograms_lut.c +0 -643
  73. data/ext/image_histograms_lut.h +0 -28
  74. data/ext/image_morphology.c +0 -327
  75. data/ext/image_morphology.h +0 -13
  76. data/ext/image_mosaicing.c +0 -554
  77. data/ext/image_mosaicing.h +0 -15
  78. data/ext/image_relational.c +0 -384
  79. data/ext/image_relational.h +0 -8
  80. data/ext/image_resample.c +0 -249
  81. data/ext/image_resample.h +0 -9
  82. data/ext/interpolator.c +0 -106
  83. data/ext/interpolator.h +0 -7
  84. data/ext/mask.c +0 -347
  85. data/ext/mask.h +0 -18
  86. data/ext/reader.c +0 -261
  87. data/ext/reader.h +0 -2
  88. data/ext/ruby_vips.c +0 -188
  89. data/ext/ruby_vips.h +0 -72
  90. data/ext/tags +0 -450
  91. data/ext/writer.c +0 -371
  92. data/ext/writer.h +0 -2
  93. data/lib/vips/reader.rb +0 -272
  94. data/lib/vips/version.rb +0 -3
  95. data/lib/vips/writer.rb +0 -342
  96. data/ruby-vips.gemspec +0 -100
  97. data/ruby.supp +0 -134
@@ -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]
@@ -1,16 +1,153 @@
1
- # Vips will print warnings to stdout unless this is set
2
- ENV['IM_WARNING'] = "0"
3
-
4
- require 'vips_ext'
5
- require 'vips/version'
6
- require 'vips/reader'
7
- require 'vips/writer'
8
-
9
- module VIPS
10
- class << self
11
- def sequential_mode_supported?
12
- comp = VIPS::LIB_VERSION_ARRAY <=> [7,28,0]
13
- comp >= 0
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
+
@@ -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
@@ -0,0 +1,11 @@
1
+ module Vips
2
+
3
+ # Various types of alignment. See {Vips::Image.join}, for example.
4
+ #
5
+ # * `:low` Align on the low coordinate edge
6
+ # * `:centre` Align on the centre
7
+ # * `:high` Align on the high coordinate edge
8
+
9
+ class Align
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ module Vips
2
+
3
+ # Various fixed 90 degree rotation angles. See {Vips::Image.rot}.
4
+ #
5
+ # * `:d0` no rotate
6
+ # * `:d90` 90 degrees clockwise
7
+ # * `:d180` 180 degrees
8
+ # * `:d270` 90 degrees anti-clockwise
9
+
10
+ class Angle
11
+ end
12
+ end
@@ -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