Monday, January 15, 2007

Ruby: bash image processing

As working mainly with images and image processing, sometimes I have to do one or two simple operations on many files at once like resizing, converting RGB two Gray, changing format of images, mirroring, blurring, etc. To this time I was always using Matlab to do it, because I could not find any free software on Mac X that can do such simple operations. Nonetheless, there are some issues with Matlab that annoy me, specifically: there is no native Matlab for Intel Mac X 10.4. Matlab works on Mac X 10.4 only by emulation mode, which is extremely slow and most importantly crashes very often. I had to find some more reliable solution, and I find it in Ruby.

Ruby, has very good image processing package called RMagick (interface between the Ruby programming language and the ImageMagick and GraphicsMagick image processing libraries). Installation is quite trivial. Explanation how to install RMagick on Mac X is here. I fallowed those instructions and had no problem.

#!/opt/local/bin/ruby
#convertFiles.rb
require 'rubygems'
require 'RMagick'

class ConvertFiles

def initialize inDir='inputDir/', outDir='out/'
raise 'No INPUT dir' if !File.exist? inDir
@inDir = inDir
@outDir = outDir
@files = Array.new
readFiles
createOutDir
end

def readFiles
Dir.glob(@inDir+'*.tiff').each { |l|
@files.push File.basename(l)
}
end

def createOutDir
Dir.mkdir(@outDir) if !File.exist? @outDir
end

def singleImgProcess img
return img.scale!(0.50)
end

def bashProcess
@files.each { |fn|
puts @inDir+fn
img=Magick::Image.read(@inDir+fn).first
img = singleImgProcess img
img.write(@outDir+fn)
}
end

end


Example usage is also quite simple:

c = ConvertFiles.new
c.bashProcess
Moreover, if I need some other operation or operations, I can just create new class, inheriting from the above one e.g.:


class Enlarge < ConvertFiles
def singleImgProcess img
return img.scale!(1.50)
end
end

e = Enlarge.new
e.bashProcess


Or if I want to add some text to all images, I just can do:

class AddText < ConvertFiles

def setText t
@txt = t
end

def singleImgProcess img
@txt='Default' if @txt.nil?
text = Magick::Draw.new
text.annotate(img, 0, 0, 0, 60, @txt) {
self.gravity = Magick::SouthGravity
self.pointsize = 48
}
return img
end
end


a=AddText.new
a.setText 'My pictures'
a.bashProcess

This simple code, shows how powerful and convenient Ruby can be.