swing - Java Buffered Image Anti Aliasing Not Working - Stack Overflow

admin2025-04-22  1

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:

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.

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.

Share Improve this question edited Jan 21 at 16:17 ObSp asked Jan 21 at 15:19 ObSpObSp 316 bronze badges 6
  • i think you just need VALUE_INTERPOLATION_BILINEAR , the image i see is correctly what a nearest-neighbor interpolation should produce .... – Ahmed AEK Commented Jan 21 at 15:33
  • @AhmedAEK thank you for the suggestion, but that doesn't visibly change anything. I will edit the question to say that I've tried it. – ObSp Commented Jan 21 at 15:40
  • @Abra I've attached an example – ObSp Commented Jan 21 at 16:17
  • 1 On my system the Graphics implementation is of class sun.java2d.SunGraphics2D, which I don't know right now how it implements resizing of the image internally nor how to control it, but as a temporary workaroud you can draw image.getScaledInstance(35, 35, Image.SCALE_SMOOTH) which internally seems to use an AreaAveragingScaleFilter and produces the desired result.Scale the image once of course, not for every paintComponent call.The documentation does not seem to specify/guarantee the algorithm used for your drawImage calls, but configuring the algorithm should be the solution IMHO. – gthanop Commented Jan 21 at 20:18
  • You may also want to try setting the KEY_RENDERING hint. – VGR Commented Jan 21 at 23:57
 |  Show 1 more comment

1 Answer 1

Reset to default 0

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."

转载请注明原文地址:http://www.anycun.com/QandA/1745301186a90577.html