When scaling up a bitmap image, more data is needed than is provided by the original image. So algorithms are used to guess what the extra pixels should be, based on the colours of the other pixels nearby.
With Java there are 3 built in options for scaling images using interpolation. When choosing a scaling algorithm there is always a trade off between speed and quality. Below is a short comparison of the three available options in AffineTransformOp:
1. Bicubic Interpolation
Bicubic interpolation is the slowest of the three options, but produces the highest quality. It takes 16 pixels into account (bilinear interpolation only takes 4). Because it uses more data the scaled images are better quality and the surface of the scaled image is smoother.
2. Bilinear Interpolation
With bilinear interpolation, the interpolation is performed first in one direction and then in the opposite direction. It is faster than bicubic interpolation but is more likely to result in a loss of quality.
3. Nearest Neighbour Interpolation
Nearest neighbour is the simplest of the three algorithms and is often used in real-time 3D rendering. It works by selecting the nearest value and ignoring other values. As with bilinear interpolation, it is faster than bicubic but it produces the worst quality results of the three options.
How to use scale images with Java
The easiest way to scale an image in Java using one of these three algorithms is to use the AffineTransformOp class. You can load an image into Java as a BufferedImage and then apply the scaling operation to generate a new BufferedImage. You can use Java’s ImageIO or a third-party image library such as JDeli to load and save the image. We have used JDeli in our example below because it works with all JPEG files and the widest range of filetypes.
For example if I wanted to double the size of an image using Bicubic interpolation, I could use the following code:
BufferedImage image = JDeli.read(new File("C:\\path\\to\\image.jpg"));
final int w = image.getWidth();
final int h = image.getHeight();
BufferedImage scaledImage = new BufferedImage((w * 2),(h * 2), BufferedImage.TYPE_INT_ARGB);
final AffineTransform at = AffineTransform.getScaleInstance(2.0, 2.0);
final AffineTransformOp ato = new AffineTransformOp(at, AffineTransformOp.TYPE_BICUBIC);
scaledImage = ato.filter(image, scaledImage);
JDeli.write(scaledImage, JDeli.OutputFormat.PNG, new File("C:\\path\\to\\scaledImage.jpg"));
Other scaling algorithms
There are other algorithms that can be used to scale images, which are not supported by Java. For example with JDeli, our Java Image Library, you can use lanczos resampling to downscale images (further information and examples available here) or super-resolution scaling to scale up images and keep a good level of visual quality (further information and example available here). If you want to give it a try you can get the free trial here.
Some other possible image scaling algorithms include:
- Box Sampling
- Edge-directed interpolation
Are there any scaling algorithms you would like us to add to JDeli? Let us know in the comments.