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.
March 13th, 2008 at 7:36 am
I have gotten better quality in the past when creating the BufferedImage with the following logic to perform the resize:
March 13th, 2008 at 8:20 am
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..
March 13th, 2008 at 8:43 am
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?
March 13th, 2008 at 12:08 pm
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.
March 13th, 2008 at 5:23 pm
[…] How To Resize Uploaded Images Using Java […]
April 29th, 2008 at 12:37 pm
http://www.comesolvego.com/2008/04/29/resize-images-with-java-high-quality-and-working-solution/