Java Graphics2D drawImage()和clip():如何应用抗锯齿?

Java Graphics2D drawImage()和clip():如何应用抗锯齿?,java,Java,Java Graphics2D的drawImage和clip方法绘制的buffereImage具有锯齿状边缘,如何应用抗锯齿 守则: BufferedImage img = ImageIO.read(new File("D:\\Pictures\\U\\U\\3306231465660486.jpg")); JFrame frame = new JFrame(); frame.add(new JPanel() { @Override protected void paintC

Java Graphics2D的
drawImage
clip
方法绘制的
buffereImage
具有锯齿状边缘,如何应用抗锯齿

守则:

BufferedImage img = ImageIO.read(new File("D:\\Pictures\\U\\U\\3306231465660486.jpg"));

JFrame frame = new JFrame();
frame.add(new JPanel() {
    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        g2d.setColor(Color.RED);
        g2d.drawLine(10, 10, 300, 100);


        g2d.translate(50, 200);
        g2d.rotate(Math.toRadians(30), getWidth() / 2.0, getHeight() / 2.0);
        g2d.drawImage(img, 0, 0, this);
        g2d.clip(new Rectangle(-110, 110, 80, 110));
        g2d.fill(new Rectangle(-100, 100, 100, 100));
    }
});

frame.setSize(600, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);

一种解决方案是在加载图像后使其边界模糊。您还应该将
RenderingHints.KEY\u RENDERING
RenderingHints.VALUE\u RENDER\u QUALITY
一起使用

这是最终结果:

完整代码如下所示。请注意,is使用此答案中描述的模糊方法:


对于图像,将图像绘制为另一个大2像素的图像,然后使用双线性插值绘制结果图像就足够了。因此,您可以通过以下方法传递图像:

private static BufferedImage addBorder(BufferedImage image)
{
    BufferedImage result = new BufferedImage(
        image.getWidth() + 2, image.getHeight() + 2, 
        BufferedImage.TYPE_INT_ARGB);
    Graphics2D g = result.createGraphics();
    g.drawImage(image, 1, 1, null);
    g.dispose();
    return result;
}
结果将是:

这是MCVE,包括设置
…\u插值\u双线性
渲染提示的行:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ImageBorderAntialiasing
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui()
    {
        //BufferedImage img = loadUnchecked("7bI1Y.jpg");
        BufferedImage img = addBorder(loadUnchecked("7bI1Y.jpg"));

        JFrame frame = new JFrame();
        frame.add(new JPanel()
        {
            @Override
            protected void paintComponent(Graphics g)
            {
                Graphics2D g2d = (Graphics2D) g;
                g2d.setRenderingHint(
                    RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);

                g2d.setRenderingHint(
                    RenderingHints.KEY_INTERPOLATION,
                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);

                g2d.setColor(Color.RED);
                g2d.drawLine(10, 10, 300, 100);

                g2d.translate(50, 200);
                g2d.rotate(Math.toRadians(30), 
                    getWidth() / 2.0, getHeight() / 2.0);
                g2d.drawImage(img, 0, 0, this);
                g2d.fill(new Rectangle(-100, 100, 100, 100));
            }
        });

        frame.setSize(600, 600);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private static BufferedImage addBorder(BufferedImage image)
    {
        BufferedImage result = new BufferedImage(
            image.getWidth() + 2, image.getHeight() + 2, 
            BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = result.createGraphics();
        g.drawImage(image, 1, 1, null);
        g.dispose();
        return result;
    }

    private static BufferedImage loadUnchecked(String fileName)
    {
        try
        {
            return ImageIO.read(new File(fileName));
        }
        catch (IOException e)
        {
            e.printStackTrace();
            return null;
        }
    }

}

回答后,问题被更新为询问
clip
方法


消除锯齿
剪辑
操作的结果可能更困难。
clip
操作“本质上”是非常困难的(我假设它最终将由类似于硬件中的一个组件来处理)

解决此问题的一种方法是手动进行剪裁。因此,与其这样做

g2d.clip(new Rectangle(-110, 110, 80, 110));
g2d.fill(new Rectangle(-100, 100, 100, 100));
你可以这样做

Shape clip = new Rectangle(-110, 110, 80, 110);
Shape rectangleA = new Rectangle(-100, 100, 100, 100);  
g2d.fill(clip(clip, rectangleA));            
其中,
clip
方法用于手动计算形状的交点

注意:计算两个形状的交点可能相当昂贵。如果这成为一个问题,人们可能不得不修改方法。但另一个注意事项是:我从事Swing编程已经有20年了,根本不记得曾经使用过
Graphics2D#clip
方法

使用
Graphics2D#clip
与手动剪裁之间的区别如下所示:

还有特写:

代码如下:

(它不再包含图像部分,因为问题完全无关…)


感谢您的回答,尽管这是一个解决方法,但它对于
clip
方法仍然无效,并且在实际应用中可能会导致额外的内存开销。所以我需要找到一个更好的解决方案。感谢您的回答,尽管这是一个解决方法,但它对于
clip
方法仍然无效,并且在实际应用中可能会导致额外的内存开销。因此,我需要找到更好的解决方案。@Yii.Guxing如果有其他要求,那么您应该在问题中说明。编辑问题以解释
clip
方法在此处的相关性。感谢您的补充回答,您的解决方案给了我很多启发,我们可以使用
TexturePaint
类和
fill()
方法来解决此问题。但它带来了一个新问题:渲染图像有点模糊。你对此有什么建议吗?好的,
clip
部分是一个完全不同的故事。解决这个问题可能不是那么简单。(一种方法是使用
区域
手动进行剪辑,但这是否可行取决于
剪辑
的准确使用方式)。我已经草拟了一种方法,但我认为最好基本上撤销这里的编辑(这样这个问题只与
drawImage
案例有关),并提出一个新问题,特别是关于
clip
方法。
Shape clip = new Rectangle(-110, 110, 80, 110);
Shape rectangleA = new Rectangle(-100, 100, 100, 100);  
g2d.fill(clip(clip, rectangleA));            
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Area;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ClippedDrawingAntialiasing
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui()
    {
        JFrame frame = new JFrame();
        frame.getContentPane().setLayout(new GridLayout(1,2));
        frame.getContentPane().add(new JPanel()
        {
            @Override
            protected void paintComponent(Graphics g)
            {
                Graphics2D g2d = (Graphics2D) g;
                g2d.setRenderingHint(
                    RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);

                g2d.setColor(Color.RED);
                g2d.drawLine(10, 10, 300, 100);

                g2d.translate(50, 200);
                g2d.rotate(Math.toRadians(30), 
                    getWidth() / 2.0, getHeight() / 2.0);

                g2d.clip(new Rectangle(-110, 110, 80, 110));

                g2d.fill(new Rectangle(-100, 100, 100, 100));            

                g2d.setColor(Color.BLUE);
                g2d.fill(new Rectangle(-60, 120, 60, 170));            
            }
        });
        frame.getContentPane().add(new JPanel()
        {
            @Override
            protected void paintComponent(Graphics g)
            {
                Graphics2D g2d = (Graphics2D) g;
                g2d.setRenderingHint(
                    RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);

                g2d.setColor(Color.RED);
                g2d.drawLine(10, 10, 300, 100);

                g2d.translate(50, 200);
                g2d.rotate(Math.toRadians(30), 
                    getWidth() / 2.0, getHeight() / 2.0);

                Clipper clipper = 
                    new Clipper(new Rectangle(-110, 110, 80, 110));

                g2d.fill(clipper.clip(new Rectangle(-100, 100, 100, 100)));            

                g2d.setColor(Color.BLUE);
                g2d.fill(clipper.clip(new Rectangle(-60, 120, 60, 170)));            
            }
        });

        frame.setSize(1200, 600);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private static class Clipper 
    {
        private final Shape shape;
        Clipper(Shape shape)
        {
            this.shape = shape;
        }

        Shape clip(Shape other)
        {
            Area a = new Area(shape);
            a.intersect(new Area(other));
            return a;
        }
    }

}