In particular, when images are displayed on the screen, the Image data is converted to a format which matches the color capabilities of the screen. The original image data is not stored persistently, only the converted screen data is stored by the screen representations. If the data for the image is needed for some other purpose (such as filtering the data for a new image), then the raw data has to be reloaded from the original source.
Another drawback of storing a separate image representation for each size drawn is the amount of memory consumed. The strategy of keeping a separate representation for each size drawn is meant to optimize rendering speed since the data is all ready to be copied to the screen byte for byte. This strategy ends up backfiring since the speed gain by having the scaled size precalculated often is more than offset by the pain and inconvenience of having to wait while the scaled variant is loaded and converted, especially if the image data needs to be reloaded over a slow network. Also, if the image is being drawn at many different sizes which will never be repeated the memory used to cache the scaled representations is wasted.
In short, there is no programmer control over whether or not the scaled version of the image is cached for subsequent rendering and whether or not the image scaling is done immediately or in the background.
Another issue which has bothered developers is that there is no way to create a new object which represents a scaled view of an existing image. An Image object can be scaled by supplying new width and height parameters to the drawImage call, but there is no way to encapsulate that information into an Image object so that by passing around that Image object, the desired size image will be drawn.
There are two primary drawbacks of this change.
As it turns out, the first problem is much less dramatic than was originally feared. In the past couple of years processors have become very fast especially in comparison to the speeds of memory systems. As a result image scaling performance is mostly limited by memory access speed and the calculations necessary to determine which is the next pixel to copy to the screen for the particular scaling desired are not very noticeable compared to the work of moving the data to the screen.
The quality issue could have been a major problem. With the 8-bit color conversion code used in JDK implementations prior to 1.1 images degraded dramatically if they were scaled after dithering. Fortunately, new color conversion algorithms have been developed for 1.1 which increase the quality of the resulting dithered image so much that the results of scaling the dithered representations are typically as good, if not better than the results of the 1.0.2 images which were dithered after scaling.
Still, even though the implementation of image scaling was beefed up in
1.1 enough to make render-time on-the-fly scaling possible, there will
be cases where the programmer wants every possible measure taken to
improve the quality of the scaled image.
To allow the programmer to choose when explicit scaling should be performed
up front instead of at rendering time, two new filter classes will be
available and a new convenience method will be added to the AWT Image
class in 1.1.
These same APIs can be used by programmers to create a new Image object
representing a scaled version of that image encapsulated into its own
Image object.
The new image scaling classes are:
java.awt.image.ReplicateScaleFilter
java.awt.image.AreaAveragingScaleFilter
The new method in the Image class is:
getScaledInstance(int width, int height, int hints)
The hints parameter controls what kind of algorithm is used to scale the
image.
There are hints which refer to specific algorithms to be used and there
are more abstract hints which indicate whether or not to optimize the
operation for speed or quality.
The current set of legal values for the hints parameter are:
Image.SCALE_DEFAULT
Image.SCALE_FAST
Image.SCALE_SMOOTH
Image.SCALE_REPLICATE
Image.SCALE_AREA_AVERAGING
import java.awt.*;
import java.applet.*;
public class ImgScaleExample extends Applet {
Image img, img2;
public void init() {
img = getImage(getDocumentBase(), "foo.gif");
img2 = img.getScaledInstance(100, 100, Image.SCALE_DEFAULT);
}
public void paint(Graphics g) {
// Draw the full size image
g.drawImage(img, 0, 0, this);
// Draw the scaled version of the image
g.drawImage(img2, 10, 10, this);
// Now draw a scaled version of the scaled image
g.drawImage(img2, 110, 10, 50, 50, this);
}
}