Java Graphics2D drawImage()和clip():如何应用抗锯齿?
Java Graphics2D的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
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;
}
}
}