As you have already learned from the Images lesson,
There are a number of common tasks when working with images.
The are two main classes that you must learn about to work with images:
A
The Raster performs the following functions:
Reading/Loading an Image
Image
s are described by a width and a height, measured in pixels, and have a coordinate system that is independent of the drawing surface.There are a number of common tasks when working with images.
- Loading an external GIF, PNG JPEG image format file into Java 2D™'s internal image representation.
- Directly creating a Java 2D image and rendering to it.
- Drawing the contents of a Java 2D image on to a drawing surface.
- Saving the contents of a Java 2D image to an external GIF, PNG, or JPEG image file.
The are two main classes that you must learn about to work with images:
- The
java.awt.Image
class is the superclass that represents graphical images as rectangular arrays of pixels. - The
java.awt.image.BufferedImage
class, which extends theImage
class to allow the application to operate directly with image data (for example, retrieving or setting up the pixel color). Applications can directly construct instances of this class.
BufferedImage
class is a cornerstone of the Java 2D immediate-mode imaging API. It manages the image in memory and provides methods for storing, interpreting, and obtaining pixel data. Since BufferedImage
is a subclass of Image
it can be rendered by the Graphics
and Graphics2D
methods that accept an Image
parameter.A
BufferedImage
is essentially an Image
with an accessible data buffer. It is therefore more efficient to work directly with BufferedImage
. A BufferedImage
has aColorModel and a Raster of image data. The ColorModel provides a color interpretation of the image's pixel data.The Raster performs the following functions:
- Represents the rectangular coordinates of the image
- Maintains image data in memory
- Provides a mechanism for creating multiple subimages from a single image data buffer
- Provides methods for accessing specific pixels within the image
Reading/Loading an image
This section explains how to load an image from an external image format into a Java application using the Image I/O APIDrawing an image
This section teaches how to display images using thedrawImage
method of the Graphics
and Graphics2D
classes.Creating and drawing To an image
This section describes how to create an image and how to use the image itself as a drawing surface.Writing/saving an image
This section explains how to save created images in an appropriate format.Reading/Loading an Image
When you think of digital images, you probably think of sampled image formats such as the JPEG image format used in digital photography, or GIF images commonly used on web pages. All programs that can use these images must first convert them from that external format into an internal format.
Java 2D™ supports loading these external image formats into its
To load an image from a specific file use the following code:
Image I/O recognises the contents of the file as a JPEG format image, and decodes it into a
If the code is running in an applet, then its just as easy to obtain the image from the applet codebase :
The
The following example shows how to use the
In addition to reading from files or URLS, Image I/O can read from other sources, such as an InputStream.
We will explore some of the other capabilities of Image I/O later in the Writing/Saving an Image section.
Java 2D™ supports loading these external image formats into its
BufferedImage
format using its Image I/O API which is in the javax.imageio
package. Image I/O has built-in support for GIF, PNG, JPEG, BMP, and WBMP. Image I/O is also extensible so that developers or administrators can "plug-in" support for additional formats. For example, plug-ins for TIFF and JPEG 2000 are separately available.To load an image from a specific file use the following code:
BufferedImage img = null; try { img = ImageIO.read(new File("strawberry.jpg")); } catch (IOException e) { }
BufferedImage
which can be directly used by Java 2D.LoadImageApp.java
shows how to display this image.If the code is running in an applet, then its just as easy to obtain the image from the applet codebase :
try { URL url = new URL(getCodeBase(), "strawberry.jpg"); img = ImageIO.read(url); } catch (IOException e) { }
getCodeBase
method used in this example returns the URL of the directory containing this applet.The following example shows how to use the
getCodeBase
method to load the strawberry.jpg file.LoadImageApp.java
contains the complete code for this example and this applet requires the strawberry.jpg
image file.In addition to reading from files or URLS, Image I/O can read from other sources, such as an InputStream.
ImageIO.read()
is the most straightforward convenience API for most applications, but the javax.imageio.ImageIO
class provides many more static methods for more advanced usages of the Image I/O API. The collection of methods on this class represent just a subset of the rich set of APIs for discovering information about the images and for controlling the image decoding (reading) process.We will explore some of the other capabilities of Image I/O later in the Writing/Saving an Image section.
Drawing an Image
As you have already learned, the
The
Ghi chú: Đối tượng ImageObserver sẽ override hàm imageUpdate () để quan sát, theo dõi, giám sát thông tin về tình trạng tải ảnh "manually". Đối tượng MediaTracker giám sát việc tải của một hay nhiều image synchronously.
The
The described method addresses only the case where the entire image is to be drawn, mapping image pixels to user space coordinates 1:1. Sometimes applications require to draw a part of the image (a sub-image), or scale the image to cover a particular area of the drawing surface, or transform or filter the image before drawing.
The overloads of the
The
The following code example divides an image into four quadrants and randomly draws each quadrant of the source image into a different quadrant of the destination.
The complete code for this applet is in
This example uses the following code to paint the jumbled
The
The following code shows how the filter action is done by operating on a
The complete example represented in
The
The complete code for this applet is in
Use the drop-down menu to select an image scaling or filtering operation.
Graphics.drawImage
method draws an image at a specific location:boolean Graphics.drawImage(Image img, int x, int y, ImageObserver observer);
x,y
location specifies the position for the top-left of the image. The observer
parameter notifies the application of updates to an image that is loaded asynchronously.Ghi chú: Đối tượng ImageObserver sẽ override hàm imageUpdate () để quan sát, theo dõi, giám sát thông tin về tình trạng tải ảnh "manually". Đối tượng MediaTracker giám sát việc tải của một hay nhiều image synchronously.
The
observer
parameter is not frequently used directly and is not needed for the BufferedImage
class, so it usually is null.The described method addresses only the case where the entire image is to be drawn, mapping image pixels to user space coordinates 1:1. Sometimes applications require to draw a part of the image (a sub-image), or scale the image to cover a particular area of the drawing surface, or transform or filter the image before drawing.
The overloads of the
drawImage()
method perform these operations. For example, the following overload of the drawImage()
method enables you to draw as much of a specified area of the specified image as is currently available, scaling it to fit inside the specified area of the destination drawable surface:boolean Graphics.drawImage(Image img, int dstx1, int dsty1, int dstx2, int dsty2, int srcx1, int srcy1, int srcx2, int srcy2, ImageObserver observer);
src
parameters represent the area of the image to copy and draw. The dst
parameters display the area of the destination to cover by the the source area. Thedstx1, dsty1
coordinates define the location to draw the image. The width and height dimensions on the destination area are calculated by the following expressions:(dstx2-dstx1), (dsty2-dsty1)
. If the dimensions of the source and destinations areas are different, the Java 2D™ API will scale up or scale down, as needed.The following code example divides an image into four quadrants and randomly draws each quadrant of the source image into a different quadrant of the destination.
The complete code for this applet is in
JumbledImageApplet.java
.This example uses the following code to paint the jumbled
duke_skateboard.jpg
image. It iterates over the four sub-images of the source, drawing each in turn into a randomly selected destination quadrant./* divide the image 'bi' into four rectangular * areas and draw each of these areas in to a * different part of the image, so as to jumble * up the image. 'cells' is an array which has * been populated with values which redirect * drawing of one subarea to another subarea. */ int cellWidth = bi.getWidth(null)/2; int cellHeight = bi.getHeight(null)/2; for (int x=0; x<2; x++) { int sx = x*cellWidth; for (int y=0; y<2; y++) { int sy = y*cellHeight; int cell = cells[x*2+y]; int dx = (cell / 2) * cellWidth; int dy = (cell % 2) * cellHeight; g.drawImage(bi, dx, dy, x+cellWidth, dy+cellHeight, sx, sy, sx+cellWidth, sy+cellHeight, null); } }
Filtering Images
In addition to copying and scaling images, the Java 2D API also filter an image. Filtering is drawing or producing a new image by applying an algorithm to the pixels of the source image. Image filters can be applied by using the following method:void Graphics2D.drawImage(BufferedImage img, BufferedImageOp op, int x, int y)
BufferedImageOp
parameter implements the filter. The following applet represents an image drawn on top of text. Drag the slider to show more or less of the text through the image and make the image more or less transparent.BufferedImage
object with an alpha channel and rescales that alpha channel by using theRescaleOp
object. The alpha channel determines the translucency of each pixel. It also specifies the degree to which this image overwrites./* Create an ARGB BufferedImage */ BufferedImage img = ImageIO.read(imageSrc); int w = img.getWidth(null); int h = img.getHeight(null); BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics g = bi.getGraphics(); g.drawImage(img, 0, 0, null); /* * Create a rescale filter op that makes the image * 50% opaque. */ float[] scales = { 1f, 1f, 1f, 0.5f }; float[] offsets = new float[4]; RescaleOp rop = new RescaleOp(scales, offsets, null); /* Draw the image, applying the filter */ g2d.drawImage(bi, rop, 0, 0);
SeeThroughImageApplet.java
includes the code that uses the slider to adjust the transparency from the initial 50%. This example also requires the duke_skateboard.jpg image.The
RescaleOp
object is just one of many filters that can be created. The Java 2D API has several built in filters including the following:ConvolveOp
. Each output pixel is computed from surrounding pixels in the source image. It may be used to blur or sharpen images.AffineTransformOp
. This filter maps pixels in the source to a different position in the destination by applying a transformation on the pixel location.LookupOp
. This filter uses an application supplied lookup table to remap pixel colors.RescaleOp
. This filter multiplies the colors by some factor. Can be used to lighten or darken the image, to increase or reduce its opacity, etc.
The complete code for this applet is in
ImageDrawingApplet.java
and this applet requires the bld.jpg image.Use the drop-down menu to select an image scaling or filtering operation.
Creating and Drawing to an Image
We already know how to load an existing image, which was created and stored in your system or in any network location. But, you probably would like also to create an new image as a pixel data buffer.
In this case, you can create a
As was already mentioned in the previous lessons, we can render images not only on screen. An images itself can be considered as a drawing surface. You can use a
Another interesting use of offscreen images is an automaticdouble buffering. This feature allows to avoid flicker in animated images by drawing an image to a back buffer and then copying that buffer onto the screen instead of drawing directly to the screen.
Java 2D™ also allows access to hardware acceleration for offscreen images, which can provide the better performance of rendering to and copying from these images. You can get the benefit of this functionality by using the following methods of the
In this case, you can create a
BufferedImage
object manually, using three constructors of this class:- new BufferedImage(width, height, type) - constructs a
BufferedImage
of one of the predefined image types. - new BufferedImage(width, height, type, colorModel) - constructs a
BufferedImage
of one of the predefined image types:TYPE_BYTE_BINARY
orTYPE_BYTE_INDEXED
. new BufferedImage(colorModel, raster, premultiplied, properties)
- constructs a newBufferedImage
with a specifiedColorModel
andRaster
.
Component
class. These methods can analyze the display resolution for the given Component
orGraphicsConfiguration
and create an image of an appropriate type.Component.createImage(width, height)
GraphicsConfiguration.createCompatibleImage(width, height)
GraphicsConfiguration.createCompatibleImage(width, height, transparency)
Image type
, if you need a BufferedImage object instead then you can perform an instanceof
and cast to a BufferedImage
in your code.As was already mentioned in the previous lessons, we can render images not only on screen. An images itself can be considered as a drawing surface. You can use a
createGraphics()
method of the BufferedImage
class for this purpose:... BufferedImage off_Image = new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = off_Image.createGraphics();
Java 2D™ also allows access to hardware acceleration for offscreen images, which can provide the better performance of rendering to and copying from these images. You can get the benefit of this functionality by using the following methods of the
Image
class:- The
getCapabilities
method allows you to determine whether the image is currently accelerated. - The
setAccelerationPriority
method lets you set a hint about how important acceleration is for the image. - The
getAccelerationPriority
method gets a hint about the acceleration importance.
Writing/Saving an Image
This lesson started with an explanation for using the
The final stage is saving a
The
Note: The
.
The
The
But the following standard image format plugins : JPEG, PNG, GIF, BMP and WBMP are always be present.
Each image format has its advantages and disadvantages:
For most applications it is sufficient to use one of these standard plugins. They have the advantage of being readily available. The
The returned array of names will include any additional plug-ins that are installed and any of these names may be used as a format name to select an image writer. The following code example is a simple version of a complete image edit/touch up program which uses a revised version of the
In this lesson you have learned just the basics of
javax.imageio
package, to load images from an external image format into Java 2D™'s internal BufferedImage
format. Then it explains how to use the Graphics.drawImage()
to draw that image, with optional filtering.The final stage is saving a
BufferedImage
object into an external image format. This may be an image that was originally loaded by the Image I/O
class from an external image format and perhaps modified using the Java 2D APIs, or it may be one that was created by Java 2D.The
Image I/O
class provides a simple way to save images in a variety of image formats in the following example:static boolean ImageIO.write(RenderedImage im, String formatName, File output) throws IOException
Note: The
BufferedImage
class implements the RenderedImage
interface.The
formatName
parameter selects the image format in which to save the BufferedImage
.try { // retrieve image BufferedImage bi = getMyImage(); File outputfile = new File("saved.png"); ImageIO.write(bi, "png", outputfile); } catch (IOException e) { ... }
ImageIO.write
method calls the code that implements PNG writing a “PNG writer plug-in”. The term plug-in is used since Image I/O
is extensible and can support a wide range of formats.But the following standard image format plugins : JPEG, PNG, GIF, BMP and WBMP are always be present.
Each image format has its advantages and disadvantages:
Format | Plus | Minus |
---|---|---|
GIF | Supports animation, and transparent pixels | Supports only 256 colors and no translucency |
PNG | Better alternative than GIF or JPG for high colour lossless images, supports translucency | Doesn't support animation |
JPG | Great for photographic images | Loss of compression, not good for text, screenshots, or any application where the original image must be preserved exactly |
Image I/O
class provides a way to plug in support for additional formats which can be used, and many such plug-ins exist. If you are interested in what file formats are available to load or save in your system, you may use the getReaderFormatNames
and getWriterFormatNames
methods of the ImageIO
class. These methods return an array of strings listing all of the formats supported in this JRE.String writerNames[] = ImageIO.getWriterFormatNames();
ImageDrawingApplet.java
sample program which can be used as follows :- An image is first loaded via Image I/O
- The user selects a filter from the drop down list and a new updated image is drawn
- The user selects a save format from the drop down list
- Next a file chooser appears and the user selects where to save the image
- The modified image can now be viewed by other desktop applications
SaveImage.java
.In this lesson you have learned just the basics of
Image I/O
, which provides extensive support for writing images, including working directly with an ImageWriter
plug-in to achieve finer control over the encoding process. ImageIO can write multiple images, image metadata, and determine quality vs. size tradeoffs. For more information see Java Image I/O API Guide.
0 comments:
Post a Comment