| We mentioned an Chapter 
              6 : Java : Images that an image is not actually loaded when 
              getImage()is 
              invoked. Only when an attempt is made to access the image, such 
              as an invocation of drawImage() 
              or getWidth() 
              will the loading of the image begin. Once the loading begins, it is, of course, not instantaneous. It 
              can in fact take considerable time if the loading takes place over 
              a slow network link. The loading is controlled by an internal thread 
              so that other processing can continue. We look here a three approaches 
              to loading images. 
              ImageObserver 
                - override the method imageUpdate 
                () and monitor the loading "manually"MediaTracker 
                - tool to monitor the loading of one or more imagesImageIcon 
                - a useful class to load a single image. See also the discussion in Chapter 
              11: Supplements: Creating & Saving Images about using classes 
              in the  javax.imageio 
              package for reading/writing instances of BufferedImage. 
             Monitoring 
              with an ImageObserver  If no other steps are taken, a call to drawImage() 
              will return immediately while the image continues to be periodically 
              updated as more pixels arrive. The last argument to drawImage() 
              is a reference to an object that implements the ImageObserver 
              interface:   drawImage 
              (Image img, int x, int y, ImageObserver iob)  The image loading thread periodically calls 
              imageUpdate()  in the ImageObserver 
              object to provide status reports on the loading:    public 
              boolean imageUpdate (Image img, int info_flags,int x, int y, int w, int h)
 This method receives information via the bit settings in the info_flags 
              argument and from the dimension values. For the situation of multiple 
              images loading, you can identify which image is being updated from 
              the reference value in the first argument. The method imageUpdate() 
              returns true 
              when the loading is not yet finished. See the ImageObserver 
              class description in the API 
              Specifications and the Constant 
              Field Values for more details about the info_flags 
              values passed in the method's arguments. You could create an ImageObserver 
              class just for monitoring the image loading but usually you just 
              put "this" 
              in the last argument, as in     g.drawImage 
              (img, x, y, this) and rely on the default imageUpdate() 
              of the Applet 
              class, which inherits this method from Component. 
              The Component 
              class implements this interface and provides a default imageUpdate() 
              method.. You can also override imageUpdate() 
              and monitor the loading yourself. The program ImageObsApplet 
              below shows one way to implement imageUpdate(). 
              The applet's start() 
              method starts a thread that will periodically check a flag - fDoneLoadingImage 
              - that indicates whether the image has finished loading. In the run() 
              method, the invocation of getWidth(ImageObserver) 
              for the image initiates the loading process. The image loading machinery 
              in the AWT will periodically call back to the ImageObserver 
              object passed in the argument to getWidth(). 
              It invokes the imageUpdate() 
              method and passes the image information described above.  As long as info_flags 
              != ALLBITS then the method returns true. 
              When info_flags 
              == ALLBITS then the flag fDoneLoadingImage 
              is set to true, 
              which will cause the loop in the run() 
              method to finish and the thread to die. The imageUpdate() 
              will return false and it will no longer be invoked.  
              
                 
                  | ImageObsApplet.java Resources: 07-JG-01-pan-A074R1_br2.jpg
 
 |   
                  |  import 
                      javax.swing.*;import java.awt.*;
 
 /** Illustrate use of ImageObserver for image loading. **/
 public class ImageObsApplet extends JApplet
 implements Runnable
 {
 // Need a reference to the panel for the
 // thread loop.
 DrawingPanel fDrawingPanel;
 
 Image fImg;
 int fImageNum = 0;
 String fMessage ="Loading...";
 boolean fDoneLoadingImage = false;
 
 /** Use a ImageObserver to load an image.**/
 public void init () {
 Container content_pane = getContentPane 
                      ();
 
 // Create an instance of DrawingPanel
 fDrawingPanel = new DrawingPanel 
                      (this);
 
 // Add the DrawingPanel to the contentPane.
 content_pane.add (fDrawingPanel);
 
 // Get image and monitor its loading.
 fImg = getImage (getCodeBase (), 
                      "07-JG-01-pan-A074R1_br2.jpg" );
 
 } // init
 
 /**
 * Start the thread to monitor the 
                      image loading.
 **/
 public void start () {
 Thread thread = new Thread (this);
 thread.start ();
 }
 
 /** Use a thread to wait for the image to load
 * before painting it.
 **/
 public void run ()  {
 
 // Checking the image width will 
                      initiate the loading.
 int width = fImg.getWidth (this);
 
 // If the width is not equal to 
                      -1 then the file has already
 // been loaded. This can happen 
                      if the applet page was loaded
 // once before and then loaded again 
                      into the browser.
 if (width >= 0) {
 fDoneLoadingImage 
                      = true;
 repaint 
                      ();
 return;
 }
 
 // Wait if the image is not loaded 
                      yet
 while (!fDoneLoadingImage) {
 try {
 Thread.sleep 
                      (500);
 }
 catch (InterruptedException 
                      ie) {
 }
 // Repaint with either 
                      the image or the text message
 repaint ();
 }
 } // run
 
 /** Override the ImageObserver imageUpdate method 
                      and monitor
 * the loading of the image. Set 
                      a flag when it is loaded.
 **/
 public boolean imageUpdate (Image img, int info_flags,
 int x, int y, int w, int h) {
 if (info_flags != ALLBITS) {
 // Indicates 
                      image has not finished loading
 // Returning 
                      true will tell the image loading
 // thread 
                      to keep drawing until image fully
 // drawn 
                      loaded.
 return true;
 } else {
 fDoneLoadingImage 
                      = true;
 return false;
 }
 } // imageUpdate
 
 }// class ImageObsApplet
 
 
 /** This JPanel subclass draws an image on the panel if
 * the image is loaded. Otherwise, it draws a 
                      text message.
 **/
 class DrawingPanel extends JPanel {
 ImageObsApplet fParent = null;
 
 DrawingPanel (ImageObsApplet parent) {
 fParent = parent;
 }// ctor
 
 public void paintComponent (Graphics g) {
 super.paintComponent (g);
 
 // Add your drawing instructions 
                      here
 if (fParent.fDoneLoadingImage)
 g.drawImage 
                      (fParent.fImg,10,10,this);
 else
 g.drawString 
                      (fParent.fMessage, 10,10);
 } // paintComponent
 
 } // class DrawingPanel
 |    MediaTracker A more powerful and elegant way to monitor image loading is to 
              use the MediaTracker 
              class. Below we see that an instance of the MediaTracker 
              is created and the image added to it. A thread is initiated to load 
              the image. The run() 
              waits for the tracker to signal that the image is loaded and then 
              the paint() 
              switches from drawing a string message to drawing the image. MediaTracker 
              provides the method     int 
              status (int ID, boolean load) which returns a status indicator in an integer value that is an 
              OR of four flags: 
              ABORTED COMPLETEERROREDLOADING The MediaTracker 
              is especially useful when one needs to load many images. The statusAll() 
              returns a similar value as above except that it is an OR of the 
              status of all the images currently loading. 
              
                 
                  | MediaTrackApplet.java Resources: m20.gif
 |   
                  |  import 
                      javax.swing.*;import java.awt.*;
 
 /** Illustrate use of MediaTracker for image loading. **/
 public class MediaTrackApplet extends JApplet
 implements Runnable
 {
 // Need a reference to the panel for the
 // thread loop.
 DrawingPanel fDrawingPanel;
 
 // Parameters to track the image
 MediaTracker fTracker;
 Image fImg;
 int fImageNum = 0;
 boolean fShow = false;
 String fMessage ="Loading...";
 
 /** Use a MediaTracker to load an image.**/
 public void init () {
 Container content_pane = getContentPane 
                      ();
 
 // Create an instance of DrawingPanel
 fDrawingPanel = new DrawingPanel 
                      (this);
 
 // Add the DrawingPanel to the contentPane.
 content_pane.add (fDrawingPanel);
 
 // Get image and monitor its loading.
 fImg = getImage (getCodeBase (), 
                      "m20.gif.jpg" );
 fTracker = new MediaTracker (this);
 
 // Pass the image reference and 
                      an ID number.
 fTracker.addImage (fImg, fImageNum);
 } // init
 
 /** If the image not yet loaded, run the thread
 * so the run() will monitor the 
                      image loading.
 **/
 public void start () {
 if (!fTracker.checkID (fImageNum) 
                      ) {
 Thread thread 
                      = new Thread (this);
 thread.start 
                      ();
 } else
 // Unloading/reloading 
                      web page can will leave
 // checkID 
                      true but fShow will be false.
 fShow = true;
 } // start
 
 /** Use a thread to wait for the image to load
 * before painting it.
 **/
 public void run ()  {
 // Paint the loading message
 repaint ();
 // The wait for the image to finish 
                      loading
 try {
 fTracker.waitForID (fImageNum 
                      );
 } catch (InterruptedException e) 
                      {}
 
 // Check if there was a loading 
                      error
 if (fTracker.isErrorID (fImageNum 
                      ))
 fMessage= 
                      "Error";
 else
 fShow = 
                      true;
 // Repaint with the image now if 
                      it loaded OK
 repaint ();
 } // run
 
 }// class MediaTrackApplet
 
 
 /** This JPanel subclass draws an image on the panel if
 * the image is loaded. Otherwise, it draws a 
                      text message.
 **/
 class DrawingPanel extends JPanel {
 MediaTrackApplet parent = null;
 
 DrawingPanel (MediaTrackApplet parent) {
 this.parent = parent;
 }// ctor
 
 public void paintComponent (Graphics g) {
 super.paintComponent (g);
 
 // Add your drawing instructions 
                      here
 if (parent.fShow)
 g.drawImage 
                      (parent.fImg,10,10,this);
 else
 g.drawString 
                      (parent.fMessage, 10,10);
 } // paintComponent
 
 } // class DrawingPanel
 |    See the API 
              Specifications for details of the MediaTracker 
              class.  Using 
               ImageIcon 
              to an Load Image The ImageIcon 
              class offers a shortcut technque for loading an image. This class, 
              which came with Java 1.2 in the  
              java.swing package, was primarily intended 
              for obtaining small icon images on buttons and other components. 
              However, it can also be used to load any image file, regardless 
              of the size.  ImageIcon 
              uses a MediaTracker 
              internally so it provides a convenient way to load a single image 
              as illustrated by this snippet:.     ...ImageIcon img = new ImageIcon (url);
 Image image = img.getImage ();
 ...
 The ImageIcon 
              constructor will block (i.e. not return) until either the image 
              loads or the address is deemed invalid. In the later case an ImageIcon 
              object is still created but it will have zero dimensions. The method 
              getImageLoadStatus() 
              returns an integer with the status flags (see above) from the internal 
              MediaTracker. References & Web Resources Latest update: March 8, 2006 |