The AWT Imaging ModelJDK 1.0 introduced the AWT imaging model for downloading and drawing images. Back then, it was thought that the most common use of imaging would involve applets pulling graphics from the Web. A standard '90s example (with the exception of using JApplet ) is shown in Example 5-1. Example 5-1. ShowImage applet (Version 1) using Image
import javax.swing.*;
import java.awt.*;
public class ShowImage extends JApplet
{
private
Image
im;
public void init( )
{ im =
getImage
(
getDocumentBase( )
, "ball.gif"); }
public void paint(Graphics g)
{ g.
drawImage
(im, 0, 0, this); }
}
The getdocumentBase( ) method returns the URL of the directory holding the original web document, and this is prepended to the image's filename to get a URL suitable for getImage( ) .
The central problem with networked image retrieval is speed. Consequently, the Java designers
The fourth argument supplied to
drawImage( )
is an
ImageObserver
(usually the applet or
JFrame
in an application), which will monitor the gradual downloading of the image. As data arrives, the
Component
's
imageUpdate( )
is repeatedly called.
imageUpdate( )
's default behavior is to call
repaint( )
, to
The overall effect is that
paint( )
will be called repeatedly as the image is downloaded,
The result of this coding style means that the Image ( im ) contains no data until paint( ) is called and even then may not contain complete information for several seconds or minutes. This makes programming difficult: for instance, a GUI cannot easily allocate an on-screen space to the image since it has no known width or height until painting has started.
Since the introduction of JDK 1.0, experience has shown that most programs do not want graphics to be drawn incrementally during execution. For example, game
The getImage( ) method is only for applets; there is a separate getImage( ) method for applications, accessible from Toolkit . For example:
Image im = Toolkit.getDefaultToolkit( ).getImage("http://....");
As with the getImage( ) method for applets, it doesn't download anything. That task is done by paint( ) . The MediaTracker Class
Most programs (and most
One solution is the java.awt.MediaTracker class: a MediaTracker object can start the download of an image and suspend execution until it has fully arrived or an error occurs. The init( ) method in the ShowImage class can be modified to do this:
public void init( )
{
im = getImage( getDocumentBase( ), "ball.gif");
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(im, 0);
try {
tracker.waitForID(0);
}
catch (InterruptedException e)
{ System.out.println("Download Error"); }
}
waitForID( ) starts the separate download thread, and suspends until it finishes. The ID used in the MediaTracker object can be any positive integer.
In paint( ) , drawImage( ) will only draw the image since a download is unnecessary. Consequently, drawImage( ) can be supplied with a null (empty) ImageObserver : drawImage(im, 0, 0, null); A common way of accelerating the downloading of multiple images is to spawn a pool of threads, each one assigned to the retrieval of a single image. Only when every thread has completed will init( ) return. ImageIcon
Writing
MediaTracker
code in every applet/application can be boring, so an
ImageIcon
class was introduced, which sets up a
MediaTracker
by itself. The
ImageIcon
name is a bit misleading: any
Using ImageIcon , the init( ) method becomes:
public void init( )
{ im = new ImageIcon( getDocumentBase( )+"ball.gif").getImage( ); }
The
ImageIcon
object can be converted to an
Image
(as here) or can be
The Rise of JARsA JAR file is a way of packaging code and resources together into a single, compressed file. Resources can be almost anything, including images and sounds.
If an applet (or application) is going to utilize a lot of images, repeated network connections to download them will severely reduce execution speed. It's better to create a single JAR file containing the applet (or application) and all the images and to have the browser (or user) download it. Then, when an image comes to be loaded, it's a fast, local load from the JAR file. From a
At the end of Chapter 6, I'll explain how to package the ImagesTests code, and the large number of images it uses, as a JAR file. The only coding change occurs in specifying the location of an image file. Going back to a simpler example, the ImageIcon example from above would need to be rewritten this way:
im = new ImageIcon(
getClass( ).getResource
("ball.gif") ).getImage( );
getClass( ) gets the Class reference for the object (e.g., ShowImage ), and getresource( ) specifies the resource is stored in the same place as that class. AWT Image Processing
It can be difficult to access the various elements of an
Image
object, such as pixel data or the
Figure 5-1. Image processing in AWT
The two predefined
ImageFilter
subclasses are
CropImageFilter
for cropping
{% if main.adsdop %}{% include 'adsenceinline.tpl' %}{% endif %}
This stream-view of filtering makes it difficult to process groups of pixels,
An alternative approach is to use the
PixelGrabber
class to collect all the pixel data from an image into an array, where it can then be conveniently
Figure 5-2. Processing the image as an array
Modern Java code (since J2SE 1.2) can utilize the image processing capabilities of Java 2D, with its many predefined operations, so you're
|