aspose file tools*
The moose likes Swing / AWT / SWT and the fly likes Resizing Image: Java vs PHP Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "Resizing Image: Java vs PHP" Watch "Resizing Image: Java vs PHP" New topic
Author

Resizing Image: Java vs PHP

Gregg Bolinger
GenRocket Founder
Ranch Hand

Joined: Jul 11, 2001
Posts: 15286
    
    6

Ok, I know this seems a strange place to talk about PHP but since we are talking about Java's Graphics API, this is the best place. For a web application I've written I needed to provide thumbnail images of various sizes on the fly. So the user uploads a single larger image and the application adjusts it when necessary for various pages.

The problem is that the code I wrote in Java to resize the images does a pretty poor job. Loss of sharpness and specifically black and white images turn out way too light. However, I am primarily dealing with black and white images here.

The original:


Java


PHP


The code used in Java to resize the images is:



I'd really prefer not to have to rewrite the entire app in PHP just to get better scaled images. Can anyone suggest a better scaling java solution that would get me the same results that I get with PHP GD2?

Thanks.


GenRocket - A Test Data Generation Platform
Ben Souther
Sheriff

Joined: Dec 11, 2004
Posts: 13410

Here's one I wrote using JAI.
It's probably not the slickest thing but the images seem to look OK.

One area where I was groping a bit was the section where the parameterBlock settings were being added so I won't be much help if you need it explained.

In a nutshell, this method, measures the height and width to determine whether the images is a landscape or portrait, and scales the image down until the larger of the two dimensions is == maxDim (500px by default).


Java API J2EE API Servlet Spec JSP Spec How to ask a question... Simple Servlet Examples jsonf
Ben Souther
Sheriff

Joined: Dec 11, 2004
Posts: 13410

Oh yea, the code....
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Perhaps you could show this ImageUtils.getScaledInstance()?

Assuming it just calls Image.getScaledInstance(), I might try using RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR instead of the bicubic interpolation.
[ August 01, 2007: Message edited by: Jim Yingst ]

"I'm not back." - Bill Harding, Twister
Gregg Bolinger
GenRocket Founder
Ranch Hand

Joined: Jul 11, 2001
Posts: 15286
    
    6

Thanks Ben. I'll give that a shot this evening. By any chance would you know how performant that is? I can't use the JNI JAI version on the host I am using so it's going to be slower anyway just because of that.
Brian Cole
Author
Ranch Hand

Joined: Sep 20, 2005
Posts: 862
Originally posted by Gregg Bolinger:
Ok, I know this seems a strange place to talk about PHP but since we are talking about Java's Graphics API, this is the best place. For a web application I've written I needed to provide thumbnail images of various sizes on the fly. So the user uploads a single larger image and the application adjusts it when necessary for various pages.

The problem is that the code I wrote in Java to resize the images does a pretty poor job. Loss of sharpness and specifically black and white images turn out way too light.


You might do better on the Other Java APIs forum, as this is not a Swing issue.

From your code there's no way to tell what ImageUtils.getScaledInstance() does, so I can't make specific recommendations. One thing you can try is using the old 1.1-style java.awt.Image.getScaledInstance() with the SCALE_AREA_AVERAGING hint.

Probably better is to take a look at this article one of the java 2d engineers wrote a few months back:


However, be aware that if you try to downscale an image by a factor of more than two (i.e., the scaled instance is less than half the size of the original), and you are using the BILINEAR or BICUBIC hint, the quality of the scaled instance may not be as smooth as you might like. If you are familiar with the quality of the old Image.SCALE_AREA_AVERAGING (or Image.SCALE_SMOOTH) hint, then you may be especially dismayed. The reason for this disparity in quality is due to the different filtering algorithms in use. If downscaling by more than two times, the BILINEAR and BICUBIC algorithms tend to lose information due to the way pixels are sampled from the source image; the older AreaAveragingFilter algorithm used by Image.getScaledInstance() is quite different and does not suffer from this problem as much, but it requires much more processing time in general.

To combat this issue, you can use a multi-step approach when downscaling by more than two times; this helps prevent the information loss issue and produces a much higher quality result that is visually quite close to that produced by Image.SCALE_AREA_AVERAGING.


Basically he suggests scaling by half in a loop, which sounds a bit odd to me but obviously he knows more about this stuff than I do.


bitguru blog
Gregg Bolinger
GenRocket Founder
Ranch Hand

Joined: Jul 11, 2001
Posts: 15286
    
    6

Sorry I forgot to post the ImageUtils class. I'll take a look at that this evening and make some adjustments there. Thanks.
Ben Souther
Sheriff

