by Dinesh Thakur

The Java AWT provides several classes to manage loading and displaying images. The most common image code you see on the Web is called an animator. There are numerous animation applets and classes available on the WWW. The Java Developer's Kit provides a set of demo applications that draw images using static, single-buffered, and double-buffered animation.

First, we will show you the basics of drawing single images. In fact, two of the classes we developed earlier actually did everything you need to know to draw an image into a graphics context.

if (image != null) {
   g.drawlmage (image,xloc,yloc, getBackground() ,this);

This call simply draws the "image" object at (xloc,yloc) in the graphics context g. Any transparent pixels are drawn in the background color of the component, and "this" object is notified when the image is drawn. Even though this is a very standard way of drawing images, there are numerous other ways to call drawlmage.

Of course, before you can draw an image, you have to obtain one. Because Java is very biased toward supporting the WWW, the AWT provides a full-featured set of dynamic image loaders. The following code excerpt shows both local and network-based image loading.

if (inAnApplet) {
image = getlmage (getCodeBase (), "./class1312.gif ");
} else {
image = tk.getImage ("./class1312.gif");

If the image is stored locally on the machine (typical for applications) you use the default Toolkit object to load the image file. The Toolkit.getImage method receives one parameter (the filename) and begins loading the image file into a new Image object. The preceding example shows a simple GIF image file. The AWT also provides integral support for jpeg images.

If the image is to be obtained from the network, the Applet.getlmage method should be used. You pass the directory containing the image (as a URL) along with the base filename (the same GIF as before). The HTTP server on the other end of the Applet connection should process the HTTP request for the image URL just like any other WWW HTTP request. Note that there is no requirement that the HTTP server be a full-fledged WWW server, it just must support the basic operations required to pass the image. If you were developing a large distributed imaging system, you might provide a custom image server that could only serve images, or otherwise differentiate itself from a standard web server.

After starting the image load as already shown, you can proceed to other work. If the image is loaded locally by the toolkit, it will usually load immediately. If the image must be obtained from a web server, there may be a substantial (perhaps infinite!) delay before the image arrives. The AWT provides two methods for dealing with image-loading delays. We chose to use the very simple MediaTracker method.

tracker = new MediaTracker(this);

MediaTracker provides for checking the status of the image loading process for as many images as you need. The preceding example shows the case of waiting on a single image.

First, you must create a new MediaTracker instance. The MediaTracker constructor is passed an object that is normally where the image will eventually be painted. Note that this doesn't absolutely mean that the parameter is the actual graphics context or component, but it usually is. For our purposes, we'll assume that this is the case. After the MediaTracker is instantiated, you would add the images to be tracked by calling MediaTracker.addlmage () . There are two forms of addlmage; the first receives only the Image object and a unique id that you will use later as a reference ID when working with the tracker. The second form of addlmage also receives a width and height that will be used to scale the image as it loads. According to the MediaTracker class documentation, images managed with lower ID's receive some preferential treatment while loading. It's not clear how you can impact the server to deliver them any differently, but there are potential local optimizations that might be done. Note that the image doesn't begin loading the instant you call addlmage. Until you call a status or wait method, the image-loading process remains pending.

The MediaTracker can be run in it's own thread or in the main tread. If you are loading images that must completely load before you can do anything else, you might wait in the main thread. If you can do other useful work before worrying about the image, you would probably use multiple threads via the Runnable interface.
Our example uses the main thread, since we load only a single image and are willing to wait for it to finish loading.

System.out.println ("waiting") ;
try {
tracker.waitForID(0) ;
} catch (InterruptedException e) {
System.out.println("not waiting") ;

Essentially, if you call one of the MediaTracker. wait xxx methods you just block until the image loads, or something "bad" happens. Our example waits for a single image, referenced by the id we passed into addlmage. When the image finishes loading, wai tForID returns, and we can be assured that the image is ready to display. If there is an error (fairly common when the networked version of getlmage is used), the MediaTracker throws an exception, and we can try and deal with it. Depending on what your application requirements are, you might try loading the image from an alternate source or just fake something up internal to your app. One obvious alternative is to follow the HTML<IMG> tag's lead and just use drawText to render an alternate text string into an image object.

MediaTracker also provides checkAll and checkID methods that give you the capability to check on and initiate the load status of images. You can use these methods to check on the load status of important images and alter the application activity depending on what the status is. For instance, an animation program might render frames faster or slower depending on how fast the images are being received from the server. You might even decide to pause the animation or skip some frames and wait for special sync frames to arrive. This is much the way some MPEG-viewers operate.

The statusID and statusAll methods provide yet another way to begin the loading of images queued up in MediaTracker. However, their primary purpose is to give you an indication of the current status of images being tracked.

For tracking image loading where you need more precise information than MediaTracker provides, we suggest you investigate the ImageObserver interface. We personally use MediaTracker because we believe that it provides sufficient capability for normal application image loading.