Site Network: Personal | Professional | Photography

Technical Blog

This blog will contain content related to Java, Seam, Security, my sites and projects, as well as other technical subjects I am interested in.

Comments and questions are welcome!

How To Resize Uploaded Images Using Java

I am building a Seam application which need to support users uploading images, and then the site displaying them. I wanted to resize big images into something reasonable (say 1024 or 800 px wide) and generate a thumbnail, and I also wanted to standardize on a single image format just to make things easy and consistent.

So I needed method that would take an uploaded image as a byte array (byte[]) and would resize the image (if needed) and convert it to a fixed quality JPG, and give me back a byte array to store in the database. I am using Seam, so I get a handy byte array, but this method should work fine for non-Seam applications as well.

 
    /**
     * This method takes in an image as a byte array (currently supports GIF, JPG, PNG and possibly other formats) and
     * resizes it to have a width no greater than the pMaxWidth parameter in pixels. It converts the image to a standard
     * quality JPG and returns the byte array of that JPG image.
     *
     * @param pImageData
     *                the image data.
     * @param pMaxWidth
     *                the max width in pixels, 0 means do not scale.
     * @return the resized JPG image.
     * @throws IOException
     *                 if the iamge could not be manipulated correctly.
     */
    public byte[] resizeImageAsJPG(byte[] pImageData, int pMaxWidth) throws IOException {
	// Create an ImageIcon from the image data
	ImageIcon imageIcon = new ImageIcon(pImageData);
	int width = imageIcon.getIconWidth();
	int height = imageIcon.getIconHeight();
	mLog.info("imageIcon width: #0  height: #1", width, height);
	// If the image is larger than the max width, we need to resize it
	if (pMaxWidth > 0 && width > pMaxWidth) {
	    // Determine the shrink ratio
	    double ratio = (double) pMaxWidth / imageIcon.getIconWidth();
	    mLog.info("resize ratio: #0", ratio);
	    height = (int) (imageIcon.getIconHeight() * ratio);
	    width = pMaxWidth;
	    mLog.info("imageIcon post scale width: #0  height: #1", width, height);
	}
	// Create a new empty image buffer to "draw" the resized image into
	BufferedImage bufferedResizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
	// Create a Graphics object to do the "drawing"
	Graphics2D g2d = bufferedResizedImage.createGraphics();
	g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
	// Draw the resized image
	g2d.drawImage(imageIcon.getImage(), 0, 0, width, height, null);
	g2d.dispose();
	// Now our buffered image is ready
	// Encode it as a JPEG
	ByteArrayOutputStream encoderOutputStream = new ByteArrayOutputStream();
	JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(encoderOutputStream);
	encoder.encode(bufferedResizedImage);
	byte[] resizedImageByteArray = encoderOutputStream.toByteArray();
	return resizedImageByteArray;
    }
 

In my application I call this method twice, once to convert the uploaded image into a limited size JPG, and then once again to generate a much smaller thumbnail. I store both of these in the database and will use caching at the Apache layer to ensure performance.

6 Responses to “How To Resize Uploaded Images Using Java”

  1. Matt Sidesinger Says:

    I have gotten better quality in the past when creating the BufferedImage with the following logic to perform the resize:

    import java.awt.RenderingHints;
    import javax.media.jai.RenderedOp;
    import javax.media.jai.operator.SubsampleAverageDescriptor;
    ...
    RenderingHints hints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    RenderedOp resizeOp = SubsampleAverageDescriptor.create(image, scale, scale, hints);
    BufferedImage bufferedResizedImage = resizeOp.getAsBufferedImage();
    
  2. Devon Says:

    Thank Matt, I will give that a try!

    – edit:

    How do you convert an incoming ImageIcon or Image to a RenderedImage needed for the SubsampleAverageDescriptor.create() call? I can see how to do it if I go through the process of painting it full size into a another BufferedImage, but that seems like it would make this call at least 2X as computationally expensive..

  3. Devon Says:

    Or did you mean just use the rendering hints you have there, and leave the rest of the code alone? Does the SubsampleAverageDescriptor provide superior resizing?

  4. Matt Sidesinger Says:

    Sorry about the not including anything about how to get a RenderedImage as I am not using an ImageIcon. A BufferedImage implements RenderedImage. You can creaete a BufferedImage from a byte[] by creating a ByteArrayInputStream and passing it to ImageIO.read().

    This post shows visual results of resizing with and without using SubsampleAverage: https://www.i-proving.ca/space/Technologies/Java+Advanced+Imaging

    I was experiencing similar results where edges were not smooth.

  5. How To Resize Uploaded Images Using Java - Better Way | Devon Hillard Tech Blog Says:

    […] How To Resize Uploaded Images Using Java […]

  6. vpetreski Says:

    http://www.comesolvego.com/2008/04/29/resize-images-with-java-high-quality-and-working-solution/

Leave a Reply