Java ScreenShot

Screenshot Core Java 2: Volume I - Fundamentals

Table of Contents
 7.  Graphics Programming


You have already seen how to build up simple images by drawing lines and shapes. Complex images, such as photographs, are usually generated externally, for example, with a scanner or special image-manipulation software. (As you will see in Volume 2, it is also possible to produce an image, pixel by pixel, and store the result in an array. This procedure is common for fractal images, for example.) Once images are stored in local files or someplace on the Internet, you can read them into a Java app and display them on Graphics objects. As of SDK 1.4, reading an image is very simple. If the image is stored in a local file, call

String filename = "...";
Image image = File(filename));

Otherwise, you can supply a URL:

String urlname = "...";
Image image = URL(urlname));

The read method throws an IOException if the image is not available. We will discuss the general topic of exception handling in . For now, our sample program just catches that exception and prints a stack trace if it occurs. Now the variable image contains a reference to an object that encapsulates the image data. You can display the image with the drawImage method of the Graphics class.

public void paintComponent(Graphics g)
 . . .
 g.drawImage(image, x, y, null);

Example 7-7 takes this a little bit further and tiles the window with the graphics image. The result looks like the screen shown in Screenshot-15. We do the tiling in the paintComponent method. We first draw one copy of the image in the top-left corner and then use the copyArea call to copy it into the entire window:

for (int i = 0; i * imageWidth <= getWidth(); i++)
 for (int j = 0; j * imageHeight <= getHeight(); j++)
 if (i + j > 0)
 g.copyArea(0, 0, imageWidth, imageHeight,
 i * imageWidth, j * imageHeight);

Screenshot-15. Window with tiled graphics image

Java graphics 07fig15.gif

Java graphics notes_icon.gif

When coding with the basic AWT, you need to work harder to produce flicker-free images: you need to use buffering. With Swing, buffering is automatically done for you by default. (You can turn it off but there is rarely a reason to do so.) If you need to acquire an image for an AWT component, first assemble your drawing in a background image, then draw the background image.

Image buffered_image = createImage(width, height);
Graphics bg = buffered_image.getGraphics();
// all drawing commands that use bg fill the buffered_image
// . . .
// finally, draw the buffer g.drawImage(buffered_image, 0, 0, null);
Java graphics notes_icon.gif

Earlier in this chapter, we used the getImage method of the Toolkit class to read an image file. However, that method was written with the assumption that an image may arrive slowly over a network connection. Instead of loading the file and returning to the caller when the image is actually loaded, the method spawns a new thread of execution to load the image and then returns to the caller without actually having completed that task. (See the Multithreading chapter of Volume 2 for more information on threads.) This is—to say the least—surprising to anyone who expects that a method won't return until it has done its job. But here, the multithreaded aspect of Java works against your assumptions. The code in our program runs in parallel with the code to load the image. Eventually, the image will be loaded and available. Of course, in the meantime, our code has tiled the entire buffer with copies of a blank image. There is a mechanism for tracking the image acquisition process. Using this mechanism, you can be notified when the image size is known, each time that a chunk of the image is ready, and finally, when the entire image is complete. When you use an Internet browser and look at a web page that contains an image, you can see how these notifications are translated into actions. An Internet browser lays out a web page as soon as it knows the sizes of the images in the page. Then it gradually fills in the images, as more detailed information becomes available. The fourth parameter of the drawImage call, which we set to null, can optionally point to an ImageObserver object that receives these notifications. However, we are not interested in incremental rendering. We just want to find out when the GIF image is completely loaded and then tile the buffer. One option is to use the ImageIO class, but that class is only available with SDK 1.4. If you use an earlier version of the SDK, you should use the MediaTracker class instead. A media tracker can track the acquisition of one or more images. (The name "media" suggests that the class should also be able to track audio files or other media. While such an extension may be available in the future, the current implementation tracks images only.) You add an image to a tracker object with the following command:

MediaTracker tracker = new MediaTracker();
Image img = Toolkit.getDefaultToolkit().getImage(name);
int id = 1; // the ID used to track the image loading process tracker.addImage(img, id);

You can add as many images as you like to a single media tracker. Each of the images should have a different ID number, but you can choose any numbering that is convenient. To wait for an image to be loaded completely, you use code like this:

try { tracker.waitForID(id); }
catch (InterruptedException e) {}

If you want to acquire multiple images, then you can add them all to the media tracker object and wait until they are all loaded. You can achieve this with the following code:

