Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to improve the performance of g.drawImage() method for resizing images

I have an application where users are able to upload pictures in albums but naturally the uploaded images need to be resized so there are also thumbs available and the shown pictures also fit in the page (eg. 800x600). The way I do the resize is like this:

Image scaledImage = img.getScaledInstance((int)width, (int)height, Image.SCALE_SMOOTH); BufferedImage imageBuff = new BufferedImage((int)width, (int)height, BufferedImage.TYPE_INT_RGB); Graphics g = imageBuff.createGraphics(); g.drawImage(scaledImage, 0, 0, new Color(0,0,0), null); g.dispose(); 

And it works okayish. My only problem is that the g.drawImage() method seems to be awfully slow, and I just cannot imagine the user to be patient enought to wait for an upload of 20 pictures 20*10 secs ~ 3 minutes. In fact, on my computer it takes almost 40 secs for making the 3 different resizes for a single picture.

That's not good enough, and I'm looking for a faster solution. I'm wondering if somebody could tell me about a better one in Java OR by calling a shell script, command, whatever hack you know, it has to be quicker, everything else does not matter this time.

like image 729
Balázs Németh Avatar asked Oct 19 '10 11:10

Balázs Németh


2 Answers

I'm using code similar to the following to scale images, I removed the part that deals with preserving the aspect ratio. The performance was definitely better than 10s per image, but I don't remember any exact numbers. To archive better quality when downscaling you should scale in several steps if the original image is more than twice the size of the wanted thumbnail, each step should scale the previous image to about half its size.

public static BufferedImage getScaledImage(BufferedImage image, int width, int height) throws IOException {     int imageWidth  = image.getWidth();     int imageHeight = image.getHeight();      double scaleX = (double)width/imageWidth;     double scaleY = (double)height/imageHeight;     AffineTransform scaleTransform = AffineTransform.getScaleInstance(scaleX, scaleY);     AffineTransformOp bilinearScaleOp = new AffineTransformOp(scaleTransform, AffineTransformOp.TYPE_BILINEAR);      return bilinearScaleOp.filter(         image,         new BufferedImage(width, height, image.getType())); } 
like image 64
Jörn Horstmann Avatar answered Oct 22 '22 19:10

Jörn Horstmann


Do you really need the quality that is provided by using Image.SCALE_SMOOTH? If you don't, you can try using Image.SCALE_FAST. You might find this article helpful if you want to stick with something provided by Java.

like image 25
Klarth Avatar answered Oct 22 '22 19:10

Klarth