Here is the original image: http://rank.my/public/images/uploaded/orig-4193395691714613396.png
And here it is scaled down to 300x225:
http://rank.my/public/images/uploaded/norm-4193395691714613396.png
And here it is scaled down to 150x112:
http://rank.my/public/images/uploaded/small-4193395691714613396.png
As you can see, 300x225 looks pretty bad, and 150x112 looks awful. Here is the code I'm using to scale down the image:
private static BufferedImage createResizedCopy(final BufferedImage source, final int destWidth,
final int destHeight) {
final BufferedImage resized = new BufferedImage(destWidth, destHeight, source.getType());
final Graphics2D bg = resized.createGraphics();
bg.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
bg.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
bg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
final float sx = (float) destWidth / source.getWidth();
final float sy = (float) destHeight / source.getHeight();
bg.scale(sx, sy);
bg.drawImage(source, 0, 0, null);
bg.dispose();
return resized;
}
What am I doing wrong here? The image scaling doesn't have to be especially fast, quality is definitely a priority over speed. Am I using the wrong technique?
When scaling, the resolution is not adjusted to best suit the new size, rather the pixels are stretched and can appear pixelated. The most common side effect of scaling an image larger than its original dimensions is that the image may appear to be very fuzzy or pixelated.
getScaledInstance() You can resize an image in Java using the getScaledInstance() function, available in the Java Image class. We'll use the BufferedImage class that extends the basic Image class.
Image class in Java is an abstract superclass for all the other classes used for graphical image representation.
There are three ways to fix the downscaling problem. First is to do it in multiple steps, with no more than a 75% reduction in each step. The second is to blur the image before resizing; the more it shrinks, the more you'll have to blur. The third way is to use a method that filters using more than the 2x2 to 4x4 pixel blocks used by a naive bilinear or bicubic interpolation method. As the shrink factor grows larger, so should the pixel block used by the filter, otherwise you get aliasing artifacts as you've seen here.
I've never used these libraries so I feel unqualified to answer, but I can't help but pass along these links I found that I think may be useful. Hopefully this will help.
http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
http://www.componenthouse.com/article-20
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With