Images consist of pixel values: each pixel is determined by its "RGB" values, typically 8-bits for each value.
Images are typically stored in compressed format.
GIF (Graphical Interchange Format) is one such format: GIF (created by CompuServe) uses the lossless Lempel-Ziv-Welch (LZW) algorithm. GIF is probably the most popular format. However, there is a patent controversy surrounding GIF. (Unisys holds the LZW patent).
JPEG (Joint Photographic Experts Group) is another format: JPEG uses lossy compression based on a number of image-processing techniques such as transforms (DCT) and quantization. JPEG is free. JPEG is really an algorithm spec rather than a file spec.
PNG (Portable Network Graphics) format: Lossless format, like GIF. Slightly better compression than GIF. Free of patent issues. Support for transparency and progressive display.
Java handles GIF, JPEG and PNG formats and decides based on the extensions .gif, .jpeg or .jpg, and .png. The following classes will be useful:
Both methods return an Image instance.
Let's look at a simple example:
import java.awt.*; import java.awt.event.*; class NewFrame extends Frame { // Constructor. public NewFrame (int width, int height) { // Set the title and other frame parameters. setTitle ("Bugs"); setResizable (true); setBackground (Color.cyan); setSize (width, height); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); // Show the frame. setVisible (true); } // Override paint(): public void paint (Graphics g) { // Get a Toolkit instance. Toolkit tk = Toolkit.getDefaultToolkit (); // Provide a filename to the getImage() method. Image img = tk.getImage ("bugs.jpg"); // Use the drawImage method. g.drawImage (img, 0, 0, this); // Note: we pass "this" as a parameter. } } // End of class "NewFrame" public class TestAwt13 { public static void main (String[] argv) { NewFrame nf = new NewFrame (800, 600); } }
Before you run the code, find a jpeg of Bugs Bunny. The file bugs.jpg is assumed to be in the same directory as the program.
Since the insets were not used, part of the image gets clipped.
The definition of drawImage() used is: public void boolean drawImage (Image img, int x, int y, ImageObserver i);
Note that Component implements the ImageObserver interface:
public abstract class Component implements ImageObserver, MenuContainer, Serializable { // ... }
Thus, Frame, which is a subclass of Component, also implements ImageObserver. Therefore, we can pass the current Frame instance (via this) as the fourth parameter: g.drawImage (img, 0, 0, this);
You don't really need to understand the purpose of ImageObserver at this time. In the next example, we will fetch an image from a URL:
import java.awt.*; import java.awt.event.*; import java.net.*; // For class URL. class NewFrame extends Frame { // Constructor. public NewFrame (int width, int height) { // Set the title and other frame parameters. setTitle ("Big Turkeys"); setResizable (true); setBackground (Color.cyan); setSize (width, height); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); // Show the frame. setVisible (true); } // Override paint(): public void paint (Graphics g) { Toolkit tk = Toolkit.getDefaultToolkit (); // try-catch needed since URL constructor throws an exception. try { // URL is in java.net. URL u = new URL ("http://www.seas.gwu.edu/~rhyspj/cs143/lab10/turkeys.jpg"); // Load the image using the second form of getImage(). Image img = tk.getImage (u); // Display image. g.drawImage (img, 0, 0, this); } catch (MalformedURLException e) { System.out.println (e); } } // "paint" } // End of class "NewFrame" public class TestAwt14 { public static void main (String[] argv) { NewFrame nf = new NewFrame (600, 300); } }
The class URL is in package java.net.
An actual URL is passed to the constructor of the class URL: URL u = new URL ("http://www.seas.gwu.edu/~rhyspj/cs143/lab10/turkeys.jpg");
The getImage() method of Toolkit has a form that takes in a URL instance.
If you try it out, you will notice that it takes time for the image to load.
The image is loaded slowly (top-down).
In-Class Exercise 9.5 (Solution): Use the following template to create a frame in which you load the image at URL http://www.seas.gwu.edu/~rhyspj/cs143/lab10/turkeys.jpg and then fit the image so that it fits exactly into the drawable area. To do this:
Next, we will use a MediaTracker instance to complete loading before display:
public void paint (Graphics g) { Toolkit tk = Toolkit.getDefaultToolkit (); try { URL u = new URL ("http://www.seas.gwu.edu/~rhyspj/cs143/lab10/turkeys.jpg"); Image img = tk.getImage (u); // Create an instance of MediaTracker and // pass a Frame instance as parameter (via "this"). MediaTracker mt = new MediaTracker (this); // Add the image instance to the tracker. mt.addImage (img, 1); // We will use a "wait" (clock) cursor while the // image is loading. this.setCursor (Cursor.getPredefinedCursor (Cursor.WAIT_CURSOR)); // Ask the MediaTracker to wait. try { mt.waitForID (1); } catch (InterruptedException e) { System.out.println (e); } // Now the image has been loaded. // Return to default cursor. this.setCursor (Cursor.getPredefinedCursor (Cursor.DEFAULT_CURSOR)); // Draw the complete image. g.drawImage (img, 0, 0, this); } catch (MalformedURLException e) { System.out.println (e); } } // "paint"
Use the following template to create a frame in which you load the four images guy1.gif, guy2.gif, guy3.gif and guy4.gif at URL http://www.seas.gwu.edu/~simha/. (Thus, the URL for guy1.gif is http://www.seas.gwu.edu/~simha/guy1.gif). This time, instead of fitting the images to the frame, fit the frame to hold all images in a row so that the frame width at least the sum of the image widths and the frame height is at least as large the the maximum height of the images. The following methods will be useful:
Use MediaTracker to wait for all images to be loaded. Class Image has
methods getWidth() and getHeight() to obtain the width and height of
an image (after its loaded). Both the above methods need to be given
an ImageObserver instance as a parameter. Use getInsets() as before
to get the insets. Use setSize(int w, int h) to set the size of the
frame. Finally, use drawImage() to draw the images at the right
places.