Chapter 27

Images and Sounds


CONTENTS

If you've seen a lot of the applets that are floating around, you've undoubtedly noticed that many of them feature vivid graphics and even sound effects. When programming in a language such a C++, displaying graphics and playing sounds can be infamously difficult, thanks to the fact that these languages provide no direct support for handling these types of files. Even the Windows API, as immense as it is, provides little help when it comes to handling these graphical and aural chores. Java, on the other hand, was designed to make creating applets as easy as possible. For that reason, Java's classes handle almost all the difficulties associated with displaying images (commonly called bitmaps) and playing sounds. In this chapter, you use Java's power to add images and sounds to your applets.

Image Types

In the world of computers, there are many types of images, each of which is associated with a specific file format. These image types are usually identified by their file extensions, which include PCX, BMP, GIF, JPEG (or JPG), TIFF (or TIF), TGA, and more. Each of these file types was created by third-party software companies for use with their products, but many became popular enough to grow into standards. The PCX graphics file type, for example, began as the format for PC Paintbrush files, whereas BMP files are usually associated with the Windows graphical interface.

If you were writing your Internet applications using a more conventional language like C++, you could choose to support whatever image type was most convenient for your use. This is because you'd have to write all the file-loading code from scratch, anyway. Java, on the other hand, comes complete with classes that are capable of loading image files for you. This convenience comes with a small price, however, since Java can load only GIF and JPEG image file formats. In this book, you'll use GIF files, which are more common, although JPEG files are rapidly gaining a reputation, especially for high-resolution, true-color images.

Loading and Displaying an Image

The first step in displaying an image in your applet is to load the image from disk. To do this, you must create an object of Java's Image class. This is fairly easy to do; however, in order to do so, you need to create an URL object that holds the location of the graphics file. You could just type the image's URL directly into your Java source code. If you do this, however, you have to change and recompile the applet whenever you move the graphics file to a different directory on your disk. A better way to create the image's URL object is to call either the getDocumentBase() or getCodeBase() method. The former returns the URL of the directory from which the current HTML file was loaded, whereas the latter returns the URL of the directory from which the applet was run.

Example: Using the getDocumentBase() Method

As I said previously, the getDocumentBase() method returns the URL of the directory from which the HTML document was loaded. If you're storing your images in the same directory (or a subdirectory of that directory) as your HTML files, you'd want to use this method to obtain an URL for an image.

Suppose you have your HTML documents in a directory called PUBLIC and the image you want, called IMAGE.gif, is stored in a subdirectory of PUBLIC called IMAGES. A call to getDocumentBase() will get you the appropriate base URL. That call looks like this:


URL url = getDocumentBase();

As you'll soon see, once you have the URL, you can load the file by using the URL along with the relative location of the image, which in this case would be IMAGES/IMAGE.gif. The full URL to the file would then be FILE:/C:/PUBLIC/IMAGES/IMAGE.gif. If you decided to move your public files to a directory called MYHOMEPAGE, the call to getDocumentBase() will give you the URL for that new directory, without your having to change the applet's source code. This new URL, once you included the relative location of the image file, would be FILE:/C:/MYHOMEPAGE/IMAGES/IMAGE.gif.

Example: Using the getCodeBase() Method

The getCodeBase() method works similarly to getDocumentBase(), except that it returns the URL of the directory from which the applet was loaded. If you're storing your images in the same directory (or a subdirectory of that directory) as your CLASS files, you'd want to call getCodeBase() to obtain an URL for an image.

Suppose you have your CLASS files in a directory called CLASSES and the image you want (still called IMAGE.gif) is stored in a subdirectory of CLASSES called IMAGES. A call to getCodeBase() will get you the base URL you need to load the image. That call looks like this:


URL url = getCodeBase();

Again, once you have the URL, you can load the file by using the URL along with the relative location of the image, which would still be IMAGES/IMAGE.gif. The full URL to the file would then be FILE:/C:/CLASSES/IMAGES/IMAGE.gif.

Loading an Image

Once you have the image's base URL, you're ready to load the image and create the Image object. You can complete both of these tasks at the same time, by calling your applet's getImage() method, like this:


Image image = getImage(baseURL, relLocation);

The getImage() method's two arguments are the URL returned by your call to getCodeBase() or getDocumentBase() and the relative location of the image. For example, assuming that you've stored your CLASS files in the directory C:\CLASSES and your images in the directory C:\CLASSES\IMAGES, you'd have a code that looks something like this:


URL codeBase = getCodeBase();

Image myImage = getImage(codeBase, "images/myimage.gif");

After Java has executed the above lines, your image is loaded into the computer's memory and ready to display.

Displaying an Image

Displaying the image is a simple matter of calling the Graphics object's drawImage() method, like this:


g.drawImage(myImage, x, y, width, height, this);

This method's arguments are the image object to display, the X and Y coordinates at which to display the image, the width and height of the image, and the applet's this reference.

