A Weird Imagination

Blend effect slideshow using shell

Posted in

The goal

Given a series of images, present them in a video with a blend effect between the images. The frames between the input frames should gradually transition between the previous and next image. This, and other transition effects, could likely be implemented using a slideshow generator, but it can also be done quite easily using a shell script.

The script

The final script I wrote is blend.sh. The following commands fetch and run it:

$ wget https://gist.githubusercontent.com/dperelman/2b4b86233aa13d13c0ab/raw/91c7988e27288af8aeb25ade11d0cab90355702f/blend.sh
$ chmod +x blend.sh
$ ./blend.sh slideshow.mkv first.png second.jpg third.gif
$ mplayer slideshow.mkv

The input images may be in any format. The extension of slideshow.mkv will be used by FFmpeg to guess the desired video format (H.264 in a Matroska Multimedia Container for .mkv).

The details

FFmpeg

To encode a video from the command line, the relevant tools are FFmpeg and MEncoder. I choose FFmpeg because I generally find it easier to use, but I tend to switch between the two when one isn't doing what I want.

We reduce the problem of generating a video to one of generating the frames for that video using the FFmpeg input mode image2, which takes in a sequence of images as the frames for a video.

ImageMagick

To generate the frames, we will use the ImageMagick family of tools, which are a set of command-line tools that will do pretty much any image manipulation task you can imagine. The primary downside of ImageMagick is that it does so much, it sometimes takes a bit of reading through the documentation to figure out the right settings for a simple task.

The basic ImageMagick command is convert. In the script, it is used to convert the input image from any format ImageMagick supports to a PNG (the frames are stored as PNG because it uses lossless compression):

convert "$image" "$dir/image${num}.png"

Blending

ImageMagick's composite command with the -blend option is used to make the intermediate frames. See the examples section of the ImageMagick documentation for how to use -blend.

The code for performing the blend is1

# Use bc for math to get decimals.
percent="$(echo "$fade_amount/$frames_per_image*100" \
    | bc -lq)"
composite -blend "$percent" "$image" "$prev" \
    "$dir/image$num"".png"

The computation of $percent is done with bc in order to get decimals:

$ fade_amount=7
$ frames_per_image=30
$ echo "$fade_amount/$frames_per_image*100"
7/30*100
$ echo $((fade_amount/frames_per_image*100))
0
$ echo $((100*fade_amount/frames_per_image))
23
$ echo "100*$fade_amount/$frames_per_image" | bc
23
$ echo "$fade_amount/$frames_per_image*100" | bc -l
23.33333333333333333300

Cleaning up

The script make a temporary directory using mktemp -d and deletes it using rm -rf when it is done. This means the script writes the frames it generates to a directory in /tmp, so if using this to create a video for many images, make sure you have enough space in /tmp for the frames or use the -p option of mktemp to place the temporary directory somewhere there is enough space. The frames will take approximately $frames_per_image (default=30) times as much space as the input images.


  1. Actually, this is all on one line in the script, but it's easier to read this way. 

Comments

Have something to add? Post a comment by sending an email to comments@aweirdimagination.net. You may use Markdown for formatting.

There are no comments yet.