Joined: Dec 11, 2004
Posts: 13410

Originally posted by Gregg Bolinger:
Thanks Ben. I'll give that a shot this evening. By any chance would you know how performant that is? I can't use the JNI JAI version on the host I am using so it's going to be slower anyway just because of that.


It's not fast.
The speed depends largely on the size of the original image.


I don't know how much of that is JVM setup and how much time is taken in determining the layout.









I just scaled your image down to 200px and it seems to look as good or better than the PHP version.

JAI




PHP

[ August 01, 2007: Message edited by: Ben Souther ]
[ August 01, 2007: Message edited by: Ben Souther ]
Gregg Bolinger
GenRocket Founder
Ranch Hand

Joined: Jul 11, 2001
Posts: 15286
    
    6

Originally posted by Ben Souther:


It's not fast.
The speed depends largely on the size of the original image.
I just scaled your image down to 200px and it seems to look as good or better than the PHP version.


Hmm, I somewhat disagree.





Yours looks a bit choppier. The PHP version is smooth. Maybe it's my eyes.
[ August 01, 2007: Message edited by: Gregg Bolinger ]
Ben Souther
Sheriff

Joined: Dec 11, 2004
Posts: 13410

Originally posted by Gregg Bolinger:


Hmm, I somewhat disagree.





Yours looks a bit choppier. The PHP version is smooth. Maybe it's my eyes.

[ August 01, 2007: Message edited by: Gregg Bolinger ]




No, it's probably my eyes.
When I blew it up, it did look worse.
I changed from InterpolationNearest to InterpolationBilinear and it seemed to get smoother.
Gregg Bolinger
GenRocket Founder
Ranch Hand

Joined: Jul 11, 2001
Posts: 15286
    
    6

Yea, I like that one. I'll check some more samples this evening. Thanks Ben.
Ben Souther
Sheriff

Joined: Dec 11, 2004
Posts: 13410

There are other intropolation objects provided by JAI as well.

Interpolation
InterpolationBicubic
InterpolationBicubic2
InterpolationBilinear
InterpolationNearest
InterpolationTable
InvertDescriptor

Some of them have constructors that take arguments (which I don't really understand).
I'll probably play with some of them when I get some free time.
Brian Cole
Author
Ranch Hand

Joined: Sep 20, 2005
Posts: 862
Originally posted by Brian Cole:
You might do better on the Other Java APIs forum, as this is not a Swing issue.

(...)

Probably better is to take a look at this article one of the java 2d engineers wrote a few months back


I apologize for mentioning the other forum. I posted without looking at your name but, as a javaranch sheriff, you obviously know what's going on.

But have you taken a look at that article yet? Unless that's what you are doing already, it would seem to solve your problems.

[edit: spell sheriff correctly]
[ August 01, 2007: Message edited by: Brian Cole ]
Gregg Bolinger
GenRocket Founder
Ranch Hand

Joined: Jul 11, 2001
Posts: 15286
    
    6

I've read that article before. In fact, that's where my ImageUtil.getScaledInstance() code came from. While Ben's approach is similar, it's simpler and seems to work better, so I believe I am going to go that route for now.

Thanks.
Gregg Bolinger
GenRocket Founder
Ranch Hand

Joined: Jul 11, 2001
Posts: 15286
    
    6

Ben, I was able to find enough time to implement your code within my application and it works wonderful. The performance impact is negligible. Thanks a bunch for your help.
Brian Cole
Author
Ranch Hand

Joined: Sep 20, 2005
Posts: 862
Originally posted by Gregg Bolinger:
I've read that article before. In fact, that's where my ImageUtil.getScaledInstance() code came from.


I was going to suggest trying the old, slow, and simple

Image scaled = origImage.getScaledInstance(133, 195, Image.SCALE_AREA_AVERAGING);

but then I tried your code on my machine (taking ImageUtil.getScaledInstance() to be exactly Chris Campbell's code from the article, except declared static) and it produced an image that is very similar to the one you labeled PHP in your original post.

The fur is a bit grainier (which could possibly have to do with the JPEG encoding) but it is much darker than the one you labeled Java in your original post.

Since your original code works well on my machine, I can't really experiment to find improvements. (btw, how are you turning your original image into a BufferedImage? Could some fading be happening there?)
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
 
subject: Resizing Image: Java vs PHP
 
Similar Threads
image resizing
Making translucent images
Adjusting the size of an image (jpg)?
Image Handling in Java
Calling of a PHP file in JSP