4

We have a photo gallery that is using servlets to resize images - we need good performance and decent quality, but we just can't get it right. Also, sadly enough, we have only java 1.4, which leaves us to almost no external image libraries (nearly everything i found is java 1.5+) and java image handling is really not good.

If I use this:

private static BufferedImage scaleImage(BufferedImage orig, int type, int w, int h) {

    BufferedImage tmp = new BufferedImage(w, h, type);
    Graphics2D g2 = tmp.createGraphics();
    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);

    g2.drawImage(orig, 0, 0, w, h, null);
    g2.dispose();
    return tmp;
}

the results are almost same every time (and bad looking) or extremely slow, it depends on the selected hint. I read almost every article about image resizing in java (including this one and it does not help.

Do you have any ideas? Any external libraries for java 1.4 that are fast and have decent quality? Any algorithm that would get good results?

skaffman
  • 398,947
  • 96
  • 818
  • 769
lzk
  • 41
  • 1

2 Answers2

2

You might try Image Magick wrappers like JMagick.

Thomas
  • 87,414
  • 12
  • 119
  • 157
  • Thanks a lot :) The only problem with JMagick seems to be that it cannot load image from InputStream, which is my case :/ Well, I will try to work on that :) – lzk Aug 04 '11 at 13:42
  • That's probably because it delegates the actual work to the command-line tool ImageMagick. – Joachim Sauer Aug 04 '11 at 13:58
  • @Izk You might write the image to a file, invoke Image Magick on that file and load it again. An alternative would be im4java, but it seems there's only a Java 5+ version. – Thomas Aug 04 '11 at 14:32
0

Izk, given your requirements I would agree with Thomas and you (likely) need to rely on an external/native library.

If you hadn't explicitly mentioned performance, I would have suggested using BICUBIC interpolation along with Chris Campbell's incremental-scaling algorithm. The imgscalr library implements all of this, but it does require Java 5 (uses Enums). That being said, you can easily copy the code into a Java 1.4-compliant implementation.

Go take a look at the Scalr class, scroll to the VERY bottom, and copy the last two methods. That is all you should need to get you 95% done IF you want to keep it implemented in Java.

But, if you found Java-scaling performance unacceptable up until this point, that implementation won't help you. You'll need to look at using a native library like ImageMagick.

Fortunately ImageMagick has 2 popular Java bindings and if the JMagick API doesn't let you deal with InputStreams, you might look at im4java which is a straight wrapper to the command line version of ImageMagick. I dug through the source code and it looks like the core ImageCommand class used to wrap "commands" to send to the command line util allow you to pass BufferedImage instances as the "images" Object param when executing an operation.

If that is the case you can use ImageIO.read(InputStream) to read the image data into a BufferedImage before sending it off to ImageMagick for processing using the im4java API.

There are a few suggestions to get you where you need to go, I hope they helped.

Riyad Kalla
  • 10,604
  • 7
  • 53
  • 56
  • Thanks a lot for your detailed analysis, it is extremely helpful and I really appreciate it. – lzk Aug 04 '11 at 22:20