try { tracker.waitForAll(); }
catch (InterruptedException e) {}
Example 7-7 shows the full source code of the image display program. This concludes our introduction to Java graphics programming. For more advanced techniques, you will want to turn to the discussion about 2D graphics and image manipulation in Volume 2.
Example 7-7
 1. import java.awt.*;
 2. import java.awt.event.*;
 3. import*;
 4. import javax.imageio.*;
 5. import javax.swing.*;
 7. public class ImageTest
 8. {
 9. public static void main(String[] args)
10. {
11. ImageFrame frame = new ImageFrame();
12. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
14. }
15. }
17. /**
18. A frame with an image panel
19. */
20. class ImageFrame extends JFrame
21. {
22. public ImageFrame()
23. {
24. setTitle("ImageTest");
27. // add panel to frame
29. ImagePanel panel = new ImagePanel();
30. Container contentPane = getContentPane();
31. contentPane.add(panel);
32. }
34. public static final int DEFAULT_WIDTH = 300;
35. public static final int DEFAULT_HEIGHT = 200;
36. }
38. /**
39. A panel that displays a tiled image
40. */
41. class ImagePanel extends JPanel
42. {
43. public ImagePanel()
44. {
45. // acquire the image
47. /*
48. image = Toolkit.getDefaultToolkit().getImage
49. ("blue-ball.gif");
50. MediaTracker tracker = new MediaTracker(this);
51. tracker.addImage(image, 0);
52. try { tracker.waitForID(0); }
53. catch (InterruptedException exception) {}
55. */
56. try
57. {
58. image = File("blue-ball.gif"));
59. }
60. catch (IOException exception)
61. {
62. exception.printStackTrace();
63. }
64. }
66. public void paintComponent(Graphics g)
67. {
68. super.paintComponent(g);
70. if (image == null) return;
72. int imageWidth = image.getWidth(this);
73. int imageHeight = image.getHeight(this);
75. // draw the image in the upper-left corner
77. g.drawImage(image, 0, 0, null);
79. // tile the image across the panel
81. for (int i = 0; i * imageWidth <= getWidth(); i++)
82. for (int j = 0; j * imageHeight <= getHeight(); j++)
83. if (i + j > 0)
84. g.copyArea(0, 0, imageWidth, imageHeight,
85. i * imageWidth, j * imageHeight);
86. }
88. private Image image;
89. }

javax.swing.ImageIO 1.4

Java graphics api_icon.gif
  • static BufferedImage read(File f)
  • static BufferedImage read(URL u)

    These methods read an image from the given file or URL.

java.awt.Image 1.0

Java graphics api_icon.gif
  • boolean drawImage(Image img, int x, int y, ImageObserver observer)

    draws a scaled image. Note: This call may return before the image is drawn.



    The image to be drawn



    The x-coordinate of the upper-left corner



    The y-coordinate of the upper-left corner



    The object to notify of the progress of the rendering process (may be null)

  • boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer)

    draws a scaled image. The system scales the image to fit into a region with the given width and height. Note: This call may return before the image is drawn.



    The image to be drawn



    The x-coordinate of the upper-left corner



    The y-coordinate of the upper-left corner



    The desired width of image



    The desired height of image



    The object to notify of the progress of the rendering process (may be null)

  • void copyArea(int x, int y, int width, int height, int dx, int dy)

    copies an area of the screen.



    The x-coordinate of the upper-left corner of the source area



    The y-coordinate of the upper-left corner of the source area



    The width of the source area



    The height of the source area



    The horizontal distance from the source area to the target area



    The vertical distance from the source area to the target area

  • Graphics getGraphics()

    gets a graphics context to draw into this image buffer.

  • void flush()

    releases all resources held by this image object.

java.awt.Graphics 1.0

Java graphics api_icon.gif
  • void dispose()

    disposes of this graphics context and releases operating system resources. You should always dispose of the graphics contexts that you receive from calls to methods such as Image.getGraphics, but not the ones handed to you by paintComponent.

java.awt.Component 1.0

Java graphics api_icon.gif
  • Image createImage(int width, int height)

    creates an off-screen image buffer to be used for double buffering.



    The width of the image



    The height of the image

java.awt.MediaTracker 1.0

Java graphics api_icon.gif

adds an image to the list of images being tracked. When the image is added, the image loading process is started.



The image to be tracked



The identifier used to later refer to this image

  • void waitForID(int id)

    waits until all images with the specified ID are loaded.

  • void waitForAll()

    waits until all images that are being tracked are loaded.

Java ScreenShot