Archive for category Ruby

Accessing CoreImage transition filters from the command line

As part of MovingImages I wrote a number of command line tools that can take advantage of MovingImages. The command line tools are written in ruby and most of them come with the MovingImages ruby gem so after installing MovingImages these command line tools are installed. If you haven’t already you’ll need to download and install MovingImages.

This blog post is about the ‘dotransition’ command line tool. This tool provides access to CoreImage’s transition filters. A CoreImage transition filter takes a source and target images and provides a way of transitioning from the source image to the target image by generating a sequence of images that represents the transition between the two images.

The command line tools all take the “–help” option which describes how to call the command line tool with the various options, and they all also take the “–verbose” option which can be useful when you get an error calling the script.

In all the examples I am going to assume that the source image is an jpeg image file in your Pictures folder called “sourceimage.jpg” and that the destination image is an image file in your Pictures folder called “targetimage.jpg”. The generated images are saved in a sub folder of a folder called transition on your desktop. The first example uses the long form of the command line options as they are more descriptive but it does result in longer commands. The other examples use a mixture of long and short form demonstrating that they can be mixed. The filter specific options are only available in the long form. The ‘dotransition’ command line tool assumes that source and target images are the same size.

The bar swipe transition uses the CoreImage filter CIBarsSwipeTransition

dotransition --transitionfilter CIBarsSwipeTransition --basename image --outputdir ~/Desktop/transition/barswipe --baroffset 60 --angle 2.0 --width 20 --sourceimage ~/Pictures/sourceimage.jpg --targetimage ~/Pictures/targetimage.jpg --exportfiletype public.jpeg --count 20

I’ll cover the command line options that are common to all the transition filters first. The “–transitionfilter” option specifies the transition filter to use. To get a list of the available transition filters call the do transition command line tool like so:

dotransition -l

The ‘dotransition’ command generates a sequence of image files. These images are created in the directory specified after the –outputdir option. If the path to the directory contains a space or other non standard character then the path will need to be quoted or escaped. To generate the file names ‘dotransition’ takes a –basename option which specifies the beginning of the filename, which is then followed by the image sequence number and then the file extension for the file type of the generated image. The –sourceimage option specifies the image file that the transition starts with, and the the –targetimage option specifies the transition ends with. Like the –outputdir option if the path contains spaces or other non standard path character then the path will need to be quoted or escaped. The –exportfiletype is optional and defaults to public.tiff if not specified. The –count option specifies the number of images in the image sequence to be generated.

The bar swipe transition takes a number of filter specific properties. These are –baroffset, –angle, –width. To determine the filter properties that belong to a specific filter you can request that from the dotransition command line tool.

dotransition --filterproperties CIBarsSwipeTransition

Which outputs the information about each property. You can use the filter key value to match with the equivalent command line option.

The ripple transition filter creates a ripple effect when transitioning from one image to another. The following example assumes that the input images have a width of 2272 and a height of 1704 pixels. The ripple effect is to center itself on the image.

dotransition --transitionfilter CIRippleTransition -b image -o ~/Desktop/transition/ripple --center 1136,852 --scale=40.0 --width 50 --extent 0,0,2272,1704 -s ~/Pictures/sourceimage.jpg -d ~/Pictures/targetimage.jpg -c 20

The swipe transition replaces the source image with the destination by swiping away the source image.

dotransition --transitionfilter CISwipeTransition -b image -o ~/Desktop/transition/swipe --angle 2.0 --width 150 --color 0.3,0.2,0.8,1.0 --extent 0,0,2272,1704 --opacity 0.7 -s ~/Pictures/sourceimage.jpg -d ~/Pictures/targetimage.jpg -t public.jpeg -c 20

The copy machine transition, imitates the action of a photocopier, but replaces the source image with the target as it passes.

dotransition --transitionfilter CICopyMachineTransition -b image -o ~/Desktop/transition/copymachine --angle=-2.0 --width 100 --color 0.8,0.2,0.6,1.0 --extent 0,0,2272,1704 --opacity 0.85 -s ~/Pictures/sourceimage.jpg -d ~/Pictures/targetimage.jpg -c 30

The disintegrate with mask transition takes a mask image which it applies to the transition effect. For best results the mask image should be black and white and the same dimensions as the source and destination images.

dotransition --transitionfilter CIDisintegrateWithMaskTransition -b image -o ~/Desktop/transition/disintegratemask --maskimage ~/Pictures/maskimage.jpg --shadowradius 80 --shadowdensity 0.8 --shadowoffset 10,25 -s ~/Pictures/sourceimage.jpg -d ~/Pictures/targetimage.jpg -c 20

