RenderingHints ignored by affineTransform

Hi

In the following code snippet the rendered image looks as if no interpolation were applied. Any idea? I set the renderingHints but they seem to be ignored…

`
public static void main(String[] args) throws IOException {
BufferedImage source = ImageIO.read(SimpleScaleDemo.class.getResource("/ch/weblica/core/image/img/empros.jpg"));

BufferedImage dest = new BufferedImage(source.getWidth()/5, source.getHeight()/5, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = dest.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2.scale(0.2f, 0.2f);
g2.drawImage(source, 0, 0, null);
g2.dispose();
ImageIO.write(dest, "jpg", new File("test.jpg"));

}
`

import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;

public class SpidTest{
	public static void main(String[] args) throws IOException	{
		BufferedImage original = ImageIO.read(new FileInputStream(new File("in.png")));
		Image scaledImage = original.getScaledInstance(640, 480, Image.SCALE_SMOOTH);
		BufferedImage scaledResultImage = new BufferedImage(640, 480, BufferedImage.TYPE_INT_RGB);
		Graphics2D scaledGraphics = (Graphics2D) scaledResultImage.createGraphics();
		scaledGraphics.drawImage(scaledImage, 0, 0, null);
		scaledGraphics.dispose();
		ImageIO.write(scaledResultImage, "png", new File("out.png"));
	}
}

Works for example.

Thanks for the tip, that seems to work! Thanks

But question remains, why doesn’t the java2d thinks work? How can I scale down an image with java2d??? (in a good quality!)

I tried the AffineTransformOP stuff too.

by the way: getScaledInstance is inofficially deprecated :stuck_out_tongue:

Please, please, please, pretty please don’t use Image.getScaledInstance(). It is much slower than using the scaling variant of Graphics.drawImage(), and it has other drawbacks. See this FAQ entry:
http://java.sun.com/products/java-media/2D/reference/faqs/index.html#Q_How_do_I_create_a_resized_copy

As for your original question… Which JDK version are you using? The BICUBIC hint was unimplemented in 1.4.2 and earlier, I believe. BILINEAR should work for all releases though. BICUBIC was implemented in JDK 5, and all scaling (NN, BILINEAR, BICUBIC) is much much faster in JDK 6.

Note that it’s not necessary to call g.scale(). Instead, it’s usually more straightforward to use the scaling variant of g.drawImage() as outlined in the FAQ item above. For example:


    int newW = 100, newH = 100;
    BufferedImage img = new BufferedImage(newW, newH, ...);
    Graphics2D g = img.createGraphics();
    g.setRenderingHint(KEY_INTERPOLATION, VALUE_INTERPOLATION_BILINEAR);
    g.drawImage(origImg, 0, 0, newW, newH, null);
    g.dispose();

Chris

Hallo Chris

Here is our example: Java Version is:

`
C:>java -version
java version “1.5.0_06”
Java™ 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot™ Client VM (build 1.5.0_06-b05, mixed mode, sharing)

Windows XP SP 2
`

`
public static void main(String[] args) throws FileNotFoundException, IOException {
BufferedImage original = ImageIO.read(SimpleScaleDemo.class.getResource("/ch/weblica/core/image/img/empros.jpg"));

BufferedImage scaledResultImage = createResizedCopy(original, original.getWidth()/5, original.getHeight()/5, true);

ImageIO.write(scaledResultImage, "jpg", new File("out.jpg"));

}

private static BufferedImage createResizedCopy(Image originalImage, int scaledWidth, int scaledHeight, boolean preserveAlpha) {
int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
Graphics2D g = scaledBI.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);

if (preserveAlpha) {
  g.setComposite(AlphaComposite.Src);
}
g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null); 
g.dispose();
return scaledBI;

}
`

These produces always bad loocking results. We are scalling the image down, original has a size of 2272 x 1704.

Well, it’s somewhat subjective, but that’s the result you get with the BICUBIC algorithm when downscaling (you can also try BILINEAR). Note that neither is a silver bullet, especially when downscaling; often it helps to do filtered downscaling in a step-by-step fashion, which will produce results very similar to what AREA_AVERAGING used to provide. For more on these techniques, I’d recommend reading this blog entry from Romain Guy, specifically the code about 5 slides from the end of the presentation:
http://jroller.com/page/gfx?entry=filthy_rich_clients_presentation_slides

The code looks something like this:


int width = image.getWidth(); 
float ratio = (float) width / (float) image.getHeight(); 
BufferedImage thumb = image; 
do { 
    width /= 2; 
    // ... 
    BufferedImage temp = new BufferedImage(width, 
                                           (int) (width / ratio), 
                                           BufferedImage.TYPE_INT_ARGB); 
    Graphics2D g2 = temp.createGraphics(); 
    g2.setRenderingHint(...); 
    g2.drawImage(thumb, 0, 0, temp.getWidth(), temp.getHeight(), null); 
    g2.dispose(); 
    thumb = temp; 
} while (width != thumbWidth);

Chris

Hallo Chris

Thanks for your hints. There really doesn’t seem to be a silver bullet around. (-: The results are very slightly better then the results from getScaledInstance. (We set all posssible rendering hints)

Thank you all for your help!