java - Java Graphics2D drawImage() 和 clip():如何应用抗锯齿?
问题描述
Java Graphics2D的and方法BufferedImage
绘制的边缘有锯齿,如何应用抗锯齿?drawImage
clip
编码:
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);
解决方案
对于图像,将图像绘制成另一张大 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,包括设置..._INTERPOLATION_BILINEAR
渲染提示的行:
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
可能会更加困难。该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
如下所示:
和特写:
还有代码:
(它不再包含图像部分,因为这些问题完全不相关......)
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;
}
}
}
推荐阅读
- android - 尝试对 RecyclerView 进行排序时出错
- node.js - 如何检测应用程序是否从 dmg 文件运行?
- powerbi - 如何在 Power BI 中获得几年总销售额的百分比?
- python-3.x - 将文本文件中的数值数组转换为 numpy 数组的最佳方法是什么?
- intellij-idea - IntelliJ junit5 运行配置 - 使用标签运行所有测试,并在特定包中运行
- r - R OMPR 包 - 限制选择的唯一变量组件的数量
- excel - 如何根据 Excel 工作表中输入的选项过滤表格?
- java - 如果对象名称不在列表中,Java ArrayList 将类对象添加到列表中?
- python - 正确获取 django 模型
- javascript - 而不是点击,我想用滚动/new.php 打开页面