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.