Author(s): Paul Brown

By using two very different tools, Kdenlive and ImageMagick, you can make animation less tedious and create some pretty cool video effects and transitions.

Below is the Custom Transitions video associated with this article.

Back in Linux Magazine issue 209 [1], I used FFmpeg and animation to create a transition from one video clip to another. In that instance, I used a Pacman animation with a transparent area and a blue, chroma area to make Pacman gobble up the first clip and lead in to the second.

Although that was fun, it required some serious and not too intuitive FFmpeg-fu to pull off. Also, placing the transition exactly where I needed it proved tricky, and it wasn't possible to know if I had done it right until I had rendered the final film.

That is why the Free Software gods have purveyed us with things like graphical video editors. Kdenlive [2] is currently my favorite, and, although I did say back in issue 209 that you couldn't use the chroma technique in Kdenlive in one go (you had to use one project to merge the first clip with the animation, render, then start a new project, and merge the rendered clip with the second clip), you can create the custom transition effect in one go using a different technique: masks.

Kdenlive Masks

Masks in Kdenlive are just images that contain transparent and non-transparent pixels that you can combine in different ways with your clips. Fire up your favorite image editor, draw a heart shape on a transparent background, save it as a PNG, and you have a heart mask (Figure 1). That's it.

Figure 1: You can create a mask with a PNG with transparent pixels.

The trick is in how you apply it in Kdenlive.

Open Kdenlive and load into the project bin (first pane on the left) the two clips you want to merge, as well as the image that will serve as a mask. By default, Kdenlive gives you three video tracks to work with. You can add more, but three is perfect for your purposes. Put your image in the topmost track, the clip you want to use as a mask on the track under that, and the clip you want to show through the hole made by your mask on the bottom-most track.

To turn your image into a mask, right-click on it on the track and choose Add transition | Composite and transform. Pull the ends of the yellow transition bar so that it covers the whole length of your static image clip. With the transition still selected, click on the Properties tab in the Effects and transitions panel (second from left, next to the project bin). You will see the properties of your transition (Figure 2).

Figure 2: Set Compositing to Xor to make the pixels in the two upper layers transparent.

One of the last options in the properties panel is the Compositing drop-down. This tells Kdenlive how you want to combine your image with the clip under it. What you want is the Xor option. The XOR operation in this context is very simple: If a pixel in the top layer (the static image that contains opaque and transparent pixels) is colored in (i.e., is opaque), it is considered a 1. The same applies to the pixels on the layer below containing the first clip. Most video clips don't have transparent pixels. If this is the case, all the pixels in all frames will be 1s. As you know from your lessons in binary logic [3], a 1 XORed with another 1 gives 0. In this transition, this means that, when an opaque pixel in the mask is overlaid onto another opaque pixel in the clip on the second track, both are rendered transparent, and the clip on the third layer will show through.

Animating

That was simple enough, but no transitioning is happening. You can make things more dynamic, because masks have keyframeable features (see the "Keyframes" box) that lets you animate them to some degree and turn your mask into a proper transition. For example, to make the second clip gradually appear in your mask and then the mask itself grow until it blots out the first clip, you can do as follows:

Keyframes You use keyframes in video editing and animation to indicate when something changes and to have your application calculate the intermediate states between the changes. Say, for example, you want a mask to go from completely invisible to completely visible. You place a keyframe on the timeline where you want the mask to be transparent and set the masks opacity to zero percent. Then you place another keyframe further down the timeline, select it, and make the mask's opacity 100 percent. Kdenlive will calculate all of the intermediate levels of opacity so that the mask will gradually fade in between the two keyframes.

1. Click on your Composite and transform transition in the timeline and make your transition about one second long.

2. Look at the properties panel above the tracks (Figure 3), and you will notice the transition has its own timeline. Make sure there's a keyframe at the beginning of the transition – a keyframe looks like a little arrow pointing upward. A keyframe at the beginning is the default, but check just in case. Click on that keyframe (it should turn red, and all the options should become available) and set the Opacity bar to zero percent. This will make your mask completely invisible.

Figure 3: How to convert a simple mask into a proper transition.

3. Move the transition's timeline cursor (the little triangle under the timeline) about 10 centiseconds in and double-click on the cursor. This will create a new keyframe at the 10-centisecond position. Now make your mask 100 percent opaque. This will make your mask fade in.

