- •Contents
- •Preface
- •Introduction to Computers, the Internet and the Web
- •1.3 Computer Organization
- •Languages
- •1.9 Java Class Libraries
- •1.12 The Internet and the World Wide Web
- •1.14 General Notes about Java and This Book
- •Sections
- •Introduction to Java Applications
- •2.4 Displaying Text in a Dialog Box
- •2.5 Another Java Application: Adding Integers
- •2.8 Decision Making: Equality and Relational Operators
- •Introduction to Java Applets
- •3.2 Sample Applets from the Java 2 Software Development Kit
- •3.3 A Simple Java Applet: Drawing a String
- •3.4 Two More Simple Applets: Drawing Strings and Lines
- •3.6 Viewing Applets in a Web Browser
- •3.7 Java Applet Internet and World Wide Web Resources
- •Repetition)
- •Class Attributes
- •5.8 Labeled break and continue Statements
- •5.9 Logical Operators
- •Methods
- •6.2 Program Modules in Java
- •6.7 Java API Packages
- •6.13 Example Using Recursion: The Fibonacci Series
- •6.16 Methods of Class JApplet
- •Class Operations
- •Arrays
- •7.6 Passing Arrays to Methods
- •7.8 Searching Arrays: Linear Search and Binary Search
- •Collaboration Among Objects
- •8.2 Implementing a Time Abstract Data Type with a Class
- •8.3 Class Scope
- •8.4 Controlling Access to Members
- •8.5 Creating Packages
- •8.7 Using Overloaded Constructors
- •8.9 Software Reusability
- •8.10 Final Instance Variables
- •Classes
- •8.16 Data Abstraction and Encapsulation
- •9.2 Superclasses and Subclasses
- •9.5 Constructors and Finalizers in Subclasses
- •Conversion
- •9.11 Type Fields and switch Statements
- •9.14 Abstract Superclasses and Concrete Classes
- •9.17 New Classes and Dynamic Binding
- •9.18 Case Study: Inheriting Interface and Implementation
- •9.19 Case Study: Creating and Using Interfaces
- •9.21 Notes on Inner Class Definitions
- •Strings and Characters
- •10.2 Fundamentals of Characters and Strings
- •10.21 Card Shuffling and Dealing Simulation
- •Handling
- •Graphics and Java2D
- •11.2 Graphics Contexts and Graphics Objects
- •11.5 Drawing Lines, Rectangles and Ovals
- •11.9 Java2D Shapes
- •12.12 Adapter Classes
- •Cases
- •13.3 Creating a Customized Subclass of JPanel
- •Applications
- •Controller
- •Exception Handling
- •14.6 Throwing an Exception
- •14.7 Catching an Exception
- •Multithreading
- •15.3 Thread States: Life Cycle of a Thread
- •15.4 Thread Priorities and Thread Scheduling
- •15.5 Thread Synchronization
- •15.9 Daemon Threads
- •Multithreading
- •Design Patterns
- •Files and Streams
- •16.2 Data Hierarchy
- •16.3 Files and Streams
- •Networking
- •17.2 Manipulating URIs
- •17.3 Reading a File on a Web Server
- •17.4 Establishing a Simple Server Using Stream Sockets
- •17.5 Establishing a Simple Client Using Stream Sockets
- •17.9 Security and the Network
- •18.2 Loading, Displaying and Scaling Images
- •18.3 Animating a Series of Images
- •18.5 Image Maps
- •18.6 Loading and Playing Audio Clips
- •18.7 Internet and World Wide Web Resources
- •Data Structures
- •19.4 Linked Lists
- •20.8 Bit Manipulation and the Bitwise Operators
- •Collections
- •21.8 Maps
- •21.9 Synchronization Wrappers
- •21.10 Unmodifiable Wrappers
- •22.2 Playing Media
- •22.3 Formatting and Saving Captured Media
- •22.5 Java Sound
- •22.8 Internet and World Wide Web Resources
- •Hexadecimal Numbers
1070 |
Multimedia: Images, Animation, Audio and Video |
Chapter 18 |
We need programming languages that make creating multimedia applications easy. Most programming languages do not have built-in multimedia capabilities. However, Java provides extensive multimedia facilities that enable you to start developing powerful multimedia applications immediately.
This chapter presents a series of “live-code” examples that cover several interesting multimedia features you will need to build useful applications, including:
1.the basics of manipulating images
2.creating smooth animations
3.customizing an animation applet via parameters supplied from the HTML file that invokes an applet
4.playing audio files with the AudioClip interface
5.creating image maps that can sense when the cursor is over them even without a mouse click
We will continue our coverage of Java’s multimedia capabilities in Chapter 22, where we discuss the Java Media Framework (JMF) and the Java Sound APIs. JMF and Java Sound enable Java programs to play and record audio and video. The JMF even enables Java programs to send audio and video streams—so-called streaming media—across a network or the Internet. The chapter exercises for this chapter and Chapter 22 suggest dozens of challenging and interesting projects and even mention some “million-dollar” ideas that could help you make your fortune! When we were creating these exercises, it seemed that the ideas just kept flowing. Multimedia seems to leverage creativity in ways that we have not experienced with “conventional” computer capabilities.
18.2 Loading, Displaying and Scaling Images
Java’s multimedia capabilities include graphics, images, animations, sounds and video. We begin our multimedia discussion with images.
The applet of Fig. 18.1 demonstrates loading an Image (package java.awt) and loading an ImageIcon (package javax.swing). The applet displays the Image in its original size and scaled to a larger size, using two versions of Graphics method drawImage. The applet also draws the ImageIcon using its method paintIcon. Class ImageIcon is easier than Image to use, because its constructor can receive arguments of several different formats, including a byte array containing the bytes of an image, an Image already loaded in memory, a String representing the location of an image and a URL representing the location of an image.
1// Fig. 18.1: LoadImageAndScale.java
2// Load an image and display it in its original size
3 // and scale it to twice its original width and height. 4 // Load and display the same image as an ImageIcon.
5
6// Java core packages
7 import java.applet.Applet;
8import java.awt.*;
Fig. 18.1 Loading and displaying an image in an applet (part 1 of 2).
Chapter 18 |
Multimedia: Images, Animation, Audio and Video |
1071 |
9
10// Java extension packages
11import javax.swing.*;
12
13public class LoadImageAndScale extends JApplet {
14private Image logo1;
15private ImageIcon logo2;
16
17// load image when applet is loaded
18public void init()
19{
20logo1 = getImage( getDocumentBase(), "logo.gif" );
21logo2 = new ImageIcon( "logo.gif" );
22}
23
24// display image
25public void paint( Graphics g )
26{
27// draw original image
28g.drawImage( logo1, 0, 0, this );
30// draw image scaled to fit width of applet
31// and height of applet minus 120 pixels
32g.drawImage( logo1, 0, 120,
33 |
getWidth(), getHeight() - 120, this ); |
34 |
|
35// draw icon using its paintIcon method
36logo2.paintIcon( this, g, 180, 0 );
37}
38
39 } // end class LoadImageAndScale
Fig. 18.1 Loading and displaying an image in an applet (part 2 of 2).
1072 |
Multimedia: Images, Animation, Audio and Video |
Chapter 18 |
Lines 14 and 15 declare an Image reference and an ImageIcon reference, respectively. Class Image is an abstract class; therefore, the applet cannot create an object of class Image directly. Rather, the applet must call a method that causes the applet container to load and return the Image for use in the program. Class Applet (the superclass of JApplet) provides a method that does just that. Line 20 in method init uses Applet method getImage to load an Image into the applet. This version of getImage takes two argu- ments—the location of the image file and the file name of the image. In the first argument, Applet method getDocumentBase returns a URL representing the location of the image on the Internet (or on your computer if the applet was loaded from your computer). The program assumes that the image is stored in the same directory as the HTML file that invoked the applet. Method getDocumentBase returns the location of the HTML file on the Internet as an object of class URL. The second argument specifies an image file name. Java supports several image formats, including Graphics Interchange Format (GIF), Joint Photographic Experts Group (JPEG) and Portable Network Graphics (PNG). File names for each of these types end with .gif, .jpg (or .jpeg) and .png, respectively.
Portability Tip 18.1
Class Image is an abstract class and, as a result, programs cannot instantiate Image objects. To achieve platform independence, the Java implementation on each platform provides its own subclass of Image to store image information.
When line 20 invokes method getImage to set up loading of the image from the local computer (or downloading of the image from the Internet). When the image is required by the program, the image is loaded in a separate thread of execution. This enables the program to continue execution while the image loads. [Note: If the requested file is not available, method getImage does not indicate an error.]
Class ImageIcon is not an abstract class; therefore, a program can create an ImageIcon object. Line 21 in method init creates an ImageIcon object that loads the same logo.gif image. Class ImageIcon provides several constructors that enable programs to initialize ImageIcon objects with images from the local computer or with images stored on the Internet.
The applet’s paint method (lines 25–37) displays the images. Line 28 uses Graphics method drawImage to display an Image. Method drawImage receives four arguments. The first argument is a reference to the Image object to display (logo1). The second and third arguments are the x- and y-coordinates at which to display the image on the applet; the coordinates indicate the upper-left corner of the image. The last argument is a reference to an ImageObserver object. Normally, the ImageObserver is the object on which the program displays the image. An ImageObserver can be any object that implements interface ImageObserver. Class Component (one of class Applet’s indirect superclasses) implements interface ImageObserver. Therefore, all Components (including our applet) are ImageObservers. The ImageObserver argument is important when displaying large images that require a long time to download from the Internet. It is possible that a program will execute the code that displays the image before the image downloads completely. The ImageObserver is notified to update the displayed image as the remainder of the image loads. When executing this applet, watch carefully as pieces of the image display while the image loads. [Note: On faster computers, you might not notice this effect.]
Lines 32–33 use another version of Graphics method drawImage to output a scaled version of the image. The fourth and fifth arguments specify the width and height of
Chapter 18 |
Multimedia: Images, Animation, Audio and Video |
1073 |
the image for display purposes. Method drawImage scales the image to fit the specified width and height. In this example, the fourth argument indicates that the width of the scaled image should be the width of the applet, and the fifth argument indicates that the height should be 120 pixels less than the height of the applet. Line 33 determines the width and height of the applet by calling methods getWidth and getHeight (inherited from class
Component).
Line 36 uses ImageIcon method paintIcon to display the image. The method requires four arguments—a reference to the Component on which to display the image, a reference to the Graphics object that will render the image, the x-coordinate of the upperleft corner of the image and the y-coordinate of the upper-left corner of the image.
If you compare the two techniques for loading and displaying images in this example, you can see that using ImageIcon is simpler. You can create objects of class ImageIcon directly, and there is no need to use an ImageObserver reference when displaying the image. For this reason, we use class ImageIcon for the remainder of the chapter. [Note: Class ImageIcon’s paintIcon method does not allow scaling of an image. However, the class provides method getImage, which returns an Image reference that Graphics method drawImage can use to display a scaled image.]
18.3 Animating a Series of Images
The next example demonstrates animating a series of images that are stored in an array. The application uses the same techniques to load and display ImageIcons as shown in Fig. 18.1. The animation presented in Fig. 18.2 is designed as a subclass of JPanel (called LogoAnimator) that can be attached to an application window or possibly to a JApplet. Class LogoAnimator also defines a main method (defined at lines 96–117) to execute the animation as an application. Method main defines an instance of class JFrame and attaches a LogoAnimator object to the JFrame to display the animation.
1 // Fig. 18.2: LogoAnimator.java
2 // Animation a series of images
3
4 // Java core packages
5import java.awt.*;
6 import java.awt.event.*;
7
8 // Java extension packages
9 import javax.swing.*;
10
11public class LogoAnimator extends JPanel
12implements ActionListener {
13 |
|
|
14 |
protected ImageIcon images[]; |
// array of images |
15 |
|
|
16 |
protected int totalImages = 30, |
// number of images |
17 |
currentImage = 0, |
// current image index |
18 |
animationDelay = 50, |
// millisecond delay |
19 |
width, |
// image width |
20 |
height; |
// image height |
Fig. 18.2 Animating a series of images (part 1 of 3).
1074 |
Multimedia: Images, Animation, Audio and Video |
Chapter 18 |
21
22protected String imageName = "deitel"; // base image name
23protected Timer animationTimer; // Timer drives animation
25// initialize LogoAnimator by loading images
26public LogoAnimator()
27{
28initializeAnimation();
29}
30
31// initialize animation
32protected void initializeAnimation()
33{
34images = new ImageIcon[ totalImages ];
36// load images
37for ( int count = 0; count < images.length; ++count )
38 |
images[ count ] = new ImageIcon( |
getClass().getResource( |
|||
39 |
"images/" + |
imageName + count + ".gif" |
) ); |
|
|
40 |
|
|
|
|
|
41 |
width = images[ 0 |
].getIconWidth(); |
// get |
icon |
width |
42height = images[ 0 ].getIconHeight(); // get icon height
43}
44
45// display current image
46public void paintComponent( Graphics g )
47{
48super.paintComponent( g );
49
50images[ currentImage ].paintIcon( this, g, 0, 0 );
51currentImage = ( currentImage + 1 ) % totalImages;
52}
53
54// respond to Timer's event
55public void actionPerformed( ActionEvent actionEvent )
56{
57repaint(); // repaint animator
58}
59
60// start or restart animation
61public void startAnimation()
62{
63if ( animationTimer == null ) {
64 |
currentImage = |
0; |
65 |
animationTimer |
= new Timer( animationDelay, this ); |
66animationTimer.start();
67}
68else // continue from last image displayed
69 |
if ( ! animationTimer.isRunning() ) |
70 |
animationTimer.restart(); |
71 |
} |
72 |
|
|
|
Fig. 18.2 Animating a series of images (part 2 of 3).
Chapter 18 |
Multimedia: Images, Animation, Audio and Video |
1075 |
73// stop animation timer
74public void stopAnimation()
75{
76animationTimer.stop();
77}
78
79// return minimum size of animation
80public Dimension getMinimumSize()
81{
82return getPreferredSize();
83}
84
85// return preferred size of animation
86public Dimension getPreferredSize()
87{
88return new Dimension( width, height );
89}
90
91// execute animation in a JFrame
92public static void main( String args[] )
93{
94// create LogoAnimator
95LogoAnimator animation = new LogoAnimator();
97// set up window
98JFrame window = new JFrame( "Animator test" );
100Container container = window.getContentPane();
101container.add( animation );
102
103 window.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
104
105// size and display window
106window.pack();
107Insets insets = window.getInsets();
109 window.setSize( animation.getPreferredSize().width +
110 insets.left + insets.right,
111 animation.getPreferredSize().height +
112 insets.top + insets.bottom );
113
114window.setVisible( true );
115animation.startAnimation(); // begin animation
117 } // end method main
118
119 } // end class LogoAnimator
Fig. 18.2 Animating a series of images (part 3 of 3).
1076 |
Multimedia: Images, Animation, Audio and Video |
Chapter 18 |
Class LogoAnimator maintains an array of ImageIcons that are loaded in method initializeAnimation (lines 32–43), which is called from the constructor. As the for structure (lines 37–39) creates each ImageIcon object, the ImageIcon constructor loads one of the animation’s 30 images. The constructor argument uses String concatenation to assemble the file name from the pieces "images/", imageName, count and ".gif". Each of the images in the animation is in a file called deitel#.gif, where # is a value in the range 0–29 specified by the loop’s control variable count. Lines 41–42 determine the width and height of the animation from the size of the first image in array images.
Performance Tip 18.1
It is more efficient to load the frames of the animation as one image than to load each image separately. (A painting program can be used to combine the frames of the animation into one image. If the images are being loaded from the Web, every image loaded requires a separate connection to the site containing the images.
Performance Tip 18.2
Loading all the frames of an animation as one large image can force your program to wait to begin displaying the animation.
After the LogoAnimator constructor loads the images, method main sets up the window in which the animation will appear and calls startAnimation (defined at lines 61–71) to begin the animation. The animation is driven by an instance of class Timer (package javax.swing). A Timer generates ActionEvents at a fixed interval in milliseconds (normally specified as an argument to the Timer’s constructor) and notifies all of its ActionListeners that the event occurred. Lines 63–67 determine whether the Timer reference animationTimer is null. If so, line 64 sets currentImage to 0, to indicate that the animation should begin with the image in the first element of array images. Line 65 assigns a new Timer object to animationTimer. The Timer constructor receives two arguments—the delay in milliseconds (animationDelay is 50 in this example) and the
ActionListener that will respond to the Timer’s ActionEvents. Class LogoAnimator implements ActionListener so line 65 specifies this as the listener. Line 66 starts the Timer object. Once started, animationTimer will generate an ActionEvent every 50 milliseconds. Lines 69–70 enable a program to restart an animation that the program stopped previously. For example, to make an animation “browser friendly” in an applet, the animation should stop when the user switches Web pages. If the user returns to the Web page with the animation, method startAnimation can be called to restart the animation. The if condition at line 73 uses Timer method isRunning to determine whether the Timer is running (i.e., generating events). If it is not running, line 70 calls Timer method restart to indicate that the Timer should start generating events again.
In response to every Timer event in this example, the program calls method actionPerformed (lines 55–58). Line 57 calls LogoAnimator’s repaint method to schedule a call to the LogoAnimator’s update method (inherited from class JPanel) which, in turn, calls LogoAnimator’s paintComponent method (lines 46– 52). Remember that any subclass of JComponent that performs drawing should do so in its paintComponent method. As mentioned in Chapter 13, the first statement in any paintComponent method should be a call to the superclass’s paintComponent method to ensure that Swing components are displayed correctly.
Chapter 18 |
Multimedia: Images, Animation, Audio and Video |
1077 |
Lines 50–51 paint the ImageIcon at element currentImage in the array and prepare for the next image to be displayed by incrementing currentImage by 1. Notice the modulus calculation to ensure that the value of currentImage is set to 0 when it is incremented past 29 (the last element subscript in the array).
Method stopAnimation (lines 74–77) stops the animation with line 76, which calls Timer method stop to indicate that the Timer should stop generating events. This prevents actionPerformed from calling repaint to initiate the painting of the next image in the array.
Software Engineering Observation 18.1
When creating an animation for use in an applet, provide a mechanism for disabling the an- imation when the user browses a new Web page separate from the page on which the animation applet resides.
Methods getMinimumSize (lines 80–83) and getPreferredSize (lines 86– 89) override the corresponding methods inherited from class Component and enable layout managers to determine the appropriate size of a LogoAnimator in a layout. In this example, the images are 160 pixels wide and 80 pixels tall, so method getPreferredSize returns a Dimension object containing the numbers 160 and 80. Method getMinimumSize simply calls getPreferredSize (a common programming practice).
Lines 107–112 of main size the application window based on the LogoAnimator’s preferred size and the window’s insets. The insets specify the number of pixels for the window’s top, bottom, left and right borders. Using the insets of the window ensures that the window’s client area is large enough to display the LogoAnimator correctly. The client area is the part of a window in which the window displays GUI components. The program obtains the window’s insets by calling method getInsets at line 107. The method returns an Insets object that contains public data members top, bottom, left and right.
18.4 Customizing LogoAnimator via Applet Parameters
When browsing the World Wide Web, you often will come across applets that are in the public domain—you can use them free of charge on your own Web pages (normally in exchange for crediting the applet’s creator). One common feature of such applets is the ability to be customized via parameters that are supplied from the HTML file that invokes the applet. For example, the HTML
<html>
<applet code = "LogoApplet.class" width = 400 height = 400> <param name = "totalimages" value = "30">
<param name = "imagename" value = "deitel"> <param name = "animationdelay" value = "200"> </applet>
</html>
from file LogoApplet.html, invokes the applet LogoApplet (Fig. 18.4) and specifies three parameters. The param tag lines must appear between the starting and ending applet tags. Each parameter has a name and a value. Applet method getParameter returns a String representing the value associated with a specific parameter name. The argument to getParameter is a String containing the name of the parameter in the param tag. For example, the statement
1078 |
Multimedia: Images, Animation, Audio and Video |
Chapter 18 |
parameter = getParameter( "animationdelay" );
gets the value 200 associated with parameter animationdelay and assigns it to String reference parameter. If there is not a param tag containing the specified parameter name, getParameter returns null.
Class LogoAnimator2 (Fig. 18.3) extends class LogoAnimator and adds a constructor that takes three arguments—the total number of images in the animation, the delay between displaying images and the base image name. Class LogoApplet (Fig. 18.4) allows Web page designers to customize the animation to use their own images. Three parameters are provided in the applet’s HTML document. Parameter animationdelay is the number of milliseconds to sleep between displaying images. This value will be converted to an integer and used as the value for instance variable sleepTime. Parameter imagename is the base name of the images to be loaded. This String will be assigned to instance variable imageName. The applet assumes that the images are in a subdirectory named images that can be found in the same directory as the applet. The applet also assumes that the image file names are numbered from 0 (as in Fig. 18.2). Parameter totalimages represents the total number of images in the animation. Its value will be converted to an integer and assigned to instance variable totalImages.
1 // Fig. 18.3: LogoAnimator2.java
2 // Animating a series of images
3
4 // Java core packages
5 import java.awt.*;
6
7 // Java extension packages
8 import javax.swing.*;
9
10 public class LogoAnimator2 extends LogoAnimator {
11
12// default constructor
13public LogoAnimator2()
14{
15super();
16}
17
18// new constructor to support customization
19public LogoAnimator2( int count, int delay, String name )
20{
21totalImages = count;
22animationDelay = delay;
23imageName = name;
24
25initializeAnimation();
26}
27
Fig. 18.3 LogoAnimator2 subclass of LogoAnimator (Fig. 18.2) adds a constructor for customizing the number of images, animation delay and base image name (part 1 of 2).
Chapter 18 |
Multimedia: Images, Animation, Audio and Video |
1079 |
28// start animation as application in its own window
29public static void main( String args[] )
30{
31// create LogoAnimator
32LogoAnimator2 animation = new LogoAnimator2();
34// set up window
35JFrame window = new JFrame( "Animator test" );
37Container container = window.getContentPane();
38container.add( animation );
39
40 window.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
41
42// size and display window
43window.pack();
44Insets insets = window.getInsets();
46 |
window.setSize( |
animation.getPreferredSize().width + |
47 |
insets.left + insets.right, |
|
48 |
animation.getPreferredSize().height + |
|
49 |
insets.top + |
insets.bottom ); |
50 |
|
|
51window.setVisible( true );
52animation.startAnimation(); // begin animation
54 } // end method main
55
56 } // end class LogoAnimator2
Fig. 18.3 LogoAnimator2 subclass of LogoAnimator (Fig. 18.2) adds a constructor for customizing the number of images, animation delay and base image name (part 2 of 2).
1// Fig. 18.4: LogoApplet.java
2// Customizing an applet via HTML parameters.
3//
4// HTML parameter "animationdelay" is an int indicating
5// milliseconds to sleep between images (default 50).
6//
7// HTML parameter "imagename" is the base name of the images
8// that will be displayed (i.e., "deitel" is the base name
9// for images "deitel0.gif," "deitel1.gif," etc.). The applet
10// assumes that images are in an "images" subdirectory of
11// the directory in which the applet resides.
12//
13// HTML parameter "totalimages" is an integer representing the
14// total number of images in the animation. The applet assumes
15// images are numbered from 0 to totalimages - 1 (default 30).
17// Java core packages
18import java.awt.*;
Fig. 18.4 Customizing an animation applet via the param HTML tag (part 1 of 2).
1080 |
Multimedia: Images, Animation, Audio and Video |
Chapter 18 |
19
20// Java extension packages
21import javax.swing.*;
22
23 public class LogoApplet extends JApplet {
24
25// obtain parameters from HTML and customize applet
26public void init()
27{
28String parameter;
29
30// get animation delay from HTML document
31parameter = getParameter( "animationdelay" );
33 int animationDelay = ( parameter == null ?
34 50 : Integer.parseInt( parameter ) );
35
36// get base image name from HTML document
37String imageName = getParameter( "imagename" );
39// get total number of images from HTML document
40parameter = getParameter( "totalimages" );
41
42 int totalImages = ( parameter == null ?
43 0 : Integer.parseInt( parameter ) );
44
45// create instance of LogoAnimator
46LogoAnimator2 animator;
47
48 if ( imageName == null || totalImages == 0 )
49animator = new LogoAnimator2();
50else
51 |
animator = new LogoAnimator2( totalImages, |
52 |
animationDelay, imageName ); |
53 |
|
54// attach animator to applet and start animation
55getContentPane().add( animator );
56animator.startAnimation();
57
58 } // end method init
59
60 } // end class LogoApplet
Fig. 18.4 Customizing an animation applet via the param HTML tag (part 2 of 2).