Sunday 28 August 2011

Resizing images smoothly in Java




Attempting to downsample (interpolate) an image containing text and other sharp edges can lead to some messy results.

Bicubic downsampling doesn't seem to cut it in this case:


private BufferedImage createResizedCopyBicubic(BufferedImage source, int destWidth, int destHeight) {
BufferedImage bicubic = new BufferedImage(destWidth, destHeight, source.getType());
Graphics2D bg = bicubic.createGraphics();
bg.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
float sx = (float)destWidth / source.getWidth();
float sy = (float)destHeight / source.getHeight();
bg.scale(sx, sy);
bg.drawImage(source, 0, 0, null);
bg.dispose();
return bicubic;
}


Instead making use of the Java Advanced Imaging APIs and using average downsample yields a much nicer result:


private BufferedImage createResizedCopyAveraging(BufferedImage source, double scaleX, double scaleY) {
RenderingHints hints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
RenderedOp resizeOp = SubsampleAverageDescriptor.create(source, scaleX, scaleY, hints);
return resizeOp.getAsBufferedImage();
}