【发布时间】:2014-07-15 13:44:50
【问题描述】:
我有一个(小)BufferedImage,需要使用最近邻插值法将其放大,然后绘制到Graphics2D。图像具有 1 位 alpha 信息并使用抗锯齿和此代码进行渲染
AffineTransform oldT = g.getTransform();
Paint oldP = g.getPaint();
int w = img.getWidth(), h = img.getHeight();
g.transform(at);
g.setPaint(new TexturePaint(img, new Rectangle2D.Double(0, 0, w, h)));
g.fillRect(0, 0, w, h);
g.setPaint(oldP);
g.setTransform(oldT);
其中img 是BufferedImage,使用at 作为AffineTransform 进行渲染。由
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
产生不错的效果,但只针对整个图像的边框;看起来很奇怪:
请注意,顶部边框实际上是图像边框,而右侧是从不透明像素到透明像素的过渡。
是否有最佳做法可以在图像中实现与应用于边框相同的抗锯齿?请注意,除 NearestNeighbor 之外的其他插值方法是不可接受的。
提前感谢任何提示。
渲染不应该花费太长时间,因为它是 paintComponent 方法的一部分,但预处理 BufferedImage 是可能的。不过,AffineTransform 是(非常)可变的。
编辑
我通过使用两步法取得了一点小进步:
AffineTransform oldT = g.getTransform();
Paint oldP = g.getPaint();
int w = img.getWidth(), h = img.getHeight(), texw = (int) (w*oldT.getScaleX()), texh = (int) (h * oldT.getScaleY());
BufferedImage tex = new BufferedImage(texw, texh, BufferedImage.TYPE_INT_ARGB);
Graphics2D tg = tex.createGraphics();
tg.scale(oldT.getScaleX(), oldT.getScaleY());
tg.drawImage(img, 0, 0, this);
g.transform(at);
g.scale(1/oldT.getScaleX(), 1/oldT.getScaleY());
g.setPaint(new TexturePaint(tex, new Rectangle2D.Double(0, 0, texw, texh)));
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.fillRect(0, 0, texw, texh);
g.setPaint(oldP);
g.setTransform(oldT);
生成此图像:
不过,这仍然不完美。我试过VALUE_INTERPOLATION_BICUBIC,但这非常慢并且基本上产生了相同的结果。我希望有一种方法可以获得完全相同的抗锯齿效果,因为它仍然很烦人。
【问题讨论】:
-
An stackoverflow.com/help/mcve 在这里可能会有所帮助 - 特别是包含原始图像的图像,因为根据一种说法,工件似乎只出现在图像 IN 中,当它包含从完全不透明到完全透明像素的过渡时。 (解决这个问题可能有点棘手,但也许有人会尝试一下......)
-
@Marco13 这里的问题与特定图像无关,我终于找到了一个好看且执行的解决方案。如果没有人想出更好的方法,我会将其作为临时答案发布。当我有时间时,我也可能会制作一个 MCVE,但这是一个相当复杂的......
标签: java swing graphics graphics2d antialiasing