If you have trouble placing the new keyframe, that may be because the cursor is not squarely on a frame. Move the cursor a little to the left or a little to the right until you find a spot that will accept a keyframe.

Kdenlive will insert all the intermediate steps, between your two keyframes, making your mask go gradually from completely transparent and invisible, to completely opaque, showing the second clip on the bottom track.

Next, you want to make the mask grow until it completely covers the first clip and, thus, completes the transition to the second clip.

4. Place a third keyframe about five centiseconds from the end, make sure your timeline cursor is on the keyframe (the head of the arrow will be red instead of white), and change the mask's size to cover the whole frame. To do this, you can use the dimension boxes under the timeline. Changing the values in the boxes labeled X (for the width of the mask) and Y (for its height) will change your mask's size.

As the resizing happens from the upper left corner downward and to the right, your mask will probably be displaced as it grows. It might even be pushed completely outside the frame. To get it back to the center, go to the preview panel (the panel showing a preview of your project on the right), select the Project Monitor tab (Figure 4), click on the hamburger menu icon (the icon with three vertical bars to the right of the time counter), and mark the Zoom checkbox.

Figure 4: You can recenter your mask (in the red rectangle) by dragging its center over to the visible frame's center.

A new toolbar will appear in the upper left-hand corner of the preview panel (in Kdenlive's development version, this bar appears when you mouse over the upper right-hand corner of the preview panel). Use the slide at the bottom of the bar to zoom out from the visible frame. At some point, you will see a red rectangle with a red square in its center. This is the frame of your mask. The visible frame also has a square in its center, and both squares are joined by a line.

Place your cursor over the square in the center of your mask frame, click, hold, and drag the square over the visible frame's square. This will recenter your mask in the visible frame.

Also notice that you have four handles (again in the shape of red squares) in each corner of you mask's frame. You can drag on these to change the size of your mask visually.

5. For good measure, add a Dissolve transition between the first and second clip (on the middle and bottom tracks), starting at the same position as the third keyframe you placed in the Composite and transform keyframe and ending at the same ending point of the Composite and transform transition. This will ensure any leftover bits from the first clip will have disappeared completely and gracefully by the end of your custom transition. Figure 5 shows how this will look on the project timeline.

Figure 5: Add a Dissolve transition to clear up any remaining pixels from the first clip.

Cartoons

Again, this is quite straightforward. After all, you are using Kdenlive's built-in tools as they were intended. I'll mix things up a bit, because things get a little more complex when you want to make a transition with an animated mask.

The complexity comes not so much from the theory, since the principles are the same. The problem is more logistic, because now you need not just one image, but a whole sequence of PNG images. If your transition is two seconds long, that is 50 images at least. You could work on each frame by hand, one by one, but I didn't do that for the animated Pacman I used in issue 209, and I have no regrets. Instead I used ImageMagick [4].

For starters I didn't even draw the Pacman in Inkscape or anything like that. Instead, I used ImageMagick's -draw feature.

To generate each frame of the animated Pacman, you can use the commands shown in Listing 1. Line 1 draws Pacman with its mouth open. Here is a breakdown of how that line works:

Listing 1 Animating Pacman 01 convert -size 534x534 xc:none +antialias -fill none -stroke yellow -draw 'arc 0,0 534,534 225,135' -draw 'line 78,78 267,267' -draw 'line 78,456 267,267' -floodfill +269+269 yellow cc01.png 02 convert -size 534x534 xc:none +antialias -fill none -stroke yellow -draw 'arc 0,0 534,534 202,158' -draw 'line 20,164 267,267' -draw 'line 20,369 267,267' -floodfill +269+269 yellow cc02.png 03 convert -size 534x534 xc:none +antialias -fill yellow -stroke yellow -draw 'circle 267,267 0,267' cc03.png

convert is ImageMagick's jack-of-all-trades command with which you can do most operations.

is ImageMagick's jack-of-all-trades command with which you can do most operations. -size 534x534 xc:none makes an image that is 534 pixels wide by 534 pixels high and sets the background to none , which, in a PNG image, means transparent.

makes an image that is 534 pixels wide by 534 pixels high and sets the background to , which, in a PNG image, means transparent. +antialias -fill none -stroke yellow switches anti-aliasing off (you want a 1980s pixelated vibe), sets the fill to transparent (otherwise everything you draw will be filled with the default color, black), and sets the stroke (i.e., the picture's outline) to yellow.

switches anti-aliasing off (you want a 1980s pixelated vibe), sets the fill to transparent (otherwise everything you draw will be filled with the default color, black), and sets the stroke (i.e., the picture's outline) to yellow. -draw 'arc 0,0 534,534 225,135' draws Pacman's "body." The arc option draws, as its name implies, arcs of ellipses. To figure out your ellipse's shape, you have to imagine it enclosed in a rectangle (or square, if you want to draw a circular arc). The first set of coordinates ( 0,0 ) gives ImageMagick the upper left-hand corner of the rectangle surrounding the ellipse. In this case, it coincides with the upper left-hand corner of the image itself. The next set of coordinates gives ImageMagick the position of the lower right-hand corner of the rectangle. Again it coincides with the lower right-hand corner of the image. As the width and height are the same, this will be a circular arc. The last set of figures, 225,135 , draws the arc itself from 225 degrees to 135 degrees. Note that, in ImageMagick, zero degrees is on the left, 90 degrees is pointing down, 180 degrees is on the right, and 270 degrees is pointing up.

draws Pacman's "body." The option draws, as its name implies, arcs of ellipses. To figure out your ellipse's shape, you have to imagine it enclosed in a rectangle (or square, if you want to draw a circular arc). The first set of coordinates ( ) gives ImageMagick the upper left-hand corner of the rectangle surrounding the ellipse. In this case, it coincides with the upper left-hand corner of the image itself. The next set of coordinates gives ImageMagick the position of the lower right-hand corner of the rectangle. Again it coincides with the lower right-hand corner of the image. As the width and height are the same, this will be a circular arc. The last set of figures, , draws the arc itself from 225 degrees to 135 degrees. Note that, in ImageMagick, zero degrees is on the left, 90 degrees is pointing down, 180 degrees is on the right, and 270 degrees is pointing up. -draw 'line 78,78 267,267' -draw 'line 78,456 267,267' draws the straight lines that make up Pacman's "jaws." You can figure out where to start each line with a bit of trigonometry. The endpoint in both cases is, of course, the center of Pacman's circular body.

draws the straight lines that make up Pacman's "jaws." You can figure out where to start each line with a bit of trigonometry. The endpoint in both cases is, of course, the center of Pacman's circular body. -floodfill +269+269 yellow picks a spot within Pacman's body (two pixels off from his center) and floods the whole shape with yellow.

picks a spot within Pacman's body (two pixels off from his center) and floods the whole shape with yellow. Finally, the resulting image is poured into cc01.png .

Line 2 does something similar, but draws Pacman with his mouth half closed and puts the resulting image into cc02.png . Finally, line 3 draws a yellow circle, which is, of course, Pacman with his mouth completely closed (Figure 6)..

Figure 6: Use some ImageMagick-fu to create your animation frames.

Now that you have the different frames for the animation, you can create the frames for the transition. As mentioned above, if you want to make your transition last two seconds, you have to draw 50 images, putting the first frame of your animation ( cco1.png ) on the right of the frame and then, with each successive frame, move Pacman toward the left, as you cycle through each frame of the animation.

Instead of doing this by hand, you can write a Bash script (Listing 2) that uses ImageMagick instructions embedded in loops to do the repetitive work for you.

Listing 2 customtransition.sh 01 #!/bin/bash 02 03 mkdir -p transition/frames 04 mkdir transition/animation 05 06 f_w=`expr match "$2" '\(.[0-9]*\)'` 07 f_h=`expr match "$2" '.*x\(.[0-9]*\)'` 08 09 for i in $1*.png 10 do 11 convert $i -resize x$f_h transition/animation/${i##*/} 12 done 13 14 anim_frames=`ls $1|wc -l` 15 16 cc=(transition/animation/*.png) 17 color=$3 18 fs=$4 19 20 i_w=0 21 for i in $1/*.png 22 do 23 cfs=`convert $i -format "%w" info:` 24 25 if [ $cfs -gt $i_w ] 26 then 27 i_w=$cfs 28 fi 29 done 30 31 i_s=$[(($f_w+$i_w)/$fs)+1] 32 f_l_e=$[($i_s*$fs)-$f_w] 33 p_p=$[$i_s*$fs] 34 pf_w=$[($i_s*$fs)+$i_w+1] 35 36 f_c=0 37 for i in $(seq -f "%03g" 0 $fs) 38 do 39 np=$[$p_p-(10#$i*$i_s)] 40 41 convert -size ${pf_w}x${f_h} xc:none ${cc[$f_c]} -geometry +${np}+0 +antialias -composite transition/frames/frameNF.png 42 convert transition/frames/frameNF.png -floodfill +$[$pf_w-1]+1 $color transition/frames/frameUC.png 43 convert transition/frames/frameNF.png -crop ${f_w}x${f_h}+$f_l_e+0 transition/frames/frame$i.png 44 convert transition/frames/frameUC.png -crop ${f_w}x${f_h}+$f_l_e+0 transition/frames/chroma$i.png 45 46 let f_c++ 47 if [ $f_c -gt $((anim_frames-1)) ] 48 then 49 f_c=0 50 fi 51 done 52 53 rm transition/frames/frameNF.png 54 rm transition/frames/frameUC.png

The script takes four parameters:

1. The path to the directory containing the animation frames (e.g., animation/ )

2. The width and height you want for the resulting transition frames (e.g., 1280x720 )

3. Color for the chroma (e.g, "#0f0" )

4. Number of frames you want for the transition (e.g., 50 )

An example command line would look like this:

customtransition.sh animation/ 1280x720 "#0f0" 50

From lines 3 to 34, you set up directories that the animation is going to land in and the variables you will later need to create the transition's frames. It is all about calculating the ideal sizes for the animation frames, the transition frames, and the initial positions of all the moving parts. The loop that runs from lines 9 to 12, for example, resizes the frames of your animation to make sure they are exactly the height of the transition clip.

The loop that runs from lines 21 to 29 finds the width of the widest animation frame. You do this because, before creating the final transition frames, you have to fit your animation image mostly outside the frame on the right in the first few transition frames and mostly outside the frame on the left in last few. You have to prepare for that, so the proto-frames are as wide as you tell them to be, but also with double the width of the widest animation frame added to the width. Don't worry: They are cropped later (see lines 43 and 44).

The real work happens in the loop from lines 37 to 51. Here, you insert the animation frame in its correct position for each transition frame (line 41) and create a chroma frame (in case you need it) by filling the empty area to the right of the animation frame with the chroma color (line 42). Then you crop both transitory frames and give them their final place in the sequence (lines 43 and 44).

Lines 46 to 50 cycle through the animation frames.

Although the example of a static image (as shown in Figure 1) used a black mask, the mask doesn't have to be black. Remember that the only condition to successfully XOR the mask with the underlying clip is that the mask contain transparent and opaque pixels. The color of the opaque pixels is irrelevant. That means the chroma frames of the transition will work perfectly well as masks.

Once you run the script, you will end up with a folder (called transition ) that contains two subfolders, animation/ and frames/ . The animation/ subfolder contains your resized animation frames, but the frames/ subfolder contains all the frames you need to create your transition in Kdenlive.

To apply your customized transition, open the two clips that you want to use the transition on in your Kdenlive project; then, load the frame and chroma sequence of images that the customtransition.sh script built. To do that, click on the Add clip button in the project bin, navigate to the transition/frames/ folder created by customtransition.sh , select the Import image sequence checkbox at the bottom of the file explorer window, and choose the first file in the frame sequence ( frame001.png ). Then open the chroma sequence by doing the same, except now pick chroma001.png .

Both sequences will load into Kdenlive and you will be able to work with them as if they were clips.

To set up your transition in Kdenlive, you'll need four video tracks: In the topmost track, you put the animation sequence (frame). On the second track, put the mask/chroma sequence (chroma) and align it with the animation on the top track. On the third track, put the first clip you want to transition from and align the end of that clip with the end of the animation sequence. Finally, on the bottom track, add the second clip you want to transition to, and make the beginning of that clip coincide with the beginning of the animation and chroma/mask sequences.

Add a Composite and transform to the chroma/mask sequence so that it affects the first clip, and change the Compositing method to Xor as shown in Figure 8.

Figure 8: Align your clips with the animation and mask sequences to create a perfect transition.

Rendering your project will give you Pacman chomping up one scene and leading into the next.