Pipeline.rb is an interface for manipulating single images, sequences of images, and frames dumped from video files, according to "plans" written in an intuitive, flexible domain-specific language.
To get Pipeline.rb running, first you must have Ruby.
Second, Pipeline.rb requires both RMagick and FFMpeg.
RMagick depends on ImageMagick, which you can download or build from imagemagick.org.
If you already have ImageMagick installed, getting RMagick should be as simple as: gem install rmagick
Pipeline.rb interfaces with FFMpeg using gwik's ffmpeg-ruby gem. I don't think you can gem install
this, and it is confusing because there are multiple similarly named packages on RubyGems.
Nevertheless, if you already have FFMpeg installed, you should be able to follow gwik's instructions to install ffmpeg-ruby at https://github.com/gwik/ffmpeg-ruby.
Tip: If you're like me, and couldn't figure out how to build FFMpeg to work with ffmpeg-ruby on OS X, try: ./configure --enable-shared --disable-static
Pipeline Image Sequence Editor <andrus@uchicago.edu>
Usage: pipeline.rb [options]
Example: pipeline.rb -p plan.p -i images/
Specific options:
-i, --in-dir DIR Read input from DIR
--stdin Read input for a single image via STDIN
--in-vid PATH Read video using FFmpeg
-o, --out-dir DIR Save output to DIR
--out-vid PATH Save processed video as `filename'
-I, --in-place Overwrite input files with output
-p, --plan PLAN Process according to PLAN
--plans x,y,z Process through a sequence of plans
-h, --help Show this message
-v, --verbose Verbose output
--version Show version
Invert an entire directory of images and save the output to another directory: ./pipeline.rb -i input/ -p invert.p -o output/
Both of the following invert the inversion of an entire directory of images and save the output in-place:
./pipeline.rb -i input/ -p invert.p -p invert.p --in-place
./pipeline.rb --in-dir input/ --plans invert.p,invert.p -I
Invert every frame of a video file and dump the results to a directory: ./pipeline.rb --in-vid family.mov --plan invert.p --out-dir frames/
Both of the following process a single image via stdin:
cat gucci_mane.png | ./pipeline.rb --stdin -p invert.p >gucci_invert.png
./pipeline.rb --stdin -p invert.p <gucci_mane.png >gucci_invert.png
The syntax for Pipeline.rb's plan-files is inspired in part by the patching systems implemented in both Max/MSP and Pure Data. Moreover, the language is intended to be equally intuitive.
Plans allow for two types of commands:
- Variable assignments, and
- Function calls
Both variable assignments and function calls take arguments of the following types:
- Integer
- Float
- Predefined variables (i.e.
$1
,$alpha
, etc.) - External files (i.e.
%(masks/big_willie_style.png)
) - String (this is tentative...)
For example, a plan to swap the green and blue channels of an image, while inverting the red channel, takes the following form: splitRGB $1 invert $1 joinRGB $1 $3 $4
It is important to note that the numeric variables—$1
, $2
, etc.—are routinely overwritten by function calls within a plan. For example, had we wanted to apply ImageMagick's edge filter with a strength of 8 to an image, we would have written:
splitRGB
$red = $1
edge $3 8
joinRGB $red $2 $1
In the above example, splitRGB
saves the red channel of our input to $1
. We must store this before we call edge
on the blue channel ($2
), since the output of edge
will be stored in $1
. Finally we rejoin the channels. Note that the green channel ($2
) is unmodified.
Relying on the numbered variable system in the above examples grows cumbersome as the complexity of a plan file increases. Named variables circumvent this problem. Prior to this language feature, the following plan would have taken nearly 7 lines: $r, $g, $b = split_rgb $1 $mask = center_fit %(images/masks/big_willie_style.png) $r $r = multiply $mask $r join_rgb $r $g $b
Significantly, in the above example, only the final line modifies a numbered variable; join_rgb
overwrites $1
.
I am considering adopting a Ruby-esque syntax, wherein any function call with an exclamation mark modifies its first argument in-place. I.e., multiply! $red $mask would be the same as $red = multiply $red $mask