I have a requirement where in i have to scale all input images to a given size dynamically. I have been searching over web to do this and found really hard time to settle on a simple solution. Here is the simple solution without need of any Library
To read this image, we can use the ImageIO class:
BufferedImage image = ImageIO.read(new File("c:\picture.jpg"));
First Attempt
Now we have to find a way to resize this image. Our first attempt is to use the drawImage() method of the Graphics interface:
private static BufferedImage resize(BufferedImage image, int width, int height) {
With this method, we can create a 24×24 avatar by calling:
BufferedImage resizedImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(image, 0, 0, width, height, null);
g.dispose();
return resizedImage;
}
Image resized = resize(image, 24, 24);
The last step is to save the image so that we can see the results. The ImageIO class can do this job:
ImageIO.write(resized, “png”, new File(“c:\picture1.png”));
Note that the second parameter is the format of the saved image. I used “png” because it is simpler. If you want to save it as JPG, you will have to use the JPEGImageEncoder class (and the result is the same, trust me).
The result of this method is a low-quality image:
Second Attempt
We noticed that the main problem of the resize() method above is the fact that it doesn’t have anti-aliasing. So we could use the Rendering Hints of the Java2D API as an attempt to solve that problem:
private static BufferedImage resize(BufferedImage image, int width, int height) {
int type = image.getType() == 0? BufferedImage.TYPE_INT_ARGB : image.getType();
BufferedImage resizedImage = new BufferedImage(width, height, type);
Graphics2D g = resizedImage.createGraphics();
g.setComposite(AlphaComposite.Src);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(image, 0, 0, width, height, null);
g.dispose();
return resizedImage;
}
The Trick
Now I will explain how to improve the quality of this image. Basically, the trick is to blur the image before resizing. The code that blurs an image in java is:
public static BufferedImage blurImage(BufferedImage image) {
float ninth = 1.0f/9.0f;
float[] blurKernel = {
ninth, ninth, ninth,
ninth, ninth, ninth,
ninth, ninth, ninth
};
Map map = new HashMap();
map.put(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
map.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
map.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
RenderingHints hints = new RenderingHints(map);
BufferedImageOp op = new ConvolveOp(new Kernel(3, 3, blurKernel), ConvolveOp.EDGE_NO_OP, hints);
return op.filter(image, null);
}
Since the original image is in the JPG format, we can’t blur it directly. We have to create a compatible image first:
private static BufferedImage createCompatibleImage(BufferedImage image) {
GraphicsConfiguration gc = BufferedImageGraphicsConfig.getConfig(image);
int w = image.getWidth();
int h = image.getHeight();
BufferedImage result = gc.createCompatibleImage(w, h, Transparency.TRANSLUCENT);
Graphics2D g2 = result.createGraphics();
g2.drawRenderedImage(image, null);
g2.dispose();
return result;
}
Blurring the image before resizing it isn’t the only trick. You have to do this when the width or height of the image is 100px. Since small avatars are usually a square (width = height), you can resize it to 100×100, call the blur() method and resize again to 24×24:
private static BufferedImage resizeTrick(BufferedImage image, int width, int height) {
image = createCompatibleImage(image);
image = resize(image, 100, 100);
image = blurImage(image);
image = resize(image, width, height);
return image;
}
(the resize() method is the one described in the second attempt)
Here is final Code
/**
*
*/
package com.linkwithweb.image;import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;import javax.imageio.ImageIO;
import sun.awt.image.BufferedImageGraphicsConfig;
/**
* High-Quality Image Resize with Java
*
* Following two articles are source for this program
*
* http://www.componenthouse.com/article-20
* http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
*
* @author ashwink
*/
public class ImageResizer{public static void main(String[] args) {
try {
/*
* BufferedImage image = ImageIO
* .read(new File(
* “C:\\setup\\Apache\\Apache2.2\\htdocs\\northalley\\Registration_files\\menu_logo.png”));
*/BufferedImage image = ImageIO
.read(new File(
“C:\\Documents and Settings\\kumara\\Desktop\\SiriFinalDocs\\SiriWork\\SWScan0000200008.jpg”));ImageIO.write(
resizeTrick(image, image.getWidth(), image.getHeight()),
“png”,
new File(
“C:\\setup\\Apache\\Apache2.2\\htdocs\\northalley\\Registration_files\\test.png”));
} catch (IOException e) {
e.printStackTrace();
}
}private static BufferedImage resize(BufferedImage image, int width,
int height) {
int type = image.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : image
.getType();
BufferedImage resizedImage = new BufferedImage(width, height, type);
Graphics2D g = resizedImage.createGraphics();
g.setComposite(AlphaComposite.Src);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(image, 0, 0, width, height, null);
g.dispose();
return resizedImage;
}private static BufferedImage resizeTrick(BufferedImage image, int width,
int height) {
image = createCompatibleImage(image);
image = resize(image, width, height);/**
* If you want to blur image
*/
// image = blurImage(image);
return resize(image, width, height);
}public static BufferedImage blurImage(BufferedImage image) {
float ninth = 1.0f / 9.0f;
float[] blurKernel = { ninth, ninth, ninth, ninth, ninth, ninth, ninth,
ninth, ninth };Map map = new HashMap();
map.put(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
map.put(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
map.put(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
RenderingHints hints = new RenderingHints(map);
BufferedImageOp op = new ConvolveOp(new Kernel(3, 3, blurKernel),
ConvolveOp.EDGE_NO_OP, hints);
return op.filter(image, null);
}private static BufferedImage createCompatibleImage(BufferedImage image) {
GraphicsConfiguration gc = BufferedImageGraphicsConfig.getConfig(image);
int w = image.getWidth();
int h = image.getHeight();
BufferedImage result = gc.createCompatibleImage(w, h,
Transparency.TRANSLUCENT);
Graphics2D g2 = result.createGraphics();
g2.drawRenderedImage(image, null);
g2.dispose();
return result;
}}