• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Resizing Image: Java vs PHP

 
Ranch Hand
Posts: 15304
6
Mac OS X IntelliJ IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Sheriff
Posts: 13411
Firefox Browser VI Editor Redhat
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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).
 
Ben Souther
Sheriff
Posts: 13411
Firefox Browser VI Editor Redhat
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Oh yea, the code....
 
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ]
 
Gregg Bolinger
Ranch Hand
Posts: 15304
6
Mac OS X IntelliJ IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Author
Posts: 986
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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.
 
Gregg Bolinger
Ranch Hand
Posts: 15304
6
Mac OS X IntelliJ IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 13411
Firefox Browser VI Editor Redhat
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Ranch Hand
Posts: 15304
6
Mac OS X IntelliJ IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 13411
Firefox Browser VI Editor Redhat
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Ranch Hand
Posts: 15304
6
Mac OS X IntelliJ IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yea, I like that one. I'll check some more samples this evening. Thanks Ben.
 
Ben Souther
Sheriff
Posts: 13411
Firefox Browser VI Editor Redhat
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 986
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Ranch Hand
Posts: 15304
6
Mac OS X IntelliJ IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Ranch Hand
Posts: 15304
6
Mac OS X IntelliJ IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 986
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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?)
 
and POOF! You're gone! But look, this tiny ad is still here:
a bit of art, as a gift, that will fit in a stocking
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic