Hack 8 Video Color Effects

figs/moderate.gif figs/hack8.gif

Simulate a video transition using Flash color effects.

This hack alters video using the Color class to create a unique type of color transition. This is not an obvious technique and not one ordinarily applied to video transitions, but that's the whole point of a hack?to explore the nonobvious.

The Boy Can't Dance

You can always tell when videographers have to create a pop music video with a singer who can't move to the beat in a hip sort of way. In such a case, the videographer moves the camera or adds lots of video transitions and effects that are in sync with the music. That way, you get onscreen movement in time with the beat even if the band is standing hopelessly still and nodding their heads in a 70s prog-rock kinda way.

Flash video poses a similar challenge: video is bandwidth-heavy, and to keep compression ratios as high as possible, we have to create sequences in which not much changes between frames. Most codecs, including the Sorenson codec that Flash uses, perform both spatial and temporal compression. Spatial compression is performed by looking for similarities within the frame (for example, a solid colored background compresses very easily). Temporal compression is achieved by looking at consecutive frames and including only deltas (differences) between the frames. It therefore makes sense to reduce large-scale movement in our videos, allowing the difference frames, which contain only the deltas between frames, to be as bandwidth-light as possible. (For want of a better analogy, difference frames are akin to the tween frames used in animation within Flash's timeline. Video, like animation, has keyframes as well.) Video keyframes are used to maintain image quality and to handle situations in which the differences between frames are so large as to make difference frames inefficient. Therefore, more changes per frame requires either larger difference frames or more keyframes.

This leaves us stuck in the same situation as the pop music video; we can't have too much big movement in our visuals without a massive increase in the download size of the video.

The trick, as in pop music videos, is to add movement or effects somewhere else. We apply the effects programmatically at runtime (on the client side) so you don't affect the video compression (i.e., the bandwidth required) by adding big interframe discontinuities.

The key to saving bandwidth without boring the viewer is to programmatically introduce variations that don't exist in the source video.


For example, you can also use runtime video effects to hide the fact that your video is looping, another popular way of conserving bandwidth. You can also make the video effects user-controllable, thus adding variation by making it an interactive element instead of a linear video.

Color Coding

You have probably applied colors to movie clips using the Advanced Effect dialog box shown in Figure 2-1. If you've never used color effects before, you can set up a color tween as follows:

  1. Draw a black circle on stage in frame 1 and convert it to a movie clip symbol (F8).

  2. Insert a keyframe in frame 10 by selecting frame 10 in the main timeline and choosing InsertTimelineKeyframe.

  3. Click on the keyframe in frame 1, and apply a motion tween to the movie clip instance by setting the Tween option in the Properties panel to Motion.

  4. Click on the keyframe in frame 10. Then use the Selection tool to click on the Stage to deselect the frame. Finally, click on the movie clip instance on stage to select it.

  5. Set the Color option in the Properties panel to Advanced.

  6. Click the Settings button in the Properties panel to open the Advanced Effect dialog box, and set the rb value, as indicated in Figure 2-1, to 200. Click OK to close the dialog box.

Figure 2-1. The Advanced Effect dialog box is used for applying color transformations
figs/flhk_0201.gif


If you scrub the playhead across the first 10 frames of the timeline, you should see the movie clip change slowly from black to red, effectively creating a color transition. (If you didn't apply the motion tween properly, the clip remains black until frame 9 and then suddenly turns red in frame 10.)

So far, so good. But how do you apply the color transition to a video at runtime? You can use the Color class to apply a similar transform to any movie clip, including a movie clip containing a video. The Color.setTransform( ) method accepts one argument, a transform object with properties ra, ga, ba, aa, rb, gb, bb, and ab. So now you're thinking, "Whuh?"

A transform object (a.k.a. transObject) is just an instance of the Object class that contains properties used to perform the color transformation. The eight properties simply correspond to the values of the eight fields in the Advance Effect dialog box, as shown in Figure 2-1. To get a feel for what the properties do, play around with the Advanced Effect values manually.

Manually applying advanced color effects to a bitmap photograph image embedded inside a movie clip will give you the best indication of what can be done with color and a video instance. Experiment with one or more still images captured from the video for best results.

Color Video Transforms

This hack creates one typical transform type: an instantaneous effect, such as going quickly from normal color film to the photographic negative for a few frames, before returning back to normal. This looks really cool if you also sync sound to the same effect [Hack #59] . This technique can be extended to create another typical effect: fades and other gradual transitions [Hack #9].

Let's look at instantaneous effects first. Figure 2-2 shows the original image and Figure 2-3 and Figure 2-4 show two possible effects.

Figure 2-2 shows the original image, with a neutral transform of:

Figure 2-2. Original image (neutral transform)
figs/flhk_0202.gif


{ra:100, rb:0, ga:100, gb:0, ba:100, bb:0, aa:100, ab:0}

Figure 2-3 shows the inverted image, with a transform of:

{ra:-100, rb:255, ga:-100, gb:255, ba:-100, bb:255, aa:100, ab:0}

Figure 2-3. Inverse image
figs/flhk_0203.gif


You are not limited to the negative effect, though. Scripted transforms allow you to overdrive further than the UI will take you via the Advanced Effect dialog box. Figure 2-4 shows a high-contrast transform:

{ra:500, rb:-500, ga:500, gb:-500, ba:500, bb:-500, aa:100, ab:0}

Figure 2-4. High-contrast image
figs/flhk_0204.gif


You can create lots of other effects, such as the "washout effect" in which the image appears overexposed, using the following transform to lighten the image:

{ra:100, rb:150, ga:100, gb:150, ba:100, bb:150, aa:100, ab:0}

You can boost the red tones with a transform of:

{ra:500, rb:-500, ga:100, gb:0, ba:100, bb:0, aa:100, ab:0}

You can darken an image with a transform of:

{ra:100, rb:-150, ga:100, gb:-150, ba:100, bb:-150, aa:100, ab:0}

For full appreciation of the effects, see the sample images or colortransforms.fla file downloadable from this book's web site.

The following code applies an instantaneous color spot transform to any content inside a movie clip:

function negativeFlick(targetClip, duration) {

  this.neutralizer = function( ) {

    negColor.setTransform(neutral);

    // Refresh the screen

    updateAfterEvent( );

    // Clear the interval

    clearInterval(negInterval);

  };

  // Define a transform that reverses the current colors

  var negTrans = {ra:-100, rb:255, ga:-100, gb:255,

                  ba:-100, bb:255, aa:100,  ab:0};

  // Define and apply a neutral transform to cancel the effect

  var neutral = {ra:100, rb:0, ga:100, gb:0, ba:100, bb:0, aa:100, ab:0};

  // Target the specified clip and apply the transform

  var negColor = new Color(targetClip);

  negColor.setTransform(negTrans);

  // Set up a callback to reverse the effect some time later

  var negInterval = setInterval(this.neutralizer, duration);

}

Here we invoke the effect for one second on a clip named bitmapClip, which presumably is a clip we've created that contains a bitmap (make sure you give the clip an instance name of bitmapClip using the Properties panel):

negativeFlick(bitmapClip, 1000);

To apply the effect to a video, call negativeFlick( ) with the name of the clip containing the video. Here is an example in which the effect is applied to a clip named myVideo_mc for two seconds (2000 milliseconds). Again, you should set the instance name of the clip, which presumably contains a video, using the Properties panel:

negativeFlick(myVideo_mc, 2000);

Typically, the script that defines the negativeFlick( ) function and the call that invokes it are attached to a separate actions layer.

To invoke negativeFlick( ) from the timeline of the myVideo_mc video clip, you would use:

negativeFlick(this, 2000);

The negativeFlick( ) function creates a Color instance and uses it to apply our transformation to the target clip. The last line of negativeFlick( ) also sets up an interval (i.e., a timer using setInterval( )) that invokes neutralizer( ). The neutralizer( ) function negates our transformation by applying a neutral transform. The code clears the interval to prevent it from repeating, as it would periodically if we failed to clear it.

Note that setInterval( ) is not tied directly to the frame rate, so the callback function, in this case neutralizer( ), will typically execute before other frame-based events (such as onEnterFrame). When using setInterval( ) to produce graphic effects, the usefulness of having a non-frame-based event is lost if you have to wait for the next frame before you see the animated effect it creates. Therefore, the call to updateAfterEvent( ) addresses the issue by forcing a screen refresh at the end of the callback function.

So, in this hack, we've seen several keys to applying color transforms to video:

  • Use a color transform object to transform the video's color.

  • Use an interval and a callback function to make the change temporary.

  • Use a neutral color transform to restore the original colors.

These techniques aren't limited to videos. You can target any movie clip or even the main timeline. Furthermore, you need not reset the color scheme using a neutral transform. You could apply a random color transform periodically, for example. In that case, you would want to randomize the values of the color transform object's properties (instead of using a neutral transform in the callback function), and you wouldn't want to clear the interval in the callback function. See the ActionScript Cookbook by Joey Lott (O'Reilly) for more examples of using color transformations and generating random numbers.