next up previous
Next: Transition Effects Up: Animation and Compositing Previous: The Compositor

Composited Effects

The example code in this section, CompositedEffects.java is one of demo programs in the SDK, shows the use of a Compositor to create a composited image out of effects, sprites, and Java text. It also shows (Fig 9.8) you how to use this as a backdrop for a QuickTime movie that draws directly to the screen. You construct a composited image containing the layering of an image file, a ripple effect, an animation and some Java text. Over this, you place a movie and its movie controller, which is drawn in front of the composited image. The Compositor is used to combine multiple-image objects, including a CompositableEffect (the ripple effect), into a single image that is then blitted on screen. Both the Compositor and the QTPlayer are added as members of the top-level DirectGroup client of a QTCanvas. The code also shows you how timing hierarchies can be established when spaces are contained within each other.


The {\tt CompositedEffects.java} Program Output

The media required for this sample code include (media files are found in the media folder in the SDK Demo files):

The compositing services of the Compositor (that is, transparent drawing, alpha blending, and so on) are not available with a DirectGroup. A DirectGroup does allow for its member objects to be layered. Thus, the movie can draw in front of the Compositor unheeded. It shows the embedding of a Compositor space in a parent Compositor, and then the embedding of thisCompositor in a parent DirectGroup display space.

We create the parent Compositor that will contain the background image, ripple effect, Java text, and the spaceship compositor. The spaceship compositor is created similarly to preceding examples:

Dimension d = new Dimension (kWidth, kHeight);
QDRect r = new QDRect(d);
QDGraphics gw = new QDGraphics (r);
Compositor comp = new Compositor (gw, QDColor.green,
  new QDGraphics (r), 10, 1);

We add the background image, setting it to the same size as the Compositor. The ripple effect will ripple the pixels that this image draws:

QTFile bgFile = new QTFile(
  QTFactory.findAbsolutePath("pics/water.pct"));
GraphicsImporterDrawer if1 = new GraphicsImporterDrawer (bgFile);
if1.setDisplayBounds (r);
ImagePresenter background =
     ImagePresenter.fromGraphicsImporterDrawer (if1);
comp.addMember (background, Layerable.kBackMostLayer);

The ripple effect is layered to apply on top of the background image, and its bounds are set to only the top part of the compositor's display bounds. A ripple effect is applied only to what is behind it, not to sprites or text drawn in front of it. The QuickTime ripple effect codec works by moving pixels around on the destination QDGraphics that it is set to. By placing it in a Compositor, your application can control which part of an image it ripples -- in this case, the water picture that is be-hind it.

CompositableEffect e = new CompositableEffect ();
AtomContainer effectSample = new AtomContainer();
effectSample.insertChild (new Atom(kParentAtomIsContainer),
        kEffectWhatAtom,
        1,
        0,
  EndianOrder.flipNativeToBigEndian32(kWaterRippleCodecType));
e.setEffect (effectSample);
e.setDisplayBounds (new QDRect (0, kHeight - 100, kWidth, 100));
comp.addMember (e, 2);

We add the contained Compositor. Yellow is set as the background color, which is then not drawn, as we set the graphics mode of the Compositor to transparent with yellow as the transparent color.

We also add a Dragger so that members of this compositor can be dragged around when any modifier key is pressed when the mouse-Pressed event is generated. We also add a Dragger to the parent Compositor so that we can drag any of its top-level members when no modifier keys are pressed:

Compositor sh = new Compositor (
    new QDGraphics (new QDRect(160, 160)),
    QDColor.yellow, 8, 1);
addSprites (sh);
sh.setLocation (190, 90);
sh.setGraphicsMode (new GraphicsMode 
     (transparent, QDColor.yellow));
sh.getTimer().setRate(1);
sh.addController(new SWController 
    (new Dragger (
     MouseResponder.kAnyModifiersMask,
     MouseResponder.kAnyModifiers), true));
comp.addMember (sh, 1);
comp.addController(new SWController (
   new Dragger (MouseResponder.kNoModifiersMask), 
   true));

You use the QTImageDrawer object using the Java-drawing APIs to draw the Java text, which is then given a transparency so that only the text characters themselves are displayed by QuickTime. Note that you set the background color to white, so the Java text appears transparent. White provides a reliable transparent background for different pixel depths.

myQTCanvas.setBackground (Color.white);
\begin{verbatim}

You add the Java text in front of the background image and ripples
and set its transparency to the background color of the {\tt QTCanvas}, so that
only the text is seen.


\begin{verbatim}
QTImageDrawer qid = 
  new QTImageDrawer (jt, new Dimension (110, 22),
      Redrawable.kSingleFrame);
Paintable jt = new JavaText ();
qid.setGraphicsMode 
  (new GraphicsMode (transparent, QDColor.white));
qid.setLocation (200, 20);
comp.addMember (qid, 1);

The code here provides a good demonstration of the timing hierarchy that is built using the display spaces of the Compositor and DirectGroup. We make a DirectGroup as the top-level container space, adding both the containing Compositor as a member of this group and the movie jumps.mov. Finally, we set the rates of both the Compositor and the DirectGroup to 1 so that they are playing when the window is shown:

DirectGroup dg = 
new DirectGroup (d, QDColor.white);
dg.addMember (comp, 2);
QTFile movieFile = 
   new QTFile (
   QTFactory.findAbsolutePath ("jumps.mov"));
QTDrawable mov = QTFactory.makeDrawable (movieFile);
mov.setDisplayBounds (new QDRect(20, 20, 120, 106));
dg.addMember (mov, 1);
myQTCanvas.setClient (dg, true);
comp.getTimer().setRate(1);
dg.getTimer().setRate(1);

The top DirectGroup is the master time base for all of its members; the rate at which its time base is set (the top text box) determines the overall rate of its members. The members can have their own rates that become offset based on the rates of their parent groups. To start the program, you set the top rate to 1.


next up previous
Next: Transition Effects Up: Animation and Compositing Previous: The Compositor
Dave Marshall
10/4/2001