views:

479

answers:

3

Hi all,

I'm a reasonably experienced Java programmer but relatively new to Java2D. I'm trying to scale an image but I'm getting poor quality results. The image is a preview of a panel so contains things like text and textfields. I'll always be scaling down, never up.

Currently I'm using the following code:-

g.drawImage(panelImage, 0, 0, scaledWidth, scaledHeight, null);

Where panelImage is the full sized preview (BufferedImage) and scaledWidth and scaledHeight are the respective target dimensions. I seem to lose a lot of detail in the text and edges of things like textfields etc.

Is there a better call I should be using to scale the image?

Thanks, John

+2  A: 

May be you should call:

 g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

and

g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Pierre
+9  A: 

A suggestion I can make is to first resize the image onto a separate BufferedImage. The reason being, a Graphics2D object of the BufferedImage can be obtained in order to produce a better quality scaled image.

Graphics2D can accept "rendering hints" which instruct the way image processing should be performed by the Graphics2D object. The setRenderingHint method is one of the methods which can be used to set those rendering hints. The rendering hints from the RenderingHints class can be used.

Then, using that Graphics2D object, an image can be drawn to the BufferedImage using the rendering hints specified earlier.

A rough (untested) code would work as the following:

BufferedImage scaledImage = new BufferedImage(
    scaledWidth,
    scaledHeight,
    BufferedImage.TYPE_INT_RGB
);

Graphics2D g = scaledImage.createGraphics();
g.setRenderingHints(
    RenderingHints.Key.KEY_INTERPOLATION,
    RenderingHints.VALUE_INTERPOLATION_BICUBIC
);

g.drawImage(panelImage, 0, 0, scaledWidth, scaledHeight, null);
g.dispose();

Other rendering hints of interest may include:

The Controlling Rendering Quality section of The Java Tutorials also has more information on how to control the rendering quality of Graphics2D objects.

And for a very good source of information on dealing with graphical interfaces in general, Filthy Rich Clients by Chet Haase and Romain Guy is highly recommended. There is one section of the book that deals with the issue of scaling images, which seems quite relevant.

coobird
Thanks, I have a copy of that book and I just dove into it to read the chapter. Should have thought to look there before posting. I completely forgot about rendering hints for scaling. Thanks! John
Johnathan
You're welcome :) Pages 98-113 deals with Image Scaling and includes some good examples. Of particular interest to me was the idea of progressive bilinear scaling presented on page 104.
coobird
Yeah I saw that but don't think my application really warrants it. BICUBIC or BILINEAR are good enough for me. Time to experiment!
Johnathan
A: 

Coobird has the correct idea. I would also try RenderingHints.VALUE_INTERPOLATION_BILINEAR interpolation and see if it's nicer looking. Bicubic works better when upscaling, though. For the best results when downscaling, one should downscale in several steps. First halve the resolution, then halve again, etc. until you get near the desired resolution (i.e. you cannot halve or the image will get too small). Final step is to scale down to the desired resolution.

For example, let's say your input image is 800x600 and you want downscale to 160x120:

  1. Downscale 50%. --> 400x300
  2. Downscale 50%. --> 200x150
  3. Downscale to 160x120.
MH114
Why would downscaling in several steps be an advantage? Please elaborate :D
Thorbjørn Ravn Andersen
Here is something on the topic: http://www.nobel-joergensen.com/roller/java/entry/downscaling_images_in_javaOther than that I don't have anything, but in my experience downscaling in steps provides a better end result. Worth trying at least. :)
MH114
This is the idea behind the "progressive bilinear scaling" -- by performing a bilinear scaling in multiple steps, the information of each pixel is preserved, rather than discarded by performing a single step bilinear rescaling of the image.
coobird
@coobird: Right, thanks! Good to know the correct name for the technique.
MH114