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/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
|
6
|
+
begin
|
7
|
+
Bundler.setup(:default, :development)
|
8
|
+
rescue Bundler::BundlerError => e
|
9
|
+
$stderr.puts e.message
|
10
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
11
|
+
exit e.status_code
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'rake'
|
15
|
+
|
16
|
+
require 'jeweler'
|
17
|
+
|
18
|
+
Jeweler::Tasks.new do |gem|
|
19
|
+
# gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
|
20
|
+
gem.name = "ruby-vips"
|
21
|
+
gem.homepage = "http://github.com/jcupitt/ruby-vips"
|
22
|
+
gem.license = "MIT"
|
23
|
+
gem.summary = %Q{Ruby extension for the vips image processing library.}
|
24
|
+
gem.description = %Q{ruby-vips is a ruby extension for vips. It is extremely fast and it can process huge images without requiring the entire image to be loaded into memory.}
|
25
|
+
gem.email = "jcupitt@gmail.com"
|
26
|
+
gem.authors = ["John Cupitt"]
|
27
|
+
# dependencies defined in Gemfile
|
28
|
+
end
|
29
|
+
Jeweler::RubygemsDotOrgTasks.new
|
30
|
+
|
31
|
+
require 'rspec/core'
|
32
|
+
require 'rspec/core/rake_task'
|
33
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
34
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
35
|
+
end
|
36
|
+
|
37
|
+
task :default => :spec
|
38
|
+
|
39
|
+
require "github/markup"
|
40
|
+
require "redcarpet"
|
41
|
+
require "yard"
|
42
|
+
require "yard/rake/yardoc_task"
|
43
|
+
|
44
|
+
YARD::Rake::YardocTask.new do |yard|
|
45
|
+
end
|
data/TODO
CHANGED
@@ -1,38 +1,14 @@
|
|
1
|
-
-
|
2
|
-
|
1
|
+
- need something like ruby-vips occasional GC stuff, we can fill memory before
|
2
|
+
a GC is triggered
|
3
3
|
|
4
|
-
-
|
4
|
+
- mail about the getpoint unimplemented error
|
5
5
|
|
6
|
-
-
|
6
|
+
http://sourceforge.net/p/ruby-gnome2/mailman/ruby-gnome2-devel-en/thread/CAGNS0RuZ5N6bha3M7B0%2BYf2M9-oni44idzZO17mtQiykS%2BmJKQ%40mail.gmail.com/#msg34790843
|
7
7
|
|
8
|
-
|
8
|
+
- still missing a few enum docs
|
9
9
|
|
10
|
+
- add complex constants, eg.
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
method is moved up to Writer and then it handles the correct to_memory method
|
14
|
-
using the image headers.
|
12
|
+
Complex(1, 2)
|
13
|
+
=> (1+2i)
|
15
14
|
|
16
|
-
add from_memory? or should the open method accept a blob in place of a path?
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
TODO
|
22
|
-
* Verify that all memory gets released when vips ops return errors. Namely,
|
23
|
-
make sure that the allocated IMAGEs get released via ruby's free callbacks.
|
24
|
-
* Allow for injecting ruby code into an image transformation pipeline (may be
|
25
|
-
slow to call out to ruby with every read, but may be worthwhile for fun custom
|
26
|
-
image processors).
|
27
|
-
* Tap into VIPS callback system to allow progress updates, etc.
|
28
|
-
* Allow for creating a ruby endpoint to the pipeline could be useful for
|
29
|
-
streaming.
|
30
|
-
* Image#to_a
|
31
|
-
* look into other.h, audit all libvips methods and make sure they are all
|
32
|
-
implemented
|
33
|
-
* JRuby support
|
34
|
-
* Optional extensions to core Ruby classes, allowing operations such as
|
35
|
-
[1, 2, 3] & im . This could be optionally enabled by requiring e.g.
|
36
|
-
vips/core_ext
|
37
|
-
* Put groups of image operations into modules, breaking docs into themes and
|
38
|
-
possibly allowing for selective loading of image ops.
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
data/example/annotate.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'vips'
|
4
|
+
|
5
|
+
im = Vips::Image.new_from_file ARGV[0], :access => :sequential
|
6
|
+
|
7
|
+
left_text = Vips::Image.text "left corner", :dpi => 300
|
8
|
+
left = left_text.embed 50, 50, im.width, 150
|
9
|
+
|
10
|
+
right_text = Vips::Image.text "right corner", :dpi => 300
|
11
|
+
right = right_text.embed im.width - right_text.width - 50, 50, im.width, 150
|
12
|
+
|
13
|
+
footer = (left | right).ifthenelse(0, [255, 0, 0], :blend => true)
|
14
|
+
|
15
|
+
im = im.insert footer, 0, im.height, :expand => true
|
16
|
+
|
17
|
+
im.write_to_file ARGV[1]
|
@@ -0,0 +1,75 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# daltonize an image with ruby-vips
|
4
|
+
# based on
|
5
|
+
# http://scien.stanford.edu/pages/labsite/2005/psych221/projects/05/ofidaner/colorblindness_project.htm
|
6
|
+
# see
|
7
|
+
# http://libvips.blogspot.co.uk/2013/05/daltonize-in-ruby-vips-carrierwave-and.html
|
8
|
+
# for a discussion of this code
|
9
|
+
|
10
|
+
require 'vips'
|
11
|
+
|
12
|
+
#Vips.set_debug true
|
13
|
+
|
14
|
+
# matrices to convert D65 XYZ to and from bradford cone space
|
15
|
+
xyz_to_brad = [
|
16
|
+
[0.8951, 0.2664, -0.1614],
|
17
|
+
[-0.7502, 1.7135, 0.0367],
|
18
|
+
[0.0389, -0.0685, 1.0296]
|
19
|
+
]
|
20
|
+
brad_to_xyz = [
|
21
|
+
[0.987, -0.147, 0.16],
|
22
|
+
[0.432, 0.5184, 0.0493],
|
23
|
+
[-0.0085, 0.04, 0.968]
|
24
|
+
]
|
25
|
+
|
26
|
+
im = Vips::Image.new_from_file ARGV[0]
|
27
|
+
|
28
|
+
# remove any alpha channel before processing
|
29
|
+
alpha = nil
|
30
|
+
if im.bands == 4
|
31
|
+
alpha = im[3]
|
32
|
+
im = im.extract_band 0, :n => 3
|
33
|
+
end
|
34
|
+
|
35
|
+
begin
|
36
|
+
# import to XYZ with lcms
|
37
|
+
# if there's no profile there, we'll fall back to the thing below
|
38
|
+
xyz = im.icc_import :embedded => true, :pcs => :xyz
|
39
|
+
rescue Vips::Error
|
40
|
+
# nope .. use the built-in converter instead
|
41
|
+
xyz = im.colourspace :xyz
|
42
|
+
end
|
43
|
+
|
44
|
+
brad = xyz.recomb xyz_to_brad
|
45
|
+
|
46
|
+
# through the Deuteranope matrix
|
47
|
+
# we need rows to sum to 1 in Bradford space --- the matrix in the original
|
48
|
+
# Python code sums to 1.742
|
49
|
+
deut = brad.recomb [
|
50
|
+
[1, 0, 0],
|
51
|
+
[0.7, 0, 0.3],
|
52
|
+
[0, 0, 1]
|
53
|
+
]
|
54
|
+
|
55
|
+
xyz = deut.recomb brad_to_xyz
|
56
|
+
|
57
|
+
# .. and back to sRGB
|
58
|
+
rgb = xyz.colourspace :srgb
|
59
|
+
|
60
|
+
# so this is the colour error
|
61
|
+
err = im - rgb
|
62
|
+
|
63
|
+
# add the error back to other channels to make a compensated image
|
64
|
+
im = im + err.recomb([
|
65
|
+
[0, 0, 0],
|
66
|
+
[0.7, 1, 0],
|
67
|
+
[0.7, 0, 1]
|
68
|
+
])
|
69
|
+
|
70
|
+
# reattach any alpha we saved above
|
71
|
+
if alpha
|
72
|
+
im = im.bandjoin(alpha)
|
73
|
+
end
|
74
|
+
|
75
|
+
im.write_to_file ARGV[1]
|
data/example/example1.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'vips'
|
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 'vips'
|
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 'vips'
|
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 'vips'
|
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 'vips'
|
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-vips ... 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 'vips'
|
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 'vips'
|
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]
|