Resize images in Java, preserving image quality
It shouldn’t be so difficult to do simple image manipulation in java. Resizing images is a frequently-encountered need, often to create thumbnails or to shrink pictures taken from digital cameras to a reasonable display size. But how to create thumbnails in java without sacrificing image quality? Standard library image manipulation is severely lacking in this area.
Luckily, talented java programmers have worked to create better solutions. I’ve thrown together an image utility, building off of the work of others, to expose a few basic image manipulation functions, namely: open (from a file, URL, InputStream or byte array), save to file, soften, resize, and resize to square. This may be useful to your project. Just read the important caveat toward the bottom of this post.
- Download: ImageUtil-1.11.zip
I make no warrantees about this utility. If you like it, a link back to this blog would be more than welcome.
I’ve done a lot of online research looking for a good image resizing solution in java, and I believe Morten Nobel-Jørgensen’s java image scaling library fits that description. Specifically, I chose to use his MultiStepRescaleOp class, which does not have high memory usage. More info here. I also take advantage of an unsharp filter, which is part of this incredible java image filter set.
Loading images is easy with the ImageLoader class. Example:
// load an image from a URL image = ImageLoader.fromUrl("http://example.com/file.gif"); // from a file image = ImageLoader.fromFile("c:\pictures\mypic.jpg"); //from an InputStream image = ImageLoader.fromStream(input); //from a byte array image = ImageLoader.fromBytes(imageBytes); |
The zip file above contains an example usage class, which you can look at and run from the command line like so:
java -classpath ./dist/ImageUtil.jar;./lib/java-image-scaling-0.8.5.jar;./lib/Filters.jar imageUtil.Example http://upload.wikimedia.org/wikipedia/commons/7/74/06._John_in_the_vineyard.jpg
The wikimedia URL is just an image in their public domain category. The imageUtil.Example
class accepts local files as well as URLs as arguments. After executing the above command, the following images are generated. A demonstration of cropping first.
Cropping With Java
Resizing With Java, Varying Quality
Images resized and saved with increasing quality (most evident in the shoulder strap):
(Note that the file sizes range from 11,835 bytes to 55,654 bytes.)
Resizing With Java, Varying Softness
More examples, this time with increasing softness added. The soften method adds a slight blur to improve the look of sharp edges following a resize operation. (Please note, the image just above has zero softness applied.)
The amount of softness you’d like to apply is a judgement call. I find 0.08f to be a good setting.
Squaring Images With Java
Next, the squaring method. Note that the preceding images retained their original aspect ratio. Often, you’d like thumbnails or picture icons to be square. The method getResizedToSquare(int width, double cropEdgesPct)
does this by cropping any excess width or height to form a square, then resizing to your desired size. The second argument, called cropEdgesPct
, specifies how much, if any, additional cropping to perform around the entire border of the square. This results in a zoom effect. It is useful because when you resize images down thumbnails, a lot of detail is lost. If we assume that the main subject of the picture is relatively centered, a zoom effect will preserve as much main subject detail as possible.
Here are some examples, with increasing degrees of edge cropping:
Next, let’s look at some little square thumbnails. Resizing images down to such a small size tends to be problematic in terms of image detail. Here are a few examples created with various settings.
Note that applying a little edge cropping brings greater focus to the face, which in this case is within the center area of the squared image. Also note the degradation when specifying a lower quality. Be aware that higher quality images require greater disk space. The center image has twice the file size as the right-most image.
* Important caveat with this utility: the writeToJPG
method uses Sun’s JPEGCodec
class, which is available in Sun JVMs only. The reason for using this class is that it is able to produce higher-quality JPG files than the alternative, the ImageIO.write
method. The latter does not allow you to set the desired image quality. Here is a comparison of two resized images, one using JPEGCodec
and the other using ImageIO
to write the file:
The output from JPEGCodec
is better. Again, compare the shoulder straps. The downside is that using the JPEGCodec
class is not portable across different JREs.
If this was at all helpful, I would greatly appreciate a link! If you have a blog on programming or web development, let’s trade links.
Thanks a ton for this! I have your little library up and running like a charm. I’m using it for a live stop-motion animation performance to resize images from my camera on the fly and project them in a sequence.
On a side note, a friend of mine just started a company called TipTheWeb that provides a mechanism for making small donations for web content. It’s in Beta now. For fun I just tried to use it to send you $10 as a show of gratitude. I’d be curious to know what kind of notification you get and/or how it reaches you.
Cheers, and thanks again.
-mike
Wow! after lots of searching I found this and got it working within 5 minutes! GREAT WORK!!
thanks a lot
wow. you are genius~!!.
Very Nice! Congrats
Now you should think about creating a maven project on it and add it to a public repository! 😉
cheers
Very effective and easy to implement
Thanks for the nice package. The only problem I have is with PNG images with transparency. If I use writeToJPG it produces black boxes. It is well known problem. I solved it with substitution of transparent pixels with white colour.
Here is the working solution:
http://stackoverflow.com/questions/464825/converting-transparent-gif-png-to-jpeg-using-java
Thank you! Your image library was the only one that worked to satisfaction. However, I understand that it will only work with the Sun (RIP) SDK. I can live with that.
Thank you for sharing.
Wim.
thanks a lot!
I add this function to you Image.java.
/**
*
* @param stream
* @param type
* @throws IOException
*/
public void writeToStream(OutputStream stream, String type) throws IOException {
if (stream == null) {
throw new IllegalArgumentException(“stream argument was null”);
}
ImageIO.write(img, type, stream);
}
Nice, I’m using it and it’s working fine.
After long and unsuccessful search for a program that make batch resize of images (the way I want), I decided to search for some Java code and I found this. Thanks.
*I’m thinking about to distribute the little app I’m doing…
Works great! And fast too- thank you!!
Dear,
Your lib is definately aswesome. However, please show me how could I rescale the image on the UI (such like facebook).
Thank you so much.
can i alter image dpi with this tool?
Thanx , very nice Work
good library, thank you.