I'm working on a java desktop application and have noticed that when downscaling images to around 50 pixels the images tend to look very pixelated and sharp. I've tried multiple approaches to fixing this, including
//I've tried every kind of interpolation, but to no avail
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
These seem to have no effect on the images though. I was wondering if there's a way to make them smoother.
In my application:
In the vs code photo viewer at 10% scale (about same size)
Any help is appreciated! NOTE: the problem only occurs when downscaling images. Displaying a 256x256 resolution image at a size of 256x256 pixels works completely fine.
EDIT: Here is a minimum reproducible example to show how interpolation/anti aliasing makes no difference:
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(400, 400);
final BufferedImage image = ImageIO.read(new File("home.png"));
JPanel pane = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.gray);
g2d.fillRect(0, 0, 400, 400);
//two examples, image on the left is without interpolation, image on the right is with interpolation
g2d.drawImage(image, 200, 200, 35, 35, null);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.drawImage(image, 250, 200, 35, 35, null);
}
};
frame.add(pane);
frame.setVisible(true);
The program uses this image: https://imgur.com/6xto1o5
The result this produces is as follows:
The house on the left was drawn without interpolation/anti aliasing, the image on the right with both. As you can see, there is no visible difference.
Thanks to @gthanop and @Abra for providing the answer, I'll summarize it here quickly:
You can call Image.getScaledInstance(width, height, hint)
to get a resized version of the image. However, if you provide it with Image.SCALE_SMOOTH
for the hint
argument, the image will be scaled down in a way that it keeps its "smoothness."