The flash transition filter generates a flash image over the source image which is then replaced by the target image.

dotransition --transitionfilter CIFlashTransition -b image -o ~/Desktop/transition/flash --extent 0,0,2272,1704 --color 0.0,0.2,0.8,1.0 --striationcontrast 2.0 --fadethreshold 0.8 --striationstrength 1.0 --center 1136,852 -s ~/Pictures/sourceimage.jpg -d ~/Pictures/targetimage.jpg -c 40 -t public.jpeg

The dissolve transition is the simplest of the transition filters, where the source image is gradually replaced with the target image. This example shows exporting the images as a png sequence. Exporting as png files is considerably slower than jpeg or tiff.

dotransition --transitionfilter CIDissolveTransition -b image -o ~/Desktop/transition/dissolve --exportfiletype public.png -s ~/Pictures/sourceimage.jpg -d ~/Pictures/targetimage.jpg -c 20

The mod transition filter creates oblated oval shapes that move and grow, gradually replace the source image with the target.

dotransition --transitionfilter CIModTransition -b image -o ~/Desktop/transition/mod  -s ~/Pictures/sourceimage.jpg -d ~/Pictures/targetimage.jpg -c 20 --angle 3.14159 --radius 340 --compression 300 --center 1136,852

The page curl transition filter, creates a page turning effect to go from the source to the target image.

dotransition --transitionfilter CIPageCurlTransition -b image -o ~/Desktop/transition/pagecurl  -s ~/Pictures/sourceimage.jpg -d ~/Pictures/targetimage.jpg -c 20 --angle 3.2 --radius 250 --extent 0,0,2272,1704 --backsideimage ~/Pictures/sourceimage.jpg

The page curl with shadow transition filter is very similar to the above but generates the shadow of the page being turned differently.

dotransition --transitionfilter CIPageCurlWithShadowTransition -b image -o ~/Desktop/transition/pagecurlwithshadow  -s ~/Pictures/sourceimage.jpg -d ~/Pictures/targetimage.jpg -c 20 --angle 3.2 --radius 350 --extent 0,0,2272,1704 --shadowamount 0.7 --shadowsize 250 --backsideimage ~/Pictures/sourceimage.jpg

Information about all the scripts that work with MovingImages.

And that’s it, please enjoy.

Tags: ,

Small things I like about ruby

The interactive ruby shell (irb) is really great tool to get comfortable with trying out features of ruby.

There are a couple of things that really help to make irb interactive. These come from ruby’s introspective capabilities.

The first is the method “methods” which returns a list of all the methods that relate to an object and since everything is an object in ruby you can call methods on anything:

For example what are the methods that an integer can take:

10.methods

which returns:

:to_s, :inspect, :-@, :+, :-, :*, :/, :div, :%, :modulo, :divmod, :fdiv, :**, :abs, :magnitude, :==, :===, :<=>, :>, :>=, :<, :<=, :~, :&, :|, :^, :[], :<<, :>>, :to_f, :size, :zero?, :odd?, :even?, :succ, :to_json, :integer?, :upto, :downto, :times, :next, :pred, :chr, :ord, :to_i, :to_int, :floor, :ceil, :truncate, :round, :gcd, :lcm, :gcdlcm, :numerator, :denominator, :to_r, :rationalize, :to_bn, :singleton_method_added, :coerce, :i, :+@, :eql?, :quo, :remainder, :real?, :nonzero?, :step, :to_c, :real, :imaginary, :imag, :abs2, :arg, :angle, :phase, :rectangular, :rect, :polar, :conjugate, :conj, :between?, :nil?, :=~, ...]

You can do the same on an array. For example an empty array:

[].methods

Now that is kind of useful, but as long as people have given their methods decent parameter names then you can work out how to call a method. So for example I have created a module ‘Smig’ with a method “create_imageimporter”. So if I enter the following in irb:

Smig.method(:create_imageimporter).parameters

Which returns:

[[:req, :pathToFile], [:opt, :importerName]]

This tells me that the first parameter is required and because I named the parameter pathToFile then I know I need to supply a path to a file. The second parameter is an optional parameter and is called importerName. Without reading about Smig this is probably not helpful but for me this is enough information to remind me how to call “create_imageimporter” without having to go and look up documentation elsewhere.

#Update 23 June 2014

