ruby-vips8 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +1 -0
  3. data/.yardopts +10 -0
  4. data/CHANGELOG.md +5 -0
  5. data/Gemfile +15 -0
  6. data/Gemfile.lock +84 -0
  7. data/LICENSE.txt +20 -0
  8. data/README.md +170 -0
  9. data/Rakefile +45 -0
  10. data/TODO +11 -0
  11. data/VERSION +1 -0
  12. data/example/annotate.rb +17 -0
  13. data/example/daltonize8.rb +75 -0
  14. data/example/example1.rb +84 -0
  15. data/example/example2.rb +31 -0
  16. data/example/example3.rb +19 -0
  17. data/example/example4.rb +18 -0
  18. data/example/example5.rb +31 -0
  19. data/example/trim8.rb +41 -0
  20. data/example/watermark.rb +44 -0
  21. data/example/wobble.rb +36 -0
  22. data/lib/vips8.rb +153 -0
  23. data/lib/vips8/access.rb +14 -0
  24. data/lib/vips8/align.rb +11 -0
  25. data/lib/vips8/angle.rb +12 -0
  26. data/lib/vips8/angle45.rb +16 -0
  27. data/lib/vips8/argument.rb +163 -0
  28. data/lib/vips8/bandformat.rb +20 -0
  29. data/lib/vips8/call.rb +302 -0
  30. data/lib/vips8/coding.rb +14 -0
  31. data/lib/vips8/demandstyle.rb +35 -0
  32. data/lib/vips8/direction.rb +11 -0
  33. data/lib/vips8/error.rb +30 -0
  34. data/lib/vips8/extend.rb +22 -0
  35. data/lib/vips8/foreignflags.rb +20 -0
  36. data/lib/vips8/image.rb +1383 -0
  37. data/lib/vips8/interpolate.rb +37 -0
  38. data/lib/vips8/interpretation.rb +28 -0
  39. data/lib/vips8/methods.rb +1807 -0
  40. data/lib/vips8/operation.rb +19 -0
  41. data/ruby-vips8.gemspec +112 -0
  42. data/spec/image_spec.rb +515 -0
  43. data/spec/samples/balloon.v +0 -0
  44. data/spec/samples/ghost.ppm +405 -0
  45. data/spec/samples/huge.jpg +0 -0
  46. data/spec/samples/icc.jpg +0 -0
  47. data/spec/samples/lcd.icc +0 -0
  48. data/spec/samples/lion.svg +154 -0
  49. data/spec/samples/sample.csv +7 -0
  50. data/spec/samples/sample.exr +0 -0
  51. data/spec/samples/wagon.jpg +0 -0
  52. data/spec/samples/wagon.v +0 -0
  53. data/spec/spec_helper.rb +49 -0
  54. data/spec/vips_spec.rb +74 -0
  55. metadata +198 -0
