Saturday, June 22, 2013

Java Image Scaling awt.Graphics2D vs. Scalr

The Target was very simple I had the last days. You will get a big image and have to scale it low for the web.
At the beginning I googled a little bit and found out the imagemagic is the best solution for quality scaling. I think it is, because it has a very big libary of commands and supportet image formats.Because I like to scale the images during a gwt server call I was not so happy to install a complete software on our hosting machines. So I checked other solution to Scale this image to a [x<=200 and y<=200] format. The first approach was using java awt image scaling stuff:
Unit Test Code


BufferedImage bsrc = ImageIO.read(new File(src));
for (String name : ImageIO.getWriterFormatNames()) {
System.out.println(name);
}
System.out.println("original size_" + bsrc.getWidth() + " height:" + bsrc.getHeight());
double scaleWith = (double) width / bsrc.getWidth();
double scaleheigth = (double) height / bsrc.getHeight();
double scalefactor = scaleheigth > scaleWith ? scaleWith : scaleheigth;
double finalWith = bsrc.getWidth() * scalefactor;
double finalHeight = bsrc.getHeight() * scalefactor;
System.out.println("Dest img size:" + finalWith + " height:" + finalHeight);
BufferedImage bdest = new BufferedImage((int) finalWith, (int) finalHeight, bsrc.getType());
Graphics2D g = bdest.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);
AffineTransform at = AffineTransform.getScaleInstance(scalefactor, scalefactor);
g.drawRenderedImage(bsrc, at);
ImageIO.write(bdest, "JPG", new File(dest));

This was the result
the-hobbit-an-unexpected-journey-dvd-cover-68-out
For a Programmer it was ok. But not for an Artist, or people which don’t have a red-green handicap :-)
So I tried out imgscalr
here my Unit Test code:
public static void scaleNEW(final String src, final int width, final int height, final String dest) throws IOException {
BufferedImage bsrc = ImageIO.read(new File(src));
String extension = src.substring(src.lastIndexOf(".") + 1, src.length());
System.out.println("extension is:" + extension);
for (String name : ImageIO.getWriterFormatNames()) {
System.out.println(name);
}
System.out.println("original size_" + bsrc.getWidth() + " height:" + bsrc.getHeight());
double scaleWith = (double) width / bsrc.getWidth();
double scaleheigth = (double) height / bsrc.getHeight();
double scalefactor = scaleheigth > scaleWith ? scaleWith : scaleheigth;
double finalWith = bsrc.getWidth() * scalefactor;
double finalHeight = bsrc.getHeight() * scalefactor;
BufferedImage thumbnail = Scalr.resize(bsrc, (int) finalWith, (int) finalHeight, Scalr.OP_ANTIALIAS);
ImageIO.write(thumbnail, extension, new File(dest));
}

I was very supprised, that the api was so easy to use…. Here you see the result:
the-hobbit-an-unexpected-journey-dvd-cover-68-out2