I’ve now started using the Yard documentation tool for reference documenting of ruby code.

I’ve also been testing the use of MovingImages asynchronously but this of course means having the ability to track when asynchronous tasks are completed. A MovingImages asynchronous task can save the results of the asynchronous command to a file when it is completed. As a result I’ve installed the ruby gem ‘listen‘. Documentation for the ruby gem listen. The githug repo for listen.

Tags:

Useful Ruby links

Understanding Ruby Blocks, Procs and Lambdas

Community Ruby Style Guide

A Ruby static code analyzer, based on the community Ruby style guide.

Ruby named parameters with defaults plus Keyword arguments in Ruby

Making Ruby Gems

A guide to Ruby Gems

Ruby 2.0.0 Standard Library Documentation

Ruby 2.0 Core API

Neat things about ruby

Programming Ruby

Ruby in Twenty minutes

Ruby Constructs: Class, Module and Mixin

Opening files relative to the home directory. Some of the info here is a bit shit, but there is also some useful info. The call:

File.dirname(__FILE__)

will give you the current file’s path.

Modules as Namespaces

MovingImages CoreImage Transition Filter Example

I’ve written a number of ruby scripts that use MovingImages. One of the recent ones takes advantage of the CoreImage filter functionality that I’ve recently hooked into Moving Images. You’ll get to see this in the second alpha release which I’m pleased to say will be released soon.

The script is called exactly as shown below:

./dotransition --count 30 --sourceimage "/Users/ktam/Pictures/20140422 Pictures/DSC01625Small2.JPG" --destinationimage "/Users/ktam/Pictures/20140422 Pictures/DSC01625Small2.JPG" --basename PageCurl --outputdir "~/Desktop/deleteme/" --backsideimage "/Users/ktam/Pictures/20140422 Pictures/DSC01625SmallCropped.jpg" --angle=-3.07 --transitionfilter CIPageCurlTransition --extent 0,0,463,694 --verbose

I then used a script that you can download that works with the first alpha release of MovingImages and was called exactly as shown below:

./createanimation --delaytime 0.1 --outputfile ~/Desktop/PageTurningAnimation.gif --verbose ~/Desktop/deleteme/PageCurl*.tiff

The result of running both those scripts

Gif animation where the same page is turned over forever

The MovingImages documentation shows the output images at each step of the filter chain. Scroll down past the generated json code to see the images.

The create animation script can be viewed here.

The do transition script can be viewed here.

And an earlier demonstration using the embossmask script

Moving Images

A few ruby notes

Mostly for my own benefit, but my use of ruby is intermittent enough that the fundamentals aren’t remembered as well as they should be.

Global variables are preceded with a dollar sign. “$”.

Class variables are preceded with two at signs “@@”.

Instance variables are preceded with an at sign “@”.

This blog about ruby symbols, which can be considered as immutable strings but with added usefulness is really helpful.

This blog post describes the syntax for writing class and instance methods in ruby.

To not have to precede all method calls with the name of a module you can do include ModuleName.

 

Tags:

Ruby: Hashes containing hashes

I’ve recently noticed when using Ruby Hashes that whether they store values by reference or make a copy depends on whether the hash contains another hash.

For example:

contextWidth = 256
contextHeight = 192

contextSize = { :width => contextWidth, :height => contextHeight }
puts contextSize
puts contextSize[:width]

contextWidth = 320
puts contextSize
puts contextSize[:width]
# contextSize[:width] remains unchanged.

If I however make a hash that contains other hashes then the behaviour changes.

contextWidth = 256
contextHeight = 192
contextSize = { :width => contextWidth, :height => contextHeight }

contextLeft = 10
contextBottom = 5
contextOrigin = { :x => contextLeft, :y => contextBottom }
contextRect = { :origin => contextOrigin, :size => contextSize }

puts contextRect

contextOrigin[:x] = 20 # was 10.

puts contextRect
puts contextRect[:origin][:x]
# contextRect[:origin][:x] changes

It seems Ruby containers set objects by value when the object is a simple type, but if the object is more complex like another container then ruby sets the value by reference. This is using ruby 2.0.0p247 on OS X 10.9.

An addendum. If you want to remove key/value pair from a hash and return the original hash with the key/value removed not a new hash there is this ruby hash stack overflow discussion. The solution that looks the simplest for non ruby/rails developers is:

h = {:a => 1, :b => 2}
 => {:a=>1, :b=>2} 
h.tap { |hs| hs.delete(:a) }
 => {:b=>2} 

