Java Notes
Images - BufferedImage
The java.awt.image.BufferedImage
class is used
to create images in memory.
You might
want to do this for unchanging images that take a long time to create.
You can create them once, then display them
repeatedly, instead of recomputing them each time.
To create a BufferedImage
You can create a new BufferedImage using either the characteristics of an existing component (eg, a JPanel), or by using a BufferedImage constructor, in which case you need to (or can) specify additional parameters like the color model and image type. Specifying an image type allows, for example, an alpha channel for transparency, but rendering images which do not use the the native image model can be slower. This description only considers creating a BufferedImage object from another component.
Some properties components are not known during the
initial construction of the interface. For example, the size of
a JPanel may change during layout. Therefore, a common technique is
to delay the construction of a BufferedImage based on a JPanel
until later. This can be done at the beginning of the
paintComponent
method.
The example below tests for the uninitialized value (null).
Assume we want to make the bufferer image the same size
as the panel we are that are drawing. This buffered image
has a grid on it, which will be used as the background
for all other drawing. We only have to compute the grid one time.
import java.awt.image.*; . . . class Painting extends JPanel { . . . BufferedImage grid; // declare the image . . . public void paintComponent(Graphics g) { super.paintComponent(g); // paint background Graphics2D g2 = (Graphics2D)g; // we need a Graphics2D context if (grid == null) { // Compute the grid only one time int w = this.getWidth(); int h = this.getHeight(); grid = (BufferedImage)(this.createImage(w,h)); Graphics2D gc = grid.createGraphics(); for (int x=0; x<w; x+=10) {gc.drawLine(x, 0, x, h);} for (int y=0; y<h; y+=10) {gc.drawLine(0, y, w, y);} } // Draw the grid from the precomputed image g2.drawImage(grid, null, 0, 0); . . . // draw remaining, dynamic, image
To Draw on a BufferedImage
To draw on anything, you need a Graphics or Graphics2D drawing context. You can get a graphics context from an image like this:
Graphics2D gp = myImage.createGraphics(); gp.drawOval(10,10,40,100); . . .
To draw the BufferedImage onto another graphics context
You usually use a BufferedImage as part of some other drawing that
you are producing.
A BufferedImage can be drawn using the drawImage
method.
Note that drawImage(...)
is only defined in the Graphics2D
class, but casting the Graphics object to Graphics2D is simple and fast.
There are many drawImage
methods;
some allow you to rescale the image to fit into a specified
area, or to apply a filter. If you just want to copy
the image directly onto graphics context g2 with with no operations (null) and
starting at (100, 200), you can do this in a paintComponent method:
// Draw myImage on the current graphics context Graphics2D g2 = (Graphics2D)g; g2.drawImage(myImage, null, 100, 200);
Example: Example - Buffered Analog Clock uses an image to compute the clock face only one time, and then reuse that image every time for the background and draw only the hands dynamically.