Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Graphics2D-沿像素边界的最近邻_Java_Swing_Graphics_Graphics2d_Antialiasing - Fatal编程技术网

Java Graphics2D-沿像素边界的最近邻

Java Graphics2D-沿像素边界的最近邻,java,swing,graphics,graphics2d,antialiasing,Java,Swing,Graphics,Graphics2d,Antialiasing,我有一个(小的)buffereImage,它需要使用最近邻插值进行放大,然后绘制成图形2d。该图像具有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

我有一个(小的)
buffereImage
,它需要使用最近邻插值进行放大,然后绘制成
图形2d
。该图像具有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
是使用
at
作为
仿射变换进行渲染的
buffereImage
。由激活的抗锯齿

g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
产生良好的效果,但仅适用于整个图像的边界;看起来很奇怪:

请注意,顶部边框实际上是图像边框,而右侧是从不透明到透明像素的过渡

是否有最佳实践可以在图像中实现与应用于边框相同的抗锯齿效果?请注意,除了最近邻点以外的其他插值方法是不可接受的

提前感谢您的任何提示

渲染不应该花费太长时间,因为它是
paintComponent
方法的一部分,但是可以对
buffereImage
进行预处理。不过,
仿射变换是(非常)可变的


编辑

我通过使用两步方法实现了一个小的改进:

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\u INTERPOLATION\u BICUBIC
,但是速度非常慢,基本上产生了相同的结果。我希望有一种方法可以获得完全相同的抗锯齿效果,因为它仍然令人恼火。

一个相当复杂的解决方案,通过大量调整和测试,将每个像素渲染为一个形状,从
缓冲图像读取其颜色和透明度,从而提供了非常好的质量:

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.awt.image.BufferedImage;

public class VectorizedImage {
    private final BufferedImage img;

    public VectorizedImage(BufferedImage img) {
        this.img = img;
    }

    public void draw(Graphics2D g) {
        Color oldC = g.getColor();
        Composite oldCo = g.getComposite();
        AlphaComposite comp = AlphaComposite.SrcOver;
        double lap = 1/Math.sqrt(g.getTransform().getDeterminant()); // This deals with inter-pixel borders letting the background shine through
        Path2D pixel = new Path2D.Double();
        pixel.moveTo(0, 0);
        pixel.lineTo(0, 1);
        pixel.lineTo(1, 1);
        pixel.lineTo(1, 0);
        pixel.lineTo(0, 0);
        pixel.transform(AffineTransform.getScaleInstance(1+lap, 1+lap));
        for (int i = 0; i < img.getWidth(); i++)
            for (int j = 0; j < img.getHeight(); j++) {
                g.setColor(new Color(img.getRGB(i, j)));
                g.setComposite(comp.derive(img.getAlphaRaster().getSampleFloat(i, j, 0) / 255));
                g.fill(pixel.createTransformedShape(AffineTransform.getTranslateInstance(i, j)));
        }
        g.setColor(oldC);
        g.setComposite(oldCo);
    }
}
导入java.awt.AlphaComposite;
导入java.awt.Color;
导入java.awt.Composite;
导入java.awt.Graphics2D;
导入java.awt.geom.AffineTransform;
导入java.awt.geom.Path2D;
导入java.awt.image.buffereImage;
公共类矢量化图像{
专用最终缓冲图像img;
公共矢量图像(BuffereImage img){
this.img=img;
}
公共作废图纸(图形2D g){
颜色oldC=g.getColor();
复合oldCo=g.getComposite();
AlphaComposite comp=AlphaComposite.SrcOver;
double lap=1/Math.sqrt(g.getTransform().getDeterminate());//这涉及像素间的边界,让背景通过
Path2D像素=新的Path2D.Double();
像素。移动到(0,0);
像素.lineTo(0,1);
像素.lineTo(1,1);
像素.lineTo(1,0);
像素.lineTo(0,0);
变换(仿射变换.getScaleInstance(1+lap,1+lap));
对于(int i=0;i
结果是这条渲染得很好的边:

An在这里可能会有所帮助,尤其是包括原始图像的图像,因为根据一种说法,当图像包含从完全不透明到完全透明的像素过渡时,伪影似乎只出现在图像中。(解决这个问题可能有点棘手,但也许有人会尝试一下…@Marco13这里的问题与特定的图像无关,我终于找到了一个美观且性能良好的解决方案。如果没有人能想出更好的办法,我会把这个作为一个临时的回答。当我有时间的时候,我也可以做一个MCVE,但这是一个相当复杂的一个。。。