Tags:

Discovering ruby

Now that I’ve made the decision to go down the ruby path. A new language to learn, and how do I get it to work in the way I need it to. I’ll be calling ruby scripts from the command line so I’ll need to handle parameters but I’ll also need to call command line tools, and get back the information I need.

There is this useful blog piece describing different ways to call a command line tool, describing what each different method provides. This is my brief run through relevant to me, calling Kernel::exec doesn’t return so your ruby script doesn’t continue after the point where exec is called. Using Kernel::system to call a command line tool returns control to the ruby script after the command is completed, you can get the exit status of the command using $? see below, but you can’t capture stdout.

The Kernel#` otherwise known as backtick looks useful for my purposes. The ruby script can capture the stdout output from running the command, plus you can get the exit status in the $? object. The IO::popen and Open3::popen3 both don’t seem to provide a mechanism to obtain the exit status from running the command so they provide more flexibility for dealing with stdin, stdout and stderr I’m not sure they are going to be much use to me. So it looks like back ticks will be what I need to use. The following shows how to set the result of running the ls command to the variable file list and then output the exit status of running the ls command.

filelist = `ls -l`
puts $?.exitstatus.to_s

Update I won’t be able to use back ticks ` for most of what I want because I can’t pass a variable in as a command. There might be a way around that but I can’t find it. Further research points me towards using Open3::capture2(*cmd). For example see here:

require 'Open3'
theCommand = "smig getproperty -property idletime"
strResult, exitValue = Open3.capture2(theCommand)
puts "Exit status is: " + exitValue.exitstatus.to_s
puts "Idle time in seconds is: " + strResult

Update 2 The above is not the best approach to use capture2. Pass each part of the command as a separate parameter and you don’t need to do any fancy quoting of paths etc. So the above should be:

require 'Open3'
strResult, exitVale = Open3.capture2("smig", "getproperty", "-property", "idletime")
puts "Exit status is: " + exitValue.exitstatus.to_s
puts "Idle time in seconds is: " + strResult

I had trouble finding how to obtain the exit status information. Ruby has a $? object used above but it wraps up the exit status and other info like process id into a single object. Being a complete ruby newbie how then do I inspect $? object.

Page 3 of this ruby tutorial helped. A class object has the method “instance_methods” that lists the methods that objects of that class handles. Calling instance_methods on the $? didn’t help, it’s an instance object of the class not a class object. But the string that also lists the exit status also has other information.

#<Process::Status: pid 950 exit 0>

So I tried.

Process.instance_methods

But that didn’t work, I’m guessing Process is something like a namespace, so then I tried.

Process::Status.instance_methods

and bingo. I could obtain the exit status by doing:

$?.exitstatus

and if I want the process id I can do the following:

$?.pid

Obvious when you know what your doing but I’m only just starting to get my head around this stuff. If you don’t want the instance methods of the super classes for the class your interested in then pass false into the method call instance_methods(false).

The next part is handling command arguments passed into a ruby script. Stackoverflow has a question on this.

There are multiple ways to handle arguments passed into a a ruby script. First up the arguments are passed in as a ruby list called ARGV.

You can find out the number of items in the ARGV list:

puts "Number of arguments: " + ARGV.length.to_s

If for example you new that every item was a filename you could expand each item fully:

pathlist = []
ARGV.each do |arg|
    pathlist << File.expand_path(arg)
end

The above raises a question of what happens when a path contains white space that needs to be escaped before being passed to Open3.capture2. Experimenting shows that if you don’t need to escape anything or wrap a path in quotes etc. then you can pass in the command with arguments in one string as in the code snippet above. With paths though it is awkward to escape or quote so if the command includes a path to a file it is better to break up the call into a command and a list of arguments:

imagepath = "~/Pictures/DSC_0184 copy.JPG"
strResult, exitValue = Open3.capture2("smig", "create", "-type", "imageimporter", "-file", imagepath)
puts "Exit status is: " + exitValue.exitstatus.to_s
puts "Image importer object reference: " + strResult

As well as access to the list of arguments that ruby provides, there are some convenience libraries that make it easier to handle arguments. I’m just going to look at option parser optparse, but there is another option parser included with ruby called GetOptLong.

My notes about using optparse are cribbed from the following three sources: http://ruby.about.com/od/advancedruby/a/optionparser.htm, http://ruby.about.com/od/advancedruby/a/optionparser2.htm, and http://ruby-doc.org/stdlib-2.0.0/libdoc/optparse/rdoc/OptionParser.html

The example on the ruby-doc.org website demonstrates pretty much every feature of optparse. First up the options parser consumes the contents of ARGV but anything that the option parser doesn’t deal with is left in the ARGV list. This is useful in the situation where there are a list of parameters dealt with by the option parser but that remaining entries in the ARGV list are a list of filenames. This is  functionality I need.

OptionParser doesn’t seem to do anything if mandatory parameters are missing. I think the idea is that it is up to you to check to see if an entry is missing or not after the parameters have been parsed.

I also need to be able to deal with optional parameters. Commented example:

# Option Parser is part of ruby 2.0 standard library. But it needs to specified.
require 'optparse'

# Create an empty Hash (In Objective-C terms a dictionary)
options = {}

# Define the parser by what command line options need to be parsed with info text.
optionsParser = OptionParser.new do |opts|
# Specify the command line tools explanatory text
    opts.banner = "Usage: sample.rb [options] file1, file2, ..."

    # A verbose option. This is optional option so add a default entry to the options Hash.
    options[:verbose] = false

    # Non obvious that Options Parser knows what to do in both cases whether
    # the "--verbose" or "--no-verbose" is specified the :verbose value is correct (true,false).
    opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
        options[:verbose] = v
    end

    # A simple switch. Default is don't display.
    options[:displaywindow] = false
    opts.on("-w", "--displaywindow", "Display the window, default is don't display") do |v|
        options[:displaywindow] = true
    end

    # The on_tail method is the same as the on method except that the entry is put at the end
    # of the list when the usage help instructions is displayed. Since we are asking for help
    # it is assumed that no more processing is required and the script exits.
    opts.on_tail("-h", "--help", "Display this screen") do
        puts opts
        exit
    end

    # Optional parameter. The frame display time in seconds. The only indicator that this is
    # optional and not mandatory is that there are square brackets around TIME. The Float
    # option is clever enough that the value dt is created as a float.
    opts.on("-d", "--delaytime [TIME]", Float,
            "The time in seconds to display each frame") do |dt|
        options[:delaytime] = dt;
    end

    # Mandatory parameter. The output file. OptionsParser doesn't check for the existence
    # mandatory parameter. The indicator that this is mandatory and not optional is that
    # there are no square brackets around FILE.
    opts.on("-o", "--outputfile FILE", "The name of the file to be created") do |fn|
        options[:outputfile] = fn
    end
end.parse!

# The following will pass all the options. Filling in options, and removing entries from ARGV.
# If you have a list of filenames as well as the options then all you have left after the
# parsing the options is the list of filenames. Very useful for my purposes.
# Now we know how to do the parse. Lets do the parse.

opt_parser.parse!(ARGV)

# Check to see if the required option FILE has been specified.

if options[:outputfile].nil?
    puts "Output file hasn't been defined."
    # Then output the usage information and exit.
    puts opt_parser
    exit
end

To debug a ruby script precede how you would normally call the script with ruby -rdebug. For example:

ruby -rdebug ./createanimation.rb --delaytime 0.1 --loopcount 0 --outputfile newanimation.gif --verbose *.jpg

Google’s unofficial ruby usage guide.

Why Ruby?

I’ve come to the realisation that unix shell scripts though workable are not really the way to go with driving the MovingImages LaunchAgent and I needed an alternative scripting environment. It very quickly came down to python or ruby. I found it very difficult to choose between the two. In the end it was that learning ruby provides an easier path to ruby-motion if I choose to in the future. Amongst the ruby/python wars on the internet I found these quotes from Python versus Ruby.

Python: “There’s a most understandable way to do something and that is how it should be done”

Ruby: “Inherits perl’s philosophy of having more than one way to do the same thing”

Now I kind of like Python’s philosophy of trying to keep things simple by choosing one way of doing something, that you believe to be the most understandable way and that is what you implement. It should keep the language compact and relatively simple but I became concerned as to who decides what is the most understandable way of doing something. We don’t all think the same way.

But I also don’t like the idea of inheriting perl’s philosophy. I’ve alway felt that perl is a language used by coders who like to write code that is obtuse & hard to follow as if the coders intention is to impress by obscurity. Whilst I’ve seen this style of coding in some of the ruby code I’ve looked at, I’ve also seen that because of ruby’s flexibility it doesn’t have to be this way, that there is plenty of code written for clarity.

But if you want me to help you make this decision, I’m sorry I couldn’t do it for myself.

 

Tags: , ,