TIP
When you want to display an image with its normal width and height, you can call a simpler version of the drawImage() method, which leaves out the width and height arguments, like this: drawImage(image, x, y, this). This version of the method actually draws the image faster because it doesn't have to worry about reducing or expanding the image to the given width and height. It just blasts it on to the screen exactly as the image normally appears.

You may be wondering where you can get the width and the height of the image. As it turns out (no doubt thanks to careful consideration by Java's programmers over hundreds of cups of coffee), the Image class has two methods, getWidth() and getHeight(), that return the width and height of the image. The complete code for displaying the image, then, might look like this:


int width = image.getWidth(this);

int height = image.getHeight(this);

g.drawImage(image, x, y, width, height, this);

As you can see, the getWidth() and getHeight() methods require a single argument, which is the applet's this reference.

Example: Displaying an Image in an Applet

You're now ready to write an applet that can display images. Listing 27.1 is the Java source code for an applet called ImageApplet that displays a small image using the techniques described previously in this chapter. When you run the applet with Appletviewer, you see the window shown in Figure 27.1. Make sure the SNAKE.gif image is in the same directory as the ImageApplet.class file, since that's where the program expects to find it.

Figure 27.1 : This is ImageApplet running under Appletviewer.


Listing 27.1  ImageApplet.java: An Applet That Displays an Image.

import java.awt.*;

import java.applet.*;

import java.net.*;



public class ImageApplet extends Applet

{

    Image snake;



    public void init()

    {

        URL codeBase = getCodeBase();

        snake = getImage(codeBase, "snake.gif");

        resize(250, 250);

    }



    

public void paint(Graphics g)

    {

        int width = snake.getWidth(this);

        int height = snake.getHeight(this);



        g.drawRect(52, 52, width+10, height+10);

        g.drawImage(snake, 57, 57, width, height, this);

    }

}


Tell Java that the applet uses the classes in the awt package.
Tell Java that the applet uses the classes in the applet package.
Tell Java that the applet uses the classes in the net package.
Derive the ImageApplet class from Java's Applet class.
Declare the class's image data field.
Override the init() method.
Retrieve the base URL.
Load the image.
Size the applet.
Override the paint() method.
Get the image's width and height.
Draw a framing rectangle for the image.
Draw the image within the rectangle.

Notice how the applet imports the classes in the net package, which is where the URL class lives. If you fail to include this line at the top of the program, Java will be unable to find the URL class and the applet will not compile.

TIP
By using different values for the drawImage() method's width and height arguments, you can display an image at any size you like. For example, to display an image at twice its normal size, just use 2*width and 2*height for the width and height arguments. To display the image at half its normal size, use width/2 and height/2. Figure 27.2 shows the snake image displayed at twice its normal size. It doesn't even fit in the window any more!

Figure 27.2 : Here's the snake image at twice its size.

Playing a Sound

Just as there are many types of image files, so too are there many types of sound files. But, when it comes to applets, the only type of sound file you need to know about are audio files, which have the file extension AU. These types of sound files were popularized on UNIX machines and are the only type of sound file Java can load and play.

When you want to play a sound from beginning to end, you only have to call getDocumentBase() or getCodeBase() for the URL and then call play() to play the sound. A call to play() looks like this:


play(baseURL, relLocation);

The play() method's two arguments are the URL returned from a call to getDocumentBase() or getCodeBase() and the relative location of the sound file.

Example: Using the play() Method

Suppose you have your CLASS files in the directory C:/MYHOMEPAGE and your AU files in the directory C:/MYHOMEPAGE/AUDIO. The following lines then will load and play an audio file called SOUND.AU:


URL codeBase = getCodeBase();

play(codeBase, "audio/sound.au");

Example: Playing a Sound in an Applet

Now get ready to write an applet that plays a sound file. Listing 27.2 is the applet in question, called SoundApplet. When you run the applet with Appletviewer, you'll see the window shown in Figure 27.3. Just click the button to hear the sound. Of course, you need to have a sound card properly installed on your system. You also must be sure that the SPACEMUSIC.AU sound file is in the same directory as the applet. (This sound file is included with the Java Developer's Kit and has been copied to this chapter's CD-ROM directory for your convenience.)

Figure 27.3 : Click the button to hear the applet's sound file.


Listing 27.2  SoundApplet.java: An Applet That Plays a Sound File.

import java.awt.*;

import java.applet.*;

import java.net.*;



public class SoundApplet extends Applet

{

    Button button;



    public void init()

    {

        BorderLayout layout = new BorderLayout();

        setLayout(layout);



        Font font = new Font("TimesRoman", Font.BOLD, 32);

        setFont(font);



        button = new Button("Play Sound");

        add("Center", button);



        resize(250, 250);

    }



    public boolean action(Event evt, Object arg)

    {

        if (evt.target instanceof Button)

        {

            URL codeBase = getCodeBase();

            play(codeBase, "spacemusic.au");

        }



        return true;

    }

}


Tell Java that the applet uses the classes in the awt package.
Tell Java that the applet uses the classes in the applet package.
Tell Java that the applet uses the classes in the net package.
Derive the SoundApplet class from Java's Applet class.
Declare the class's button object.
Override the init() method.
Create and set the applet's layout.
Create and set the applet's font.
Create and add the button.
Size the applet.
Override the action() method.
If the user clicks the button...
Get the base URL.
Play the sound.
Tell Java that the event was handled.

Controlling Sounds

Although the applet's play() method is the easiest way to load and play sounds, it doesn't give you much control. You have only one option: play the sound from beginning to end. If you want a little more control over your sounds, you can create an AudioClip object and use the object's methods to control the sound. Unfortunately, even the AudioClip class doesn't give you much power, although you can play, stop, and loop the sound.

To create the AudioClip object, you call the getAudioClip() method, like this:


AudioClip audioClip = getAudioClip(baseURL, relLocation);

This method's two arguments are the sound file's base URL and relative location.

Once you have the AudioClip object created and loaded, you can call its methods to control the sound. There are only three from which to choose: play(), stop(), and loop(). The play() method plays the sound once from beginning to end, stop() stops the sound whether or not it has finished playing, and loop() causes the sound to keep repeating until it's stopped.

Example: Using an AudioClip in an Applet

Although using audio clips is a little more complicated than simply loading and playing a sound using the applet's play() method, it's still a straightforward process. Listing 27.3 is an applet that creates an AudioClip object and enables the user to send commands to the object using the applet's command buttons. When you run the applet with Appletviewer, you see the window shown in Figure 27.4. To play the sound once from beginning to end, click the Play button. To stop the sound at any time, click the Stop button. Finally, to play the sound over and over, click the Loop button.

Figure 27.4 : This is Appletviewer running SoundApplet2.


Listing 27.3  SoundApplet2.java: An Applet That Creates and Displays an AudioClip Object.

import java.awt.*;

import java.applet.*;

import java.net.*;



public class SoundApplet2 extends Applet

{

    AudioClip soundClip;



    public void init()

    {

        GridLayout layout = new GridLayout(1, 3, 10, 10);

        setLayout(layout);



        Font font = new Font("TimesRoman", Font.BOLD, 24);

        setFont(font);



        Button button = new Button("Play");

        add(button);

        button = new Button("Stop");

        add(button);

        button = new Button("Loop");

        add(button);



        URL codeBase = getCodeBase();

        soundClip = getAudioClip(codeBase, "spacemusic.au");



        resize(250, 250);

    }



    

public boolean action(Event evt, Object arg)

    {

        if (arg == "Play")

            soundClip.play();

        else if (arg == "Stop")

            soundClip.stop();

        else if (arg == "Loop")

            soundClip.loop();



        return true;

    }

}


Tell Java that the applet uses the classes in the awt package.
Tell Java that the applet uses the classes in the applet package.
Tell Java that the applet uses the classes in the net package.
Derive the SoundApplet2 class from Java's Applet class.
Declare the class's audio clip object.
Override the init() method.
Create and set the applet's layout.
Create and set the applet's font.
Create and add the three buttons.
Get the base URL and create the audio clip.
Size the applet.
Override the 5 method.
Respond to the appropriate button.
Tell Java that the event was handled.

Summary

Nothing spices up an applet more than vivid graphics and enjoyable sound effects. That's why Java's creators went to such lengths to ensure that you can easily add these important elements to your applets. Loading and displaying an image is as simple as obtaining the image's base URL, creating an Image object, and calling drawImage() to display the image on the screen. Sound effects are just as easy-if not easier-to handle. The simplest way is to call the applet's play() method, which will play the sound from beginning to end. However, if you want a little extra control over the sound, you can create an AudioClip object, whose method's enable you to play, stop, and loop the sound.

Review Questions

  1. What two types of image files can be loaded by a Java applet?
  2. What two parameters are required by methods such as getImage() and getAudioClip()?
  3. What's the only type of audio file recognized by Java?
  4. How do you display an image after it's loaded?
  5. Do image and sound files always have to be stored in the same directory as the HTML or CLASS file?
  6. How do you display an image larger or smaller than normal?
  7. How can you determine the width and height of an image?
  8. What's the difference between a document and code base URL?
  9. Why does creating an AudioClip object give you more control over your sound effects?

Review Exercises

  1. Write an applet that displays the SNAKE.gif image at three times its normal size.
  2. Write an applet that loops the SPACEMUSIC.AU file as soon as the applet starts up. The applet should have a Stop button that enables the user to stop the sound.
  3. Write an applet that has three buttons for displaying an image at 50%, 100%, and 200% of its normal size. Use the SNAKE.gif image that you used earlier in this chapter. When the user clicks a button, you should display the image at the selected size, reducing or enlarging the applet's size to accommodate the image. But make the applet's minimum horizontal size 150 so that the three buttons always fit across the top. Figures 27.6, 27.7, and 27.8 show the ImageApplet3 applet displaying the image in its three sizes. (You can find the solution for this exercise in the CHAP27 folder of this book's CD-ROM.)

Figure 27.5 : Here's the image at 50%.

Figure 27.6 : Here's the image at 100%.

Figure 27.7 : And here's the image at 200%.