next up previous
Next: Using the QTImageDrawer Class Up: QuickTime for Java Previous: Quicktime to Java Imaging

Image Producing

The code in this section shows how to display any QuickTime drawing object using Java's ImageProducer model.

The program works with the QTImageProducer and with Swing components. The QTImageProducer in this case is responsible for getting the QuickTime movie and producing the pixels for a
java.awt.Image. It draws the movie into its own QDGraphics world and then feeds the pixels to any java.image.ImageConsumer objects that are registered with it in a format that they are able to deal with. The Swing buttons control the movie playback.

The Swing JComponent is the ImageConsumer of the QTImageProducer. It will automatically repaint itself if the QTImageProducer source is multiframed media, such as a movie. This is a feature of the ImageProducer model of the Java API.

Placing a QuickTime movie within a Swing JComponent requires the usage of Java's image producing API. Swing is a framework that uses lightweight components. As such, a heavyweight component, such as a QTCanvas, is generally not added to the lightweight components. To put QuickTime content into a lightweight component java.awt.Image is used to capture the pixel data generated by QuickTime. As the previous example showed, the Java image producing API is used, with the QTImageProducer implementing the ImageProducer interface used for this purpose.

We open the movie and set looping of its time base. We make a MoviePlayer out of the Movie to pass to the QTImageProducer, which takes any QTDrawable object as a source of pixel data. We pass in the original size of the movie to the QTImageProducer, which will notify the producer how big a QDGraphics it should create.

Once the QTImageProducer is made, we need to redraw it when each frame of the movie is drawn. To optimize this process, we install a MovieDrawingComplete callback. This callback notifies us when the movie draws a complete frame, and in the execute() method we redraw the QTImageProducer. The QTImageProducer redraw() method will pass on the changed pixel data to the registered ImageConsumer objects. The ImageConsumer is registered with the QTImageProducer when we create the IPJComponent, as shown in the code below.

OpenMovieFile openMovieFile = OpenMovieFile.asRead(movFile);
Movie m = Movie.fromFile (openMovieFile);
m.getTimeBase().setFlags (loopTimeBase);
MoviePlayer moviePlayer = new MoviePlayer (m);
QDRect r = moviePlayer.getDisplayBounds();
Dimension d = new Dimension (r.getWidth(), r.getHeight());
ip = new QTImageProducer (moviePlayer, d);

//this tells us that the movie has redrawn and
//we use this to redraw the QTImageProducer - which will
//supply more pixel data to its registered consumers

m.setDrawingCompleteProc (movieDrawingCallWhenChanged, this);
IPJComponent canv = new IPJComponent (d, ip);
pan.add("Center", canv);

The following is the execute() method of the MovieDrawingComplete interface. This execute() method is invoked whenever the movie draws. We use the updateConsumers() method of the QTImageProducer as the movie has already drawn when this callback is executed, so we only need to notify the image consumers and give them the new pixel data. If the movie hadn't drawn, then the QTImageProducer redraw() method would be called. This both redraws the QTDrawable source and updates the image consumers' pixel data:

public int execute (Movie m) {
try {
  ip.updateConsumers (null);
    } catch (QTException e) {

return e.errorCode();
}
return 0;
}

The following shows the construction of the IPJComponent. This JComponent is a Swing component and its paint() method will draw the image that is the consumer of the QTImageProducer. The constructor creates a java.awt.Image, the createImage() method establishing the QTImageProducer as the producer of pixel data for this Image. The prepareImage() call establishes the IPJComponent as the ImageObserver of this process. The paint() method uses the supplied java.awt.Graphic drawImage() call to draw the Image, also passing the IPJComponent as the ImageObserver. Each time the QTImageProducer is redrawn, it notifies its image consumers that it has more pixel data. This will, in turn, notify the ImageObserver, which is the IPJComponent, that it should repaint itself. The paint() method is consequently called and drawImage() will draw the new pixel data to the screen.

static class IPJComponent extends JComponent {
IPJComponent (Dimension prefSize, QTImageProducer ip) {
pSize = prefSize;
im = createImage (ip);
prepareImage (im, this);
}
private Dimension pSize;
private Image im;
public Dimension getPreferredSize() {
return pSize;
}
public void paint (Graphics g) {
g.drawImage (im, 0, 0, pSize.width, pSize.height, this);
}
// stops flicker as we have no background color to erase
public void update (Graphics g) {
paint (g);
}
}


next up previous
Next: Using the QTImageDrawer Class Up: QuickTime for Java Previous: Quicktime to Java Imaging
Dave Marshall
10/4/2001