Java image resizer servlet

I’m working on a photo gallery application running on Java 6 using Tomcat 6, JQuery for the client side, and images and xml generated from Picasa. I needed several sizes of images for thumbnails and animations and I wasn’t about to create multiple image sizes with Fireworks (I’m a lazy developer). Doing what every lazy developer does, I search Google for an image resize solution that would run on the application server and give me the sizes that I needed and take the manual work out of the equation. I found several PHP examples and disjointed Java examples, but no complete solutions. So, unfortunately I had to do some work to put something together.

Down to brass tax, here’s the image resizer servlet code: (copy paste, use as you please)

package com.photo.gallery;

import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ImageResizer extends HttpServlet {
	/**
	 * Servlet resizes an image located in a directory in a web project ex.
	 * /image?root=/albums&file=/thumbs/imagename.jpg&width=270&height=100 ex.
	 * /image?file=/thumbs/imagename.jpg&width=270 (default root, calculated
	 * height)
	 */
	private static final long serialVersionUID = -8285774993751841288L;

	public void doGet(HttpServletRequest request, HttpServletResponse response) {
		// Optional: Only supports output of jpg and png, defaults to png if not
		// specified
		String imageOutput = getParam(request, "output", "png");
		// Optional: Folder in web app where images are located, defaults to
		// albums if not specified
		String imageRoot = getParam(request, "root", "/albums");
		// Required: Path from root to image, including filename
		String imageFile = getParam(request, "file", "/Album1/image1.jpg");
		// Required: Width image should be resized to
		int width = Integer.parseInt(getParam(request, "width", "250"));
		// Optional: If specified used, otherwise proportions are calculated
		int height = Integer.parseInt(getParam(request, "width", "0"));

		// Set the mime type of the image
		if ("png".equals(imageOutput))
			response.setContentType("image/png");
		else
			response.setContentType("image/jpeg");

		// Server Location of the image
		String imageLoc = request.getSession().getServletContext().getRealPath(imageRoot) + imageFile;

		try {
			// Read the original image from the Server Location
			BufferedImage bufferedImage = ImageIO.read(new File(imageLoc));
			// Calculate the new Height if not specified
			int calcHeight = height > 0 ? height : (width * bufferedImage.getHeight() / bufferedImage.getWidth());
			// Write the image
			ImageIO.write(createResizedCopy(bufferedImage, width, calcHeight), imageOutput, response.getOutputStream());
		} catch (Exception e) {
			log("Problem with image: " + imageLoc + e);
		}
	}

	BufferedImage createResizedCopy(Image originalImage, int scaledWidth, int scaledHeight) {
		BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_RGB);
		Graphics2D g = scaledBI.createGraphics();
		g.setComposite(AlphaComposite.Src);
		g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null);
		g.dispose();
		return scaledBI;
	}

	// Check the param if it's not present return the default
	private String getParam(HttpServletRequest request, String param, String def) {
		String parameter = request.getParameter(param);
		if (parameter == null || "".equals(parameter)) {
			return def;
		} else {
			return parameter;
		}
	}
}

Here’s the web.xml servlet definition and mapping:

  
  	image
  	com.photo.gallery.ImageResizer
  	1
  
  
    image
    /image
  

Images in html would look something like this:

  
  

Hopefully I’ve contributed something useful to another lazy developer and this solution works. I have no idea how scalable this solution is, nor do I care, it’s just for a photo album where I needed cleanly resized images. More articles to come later on the album such as customizing and parsing xml from Picasa and a Java-based Ajax photo gallery using JQuery UI, don’t hold your breath though, remember I’m lazy.

14 Responses to “Java image resizer servlet”

  1. Pretty cool. I would have separated the image resizing code from the servlet but, it would make posting on a web site a bit more of a pain. Anyway, your code is definitely clear enough to modify.
    Kudo :-)

    Though not for the server, I did something similar with a bash script for my personal images (which are then loaded up on the server).
    http://willcode4beer.com/tips.jsp?set=photoscript

    It requires the ImageMagick libs be installed but, most Linux distros have ‘em by default anyway.

  2. Please have a look at SwingX lib for high quality image scaling scaling (http://www.swinglabs.org) and in particular this method:

    GraphicsUtilities.createThumbnail(BufferedImage image, int newSize)

  3. Cool, thanks for the feedback. I used a servlet since I’m working on a dynamic photo gallery and need several different sized images for animations and such and wanted the least painful way to get any size at any point time from the original image. This just worked well for this application.

  4. Java image resizer servlet

    [...]A servlet for resizing images in a web application using the ImageIO api.[...]

  5. Hi, Rob

    I tried the SwingX lib, the image quality gets improved. But for some reason the created image has a smaller image inside the bigger one.

    It is strange.
    Thx

  6. Hi, Bob

    GraphicsUtilities.createThumbnail created duplicate images, but GraphicsUtilities.createThumbnailFast works perfect and quality is good.

    Thx
    Fei

  7. Image resizing is an expensive task. Make some stress tests to your application and you will see the poor performance.
    Anyway your solution could be easily tuned up by making good usage of http response headers and even including an intermediate cache

  8. You’re absolutely right Nacho! I’ve seen the performance implications of resizing on the fly. Good suggestions, it’s definitely not viable with a large number of requests in this example. My original implementation of this servlet was to resize and compress files on upload for content management, I had issue with users that loved to upload 2MB photos for display on their websites and the Java API compressed nicely without too much quality loss.

  9. Hi webguy

    My server still runs Java 1.4.3 :( Will this servlet run on it?

    If not, what parts won’t and is there a work-around?

    Any advice would be much appreciated.

  10. Lyndon, I think you’re good to go, all of these API’s were introduced in the 1.4 JDK. Just be aware this is probably not a scalable solution, some sort of disk caching would probably be needed in a high-scale environment since resizing images on the fly is a CPU intensive process.

  11. Thanks,
    Nice example

  12. thanks man

  13. This is very cool. I would like to use it for allowing clietns to upload images to the server but I want them to resize the images on their end first.

Leave a Reply

You can use these XHTML tags: <a href="" title=""> <abbr title=""> <acronym title=""> <blockquote cite=""> <code> <em> <strong>