@@ -0,0 +1,19 @@
1
+ module Vips
2
+
3
+ # add a conventience method to Operation
4
+ # @private
5
+ class Operation
6
+ # Fetch arg list, remove boring ones, sort into priority order.
7
+ def get_args
8
+ gobject_class = gtype.to_class
9
+ props = gobject_class.properties.select do |name|
10
+ flags = get_argument_flags name
11
+ io = ((flags & :input) | (flags & :output)) != 0
12
+ dep = (flags & :deprecated) != 0
13
+ io & (not dep)
14
+ end
15
+ args = props.map {|name| Argument.new self, name}
16
+ args.sort! {|a, b| a.priority - b.priority}
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,112 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: ruby-vips8 0.1.0 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "ruby-vips8"
9
+ s.version = "0.1.0"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["John Cupitt"]
14
+ s.date = "2016-01-25"
15
+ s.description = "ruby-vips8 is a ruby extension for vips8. It is extremely fast and it can process huge images without requiring the entire image to be loaded into memory."
16
+ s.email = "jcupitt@gmail.com"
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.md",
20
+ "TODO"
21
+ ]
22
+ s.files = [
23
+ ".rspec",
24
+ ".yardopts",
25
+ "CHANGELOG.md",
26
+ "Gemfile",
27
+ "Gemfile.lock",
28
+ "LICENSE.txt",
29
+ "README.md",
30
+ "Rakefile",
31
+ "TODO",
32
+ "VERSION",
33
+ "example/annotate.rb",
34
+ "example/daltonize8.rb",
35
+ "example/example1.rb",
36
+ "example/example2.rb",
37
+ "example/example3.rb",
38
+ "example/example4.rb",
39
+ "example/example5.rb",
40
+ "example/trim8.rb",
41
+ "example/watermark.rb",
42
+ "example/wobble.rb",
43
+ "lib/vips8.rb",
44
+ "lib/vips8/access.rb",
45
+ "lib/vips8/align.rb",
46
+ "lib/vips8/angle.rb",
47
+ "lib/vips8/angle45.rb",
48
+ "lib/vips8/argument.rb",
49
+ "lib/vips8/bandformat.rb",
50
+ "lib/vips8/call.rb",
51
+ "lib/vips8/coding.rb",
52
+ "lib/vips8/demandstyle.rb",
53
+ "lib/vips8/direction.rb",
54
+ "lib/vips8/error.rb",
55
+ "lib/vips8/extend.rb",
56
+ "lib/vips8/foreignflags.rb",
57
+ "lib/vips8/image.rb",
58
+ "lib/vips8/interpolate.rb",
59
+ "lib/vips8/interpretation.rb",
60
+ "lib/vips8/methods.rb",
61
+ "lib/vips8/operation.rb",
62
+ "ruby-vips8.gemspec",
63
+ "spec/image_spec.rb",
64
+ "spec/samples/balloon.v",
65
+ "spec/samples/ghost.ppm",
66
+ "spec/samples/huge.jpg",
67
+ "spec/samples/icc.jpg",
68
+ "spec/samples/lcd.icc",
69
+ "spec/samples/lion.svg",
70
+ "spec/samples/sample.csv",
71
+ "spec/samples/sample.exr",
72
+ "spec/samples/wagon.jpg",
73
+ "spec/samples/wagon.v",
74
+ "spec/spec_helper.rb",
75
+ "spec/vips_spec.rb"
76
+ ]
77
+ s.homepage = "http://github.com/jcupitt/ruby-vips8"
78
+ s.licenses = ["MIT"]
79
+ s.rubygems_version = "2.2.2"
80
+ s.summary = "Ruby extension for the vips8 image processing library."
81
+
82
+ if s.respond_to? :specification_version then
83
+ s.specification_version = 4
84
+
85
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
86
+ s.add_runtime_dependency(%q<gobject-introspection>, ["~> 3.0"])
87
+ s.add_development_dependency(%q<rspec>, ["~> 3.3"])
88
+ s.add_development_dependency(%q<yard>, ["~> 0.8"])
89
+ s.add_development_dependency(%q<redcarpet>, ["~> 3.3"])
90
+ s.add_development_dependency(%q<github-markup>, ["~> 1.4"])
91
+ s.add_development_dependency(%q<bundler>, ["~> 1.0"])
92
+ s.add_development_dependency(%q<jeweler>, ["~> 2.0"])
93
+ else
94
+ s.add_dependency(%q<gobject-introspection>, ["~> 3.0"])
95
+ s.add_dependency(%q<rspec>, ["~> 3.3"])
96
+ s.add_dependency(%q<yard>, ["~> 0.8"])
97
+ s.add_dependency(%q<redcarpet>, ["~> 3.3"])
98
+ s.add_dependency(%q<github-markup>, ["~> 1.4"])
99
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
100
+ s.add_dependency(%q<jeweler>, ["~> 2.0"])
101
+ end
102
+ else
103
+ s.add_dependency(%q<gobject-introspection>, ["~> 3.0"])
104
+ s.add_dependency(%q<rspec>, ["~> 3.3"])
105
+ s.add_dependency(%q<yard>, ["~> 0.8"])
106
+ s.add_dependency(%q<redcarpet>, ["~> 3.3"])
107
+ s.add_dependency(%q<github-markup>, ["~> 1.4"])
108
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
109
+ s.add_dependency(%q<jeweler>, ["~> 2.0"])
110
+ end
111
+ end
112
+
@@ -0,0 +1,515 @@
1
+ require 'spec_helper.rb'
2
+
3
+ def has_jpeg?
4
+ Vips::type_find("VipsOperation", "jpegload") != nil
5
+ end
6
+
7
+ RSpec.describe Vips::Image do
8
+ describe '#new' do
9
+ it 'can make an empty image' do
10
+ image = Vips::Image.new
11
+
12
+ expect(image.width).to eq(1)
13
+ expect(image.height).to eq(1)
14
+ expect(image.bands).to eq(1)
15
+ end
16
+
17
+ it 'can save an image to a file' do
18
+ filename = timg "x.v"
19
+
20
+ image = Vips::Image.black(16, 16) + 128
21
+ image.write_to_file filename
22
+
23
+ expect(File.exist?(filename)).to be true
24
+ end
25
+
26
+ it 'can load an image from a file' do
27
+ filename = timg "x.v"
28
+
29
+ image = Vips::Image.black(16, 16) + 128
30
+ image.write_to_file(filename)
31
+
32
+ x = Vips::Image.new_from_file filename
33
+ expect(x.width).to eq(16)
34
+ expect(x.height).to eq(16)
35
+ expect(x.bands).to eq(1)
36
+ expect(x.avg).to eq(128)
37
+ end
38
+
39
+ if has_jpeg?
40
+ it 'can save an image to a buffer' do
41
+ image = Vips::Image.black(16, 16) + 128
42
+ buffer = image.write_to_buffer ".jpg"
43
+ expect(buffer.length).to be > 100
44
+ end
45
+ end
46
+
47
+ if has_jpeg?
48
+ it 'can load an image from a buffer' do
49
+ image = Vips::Image.black(16, 16) + 128
50
+ buffer = image.write_to_buffer ".jpg"
51
+ x = Vips::Image.new_from_buffer buffer, ""
52
+ expect(x.width).to eq(16)
53
+ expect(x.height).to eq(16)
54
+ end
55
+ end
56
+
57
+ it 'can make an image from a 2d array' do
58
+ image = Vips::Image.new_from_array [[1, 2], [3, 4]]
59
+ expect(image.width).to eq(2)
60
+ expect(image.height).to eq(2)
61
+ expect(image.bands).to eq(1)
62
+ expect(image.avg).to eq(2.5)
63
+ end
64
+
65
+ it 'can make an image from a 1d array' do
66
+ image = Vips::Image.new_from_array [1, 2]
67
+ expect(image.width).to eq(2)
68
+ expect(image.height).to eq(1)
69
+ expect(image.bands).to eq(1)
70
+ expect(image.avg).to eq(1.5)
71
+ end
72
+
73
+ it 'can use array consts for image args' do
74
+ r = Vips::Image.black(16, 16)
75
+ r = r.draw_rect 255, 10, 12, 1, 1
76
+ g = Vips::Image.black(16, 16)
77
+ g = g.draw_rect 255, 10, 11, 1, 1
78
+ b = Vips::Image.black(16, 16)
79
+ b = b.draw_rect 255, 10, 10, 1, 1
80
+ im = r.bandjoin([g, b])
81
+
82
+ expect(im.width).to eq(16)
83
+ expect(im.height).to eq(16)
84
+ expect(im.bands).to eq(3)
85
+
86
+ im = im.conv [
87
+ [0.11, 0.11, 0.11],
88
+ [0.11, 0.11, 0.11],
89
+ [0.11, 0.11, 0.11]
90
+ ], :precision => :float
91
+
92
+ expect(im.width).to eq(16)
93
+ expect(im.height).to eq(16)
94
+ expect(im.bands).to eq(3)
95
+ end
96
+
97
+ it 'can set scale and offset on a convolution mask' do
98
+ image = Vips::Image.new_from_array [1, 2], 8, 2
99
+ expect(image.width).to eq(2)
100
+ expect(image.height).to eq(1)
101
+ expect(image.bands).to eq(1)
102
+ expect(image.scale).to eq(8)
103
+ expect(image.offset).to eq(2)
104
+ expect(image.avg).to eq(1.5)
105
+ end
106
+
107
+ if has_jpeg?
108
+ it 'can load a sample jpg image' do
109
+ x = Vips::Image.new_from_file simg("wagon.jpg")
110
+ expect(x.width).to eq(685)
111
+ expect(x.height).to eq(478)
112
+ expect(x.bands).to eq(3)
113
+ expect(x.avg).to be_within(0.001).of(109.789)
114
+ end
115
+ end
116
+
117
+ if has_jpeg?
118
+ it 'can extract an ICC profile from a jpg image' do
119
+ x = Vips::Image.new_from_file simg("icc.jpg")
120
+ expect(x.width).to eq(2800)
121
+ expect(x.height).to eq(2100)
122
+ expect(x.bands).to eq(3)
123
+ expect(x.avg).to be_within(0.001).of(109.189)
124
+
125
+ profile = x.get_value "icc-profile-data"
126
+ expect(profile.class).to eq(String)
127
+ expect(profile.length).to eq(2360)
128
+ end
129
+ end
130
+
131
+ if has_jpeg?
132
+ it 'can set an ICC profile on a jpg image' do
133
+ x = Vips::Image.new_from_file simg("icc.jpg")
134
+ profile = File.open(simg("lcd.icc"), "rb").read
135
+ x.set_value "icc-profile-data", profile
136
+ x.write_to_file(timg("x.jpg"))
137
+
138
+ x = Vips::Image.new_from_file timg("x.jpg")
139
+ expect(x.width).to eq(2800)
140
+ expect(x.height).to eq(2100)
141
+ expect(x.bands).to eq(3)
142
+ expect(x.avg).to be_within(0.1).of(109.189)
143
+
144
+ profile = x.get_value "icc-profile-data"
145
+ expect(profile.class).to eq(String)
146
+ expect(profile.length).to eq(3048)
147
+ end
148
+ end
149
+
150
+ if has_jpeg?
151
+ it 'can load a sample jpg image' do
152
+ x = Vips::Image.new_from_file simg("wagon.jpg")
153
+ expect(x.width).to eq(685)
154
+ expect(x.height).to eq(478)
155
+ expect(x.bands).to eq(3)
156
+ expect(x.avg).to be_within(0.001).of(109.789)
157
+ end
158
+ end
159
+
160
+ it 'has binary arithmetic operator overloads with constants' do
161
+ image = Vips::Image.black(16, 16) + 128
162
+
163
+ image += 128
164
+ image -= 128
165
+ image *= 2
166
+ image /= 2
167
+ image %= 100
168
+ image += 100
169
+ image **= 2
170
+ image **= 0.5
171
+ image <<= 1
172
+ image >>= 1
173
+ image |= 64
174
+ image &= 32
175
+ image ^= 128
176
+
177
+ expect(image.avg).to eq(128)
178
+ end
179
+
180
+ it 'has binary arithmetic operator overloads with array constants' do
181
+ image = Vips::Image.black(16, 16, :bands => 3) + 128
182
+
183
+ image += [128, 0, 0]
184
+ image -= [128, 0, 0]
185
+ image *= [2, 1, 1]
186
+ image /= [2, 1, 1]
187
+ image %= [100, 99, 98]
188
+ image += [100, 99, 98]
189
+ image **= [2, 3, 4]
190
+ image **= [1.0 / 2.0, 1.0 / 3.0, 1.0 / 4.0]
191
+ image <<= [1, 2, 3]
192
+ image >>= [1, 2, 3]
193
+ image |= [64, 128, 256]
194
+ image &= [64, 128, 256]
195
+ image ^= [64 + 128, 0, 256 + 128]
196
+
197
+ expect(image.avg).to eq(128)
198
+ end
199
+
200
+ it 'has binary arithmetic operator overloads with image args' do
201
+ image = Vips::Image.black(16, 16) + 128
202
+ x = image
203
+
204
+ x += image
205
+ x -= image
206
+ x *= image
207
+ x /= image
208
+ x %= image
209
+ x += image
210
+ x |= image
211
+ x &= image
212
+ x ^= image
213
+
214
+ expect(image.avg).to eq(128)
215
+ end
216
+
217
+ it 'has relational operator overloads with constants' do
218
+ image = Vips::Image.black(16, 16) + 128
219
+
220
+ expect((image > 128).avg).to eq(0)
221
+ expect((image >= 128).avg).to eq(255)
222
+ expect((image < 128).avg).to eq(0)
223
+ expect((image <= 128).avg).to eq(255)
224
+ expect((image == 128).avg).to eq(255)
225
+ expect((image != 128).avg).to eq(0)
226
+ end
227
+
228
+ it 'has relational operator overloads with array constants' do
229
+ image = Vips::Image.black(16, 16, :bands => 3) + [100, 128, 130]
230
+
231
+ expect((image > [100, 128, 130]).avg).to eq(0)
232
+ expect((image >= [100, 128, 130]).avg).to eq(255)
233
+ expect((image < [100, 128, 130]).avg).to eq(0)
234
+ expect((image <= [100, 128, 130]).avg).to eq(255)
235
+ expect((image == [100, 128, 130]).avg).to eq(255)
236
+ expect((image != [100, 128, 130]).avg).to eq(0)
237
+ end
238
+
239
+ it 'has relational operator overloads with image args' do
240
+ image = Vips::Image.black(16, 16) + 128
241
+
242
+ expect((image > image).avg).to eq(0)
243
+ expect((image >= image).avg).to eq(255)
244
+ expect((image < image).avg).to eq(0)
245
+ expect((image <= image).avg).to eq(255)
246
+ expect((image == image).avg).to eq(255)
247
+ expect((image != image).avg).to eq(0)
248
+ end
249
+
250
+ it 'has band extract with numeric arg' do
251
+ image = Vips::Image.black(16, 16, :bands => 3) + [100, 128, 130]
252
+ x = image[1]
253
+
254
+ expect(x.width).to eq(16)
255
+ expect(x.height).to eq(16)
256
+ expect(x.bands).to eq(1)
257
+ expect(x.avg).to eq(128)
258
+ end
259
+
260
+ it 'has band extract with range arg' do
261
+ image = Vips::Image.black(16, 16, :bands => 3) + [100, 128, 130]
262
+ x = image[1..2]
263
+
264
+ expect(x.width).to eq(16)
265
+ expect(x.height).to eq(16)
266
+ expect(x.bands).to eq(2)
267
+ expect(x.avg).to eq(129)
268
+ end
269
+
270
+ it 'has rounding members' do
271
+ # need to avoid rounding down to 0.499999
272
+ image = Vips::Image.black(16, 16) + 0.500001
273
+
274
+ expect(image.floor.avg).to eq(0)
275
+ expect(image.ceil.avg).to eq(1)
276
+ expect(image.rint.avg).to eq(1)
277
+ end
278
+
279
+ it 'has bandsplit and bandjoin' do
280
+ image = Vips::Image.black(16, 16, :bands => 3) + [100, 128, 130]
281
+
282
+ split = image.bandsplit
283
+ x = split[0].bandjoin split[1..2]
284
+
285
+ expect(x[0].avg).to eq(100)
286
+ expect(x[1].avg).to eq(128)
287
+ expect(x[2].avg).to eq(130)
288
+ end
289
+
290
+ it 'can bandjoin constants' do
291
+ image = Vips::Image.black(16, 16, :bands => 3) + [100, 128, 130]
292
+
293
+ x = image.bandjoin 255
294
+
295
+ expect(x[0].avg).to eq(100)
296
+ expect(x[1].avg).to eq(128)
297
+ expect(x[2].avg).to eq(130)
298
+ expect(x[3].avg).to eq(255)
299
+ expect(x.bands).to eq(4)
300
+
301
+ x = image.bandjoin [1, 2]
302
+
303
+ expect(x[0].avg).to eq(100)
304
+ expect(x[1].avg).to eq(128)
305
+ expect(x[2].avg).to eq(130)
306
+ expect(x[3].avg).to eq(1)
307
+ expect(x[4].avg).to eq(2)
308
+ expect(x.bands).to eq(5)
309
+
310
+ end
311
+
312
+ it 'has minpos/maxpos' do
313
+ image = Vips::Image.black(16, 16) + 128
314
+ image = image.draw_rect 255, 10, 12, 1, 1
315
+ v, x, y = image.maxpos
316
+
317
+ expect(v).to eq(255)
318
+ expect(x).to eq(10)
319
+ expect(y).to eq(12)
320
+
321
+ image = Vips::Image.black(16, 16) + 128
322
+ image = image.draw_rect 12, 10, 12, 1, 1
323
+ v, x, y = image.minpos
324
+
325
+ expect(v).to eq(12)
326
+ expect(x).to eq(10)
327
+ expect(y).to eq(12)
328
+
329
+ end
330
+
331
+ it 'can form complex images' do
332
+ r = Vips::Image.black(16, 16) + 128
333
+ i = Vips::Image.black(16, 16) + 12
334
+ cmplx = r.complexform i
335
+ re = cmplx.real
336
+ im = cmplx.imag
337
+
338
+ expect(re.avg).to eq(128)
339
+ expect(im.avg).to eq(12)
340
+ end
341
+
342
+ it 'can convert complex polar <-> rectangular' do
343
+ r = Vips::Image.black(16, 16) + 128
344
+ i = Vips::Image.black(16, 16) + 12
345
+ cmplx = r.complexform i
346
+
347
+ cmplx = cmplx.rect.polar
348
+
349
+ expect(cmplx.real.avg).to be_within(0.001).of(128)
350
+ expect(cmplx.imag.avg).to be_within(0.001).of(12)
351
+ end
352
+
353
+ it 'can take complex conjugate' do
354
+ r = Vips::Image.black(16, 16) + 128
355
+ i = Vips::Image.black(16, 16) + 12
356
+ cmplx = r.complexform i
357
+
358
+ cmplx = cmplx.conj
359
+
360
+ expect(cmplx.real.avg).to be_within(0.001).of(128)
361
+ expect(cmplx.imag.avg).to be_within(0.001).of(-12)
362
+ end
363
+
364
+ it 'has working trig functions' do
365
+ image = Vips::Image.black(16, 16) + 67
366
+
367
+ image = image.sin.cos.tan
368
+ image = image.atan.acos.asin
369
+
370
+ expect(image.avg).to be_within(0.01).of(67)
371
+ end
372
+
373
+ it 'has working log functions' do
374
+ image = Vips::Image.black(16, 16) + 67
375
+
376
+ image = image.log.exp.log10.exp10
377
+
378
+ expect(image.avg).to be_within(0.01).of(67)
379
+ end
380
+
381
+ it 'can flip' do
382
+ a = Vips::Image.black(16, 16)
383
+ a = a.draw_rect 255, 10, 12, 1, 1
384
+ b = Vips::Image.black(16, 16)
385
+ b = b.draw_rect 255, 15 - 10, 12, 1, 1
386
+
387
+ expect((a - b.fliphor).abs.max).to eq(0.0)
388
+
389
+ a = Vips::Image.black(16, 16)
390
+ a = a.draw_rect 255, 10, 15 - 12, 1, 1
391
+ b = Vips::Image.black(16, 16)
392
+ b = b.draw_rect 255, 10, 12, 1, 1
393
+
394
+ expect((a - b.flipver).abs.max).to eq(0.0)
395
+ end
396
+
397
+ it 'can getpoint' do
398
+ a = Vips::Image.black(16, 16)
399
+ a = a.draw_rect 255, 10, 12, 1, 1
400
+ b = Vips::Image.black(16, 16)
401
+ b = b.draw_rect 255, 10, 10, 1, 1
402
+ im = a.bandjoin(b)
403
+
404
+ expect(im.getpoint(10, 12)).to eq([255, 0])
405
+ expect(im.getpoint(10, 10)).to eq([0, 255])
406
+ end
407
+
408
+ it 'can median' do
409
+ a = Vips::Image.black(16, 16)
410
+ a = a.draw_rect 255, 10, 12, 1, 1
411
+ im = a.median
412
+
413
+ expect(im.max).to eq(0)
414
+ end
415
+
416
+ it 'can erode' do
417
+ a = Vips::Image.black(16, 16)
418
+ a = a.draw_rect 255, 10, 12, 1, 1
419
+ mask = Vips::Image.new_from_array [
420
+ [128, 255, 128],
421
+ [255, 255, 255],
422
+ [128, 255, 128]
423
+ ]
424
+ im = a.erode mask
425
+
426
+ expect(im.max).to eq(0)
427
+ end
428
+
429
+ it 'can dilate' do
430
+ a = Vips::Image.black(16, 16)
431
+ a = a.draw_rect 255, 10, 12, 1, 1
432
+ mask = Vips::Image.new_from_array [
433
+ [128, 255, 128],
434
+ [255, 255, 255],
435
+ [128, 255, 128]
436
+ ]
437
+ im = a.dilate mask
438
+
439
+ expect(im.getpoint(10, 12)).to eq([255])
440
+ expect(im.getpoint(11, 12)).to eq([255])
441
+ expect(im.getpoint(12, 12)).to eq([0])
442
+ end
443
+
444
+ it 'can rot' do
445
+ a = Vips::Image.black(16, 16)
446
+ a = a.draw_rect 255, 10, 12, 1, 1
447
+
448
+ im = a.rot90.rot90.rot90.rot90
449
+ expect((a - im).abs.max).to eq(0.0)
450
+
451
+ im = a.rot180.rot180
452
+ expect((a - im).abs.max).to eq(0.0)
453
+
454
+ im = a.rot270.rot270.rot270.rot270
455
+ expect((a - im).abs.max).to eq(0.0)
456
+ end
457
+
458
+ it 'can bandbool' do
459
+ a = Vips::Image.black(16, 16)
460
+ a = a.draw_rect 255, 10, 12, 1, 1
461
+ b = Vips::Image.black(16, 16)
462
+ b = b.draw_rect 255, 10, 10, 1, 1
463
+ im = a.bandjoin(b)
464
+
465
+ expect(im.bandand.getpoint(10, 12)).to eq([0])
466
+ expect(im.bandor.getpoint(10, 12)).to eq([255])
467
+ expect(im.bandeor.getpoint(10, 12)).to eq([255])
468
+ end
469
+
470
+ it 'ifthenelse with image arguments' do
471
+ image = Vips::Image.black(16, 16)
472
+ image = image.draw_rect 255, 10, 12, 1, 1
473
+ black = Vips::Image.black(16, 16)
474
+ white = Vips::Image.black(16, 16) + 255
475
+
476
+ result = image.ifthenelse black, white
477
+
478
+ v, x, y = result.minpos
479
+
480
+ expect(v).to eq(0)
481
+ expect(x).to eq(10)
482
+ expect(y).to eq(12)
483
+ end
484
+
485
+ it 'ifthenelse with constant arguments' do
486
+ image = Vips::Image.black(16, 16)
487
+ image = image.draw_rect 255, 10, 12, 1, 1
488
+
489
+ result = image.ifthenelse 0, 255
490
+
491
+ v, x, y = result.minpos
492
+
493
+ expect(v).to eq(0)
494
+ expect(x).to eq(10)
495
+ expect(y).to eq(12)
496
+ end
497
+
498
+ it 'ifthenelse with vector arguments' do
499
+ image = Vips::Image.black(16, 16)
500
+ image = image.draw_rect 255, 10, 12, 1, 1
501
+ white = Vips::Image.black(16, 16) + 255
502
+
503
+ result = image.ifthenelse [255, 0, 0], white
504
+
505
+ v, x, y = result.minpos
506
+
507
+ expect(v).to eq(0)
508
+ expect(x).to eq(10)
509
+ expect(y).to eq(12)
510
+ end
511
+
512
+ end
513
+
514
+ end
515
+