平滑BufferImage边缘

4
有没有办法平滑转换(平移和旋转)的BufferedImage的锯齿边缘?
测试图像的放大视图:
请注意,这不是实际将使用的BufferedImage,仅用于在此处演示。
已经使用双线性插值、质量渲染和抗锯齿RenderHints,但是抗锯齿似乎只适用于Java绘制的形状。显然,形状的白色背景和黑色边缘没有像灰色和黑色的插值那样混合在一起。
我想要的可以通过在图像周围添加1px的透明边框并让插值工作来实现,但这感觉很冗余。难道没有更好的方法吗?

1
其实,我也喜欢你的1像素透明边框技巧。:-) 不过,对于大图像来说需要相当多的内存( (w+2) * (h+2) * pixelSize字节 )。Chris Campbell的方法可能更快一些,但我还没有测试过。 - Harald K
1个回答

4

是的,这是一个已知的问题,但可以通过一种聪明的技巧解决,我曾在Chris Campbell的博客文章中找到过:

的确,在使用Graphics.drawImage()渲染时,Sun的Java 2D实现不会自动抗锯齿图像边缘。然而,有一个简单的解决方法:使用TexturePaint,并渲染一个经过变换/抗锯齿处理的fillRect()。

这是我使用的代码,改编自他博客中的代码:

// For multiples of 90 degrees, use the much faster drawImage approach
boolean fast = ((Math.abs(Math.toDegrees(angle)) % 90) == 0.0);

int w = source.getWidth();
int h = source.getHeight();

// Compute new width and height
double sin = Math.abs(Math.sin(angle));
double cos = Math.abs(Math.cos(angle));

int newW = (int) Math.floor(w * cos + h * sin);
int newH = (int) Math.floor(h * cos + w * sin);

// Create destination image for painting onto
BufferedImage dest = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB);

// Set up transformation around center
AffineTransform transform = AffineTransform.getTranslateInstance((newW - w) / 2.0, (newH - h) / 2.0);
transform.rotate(angle, w / 2.0, h / 2.0);

Graphics2D g = dest.createGraphics();

try {
    g.transform(transform);

    if (!fast) {
        // Max quality
        g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
                           RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                           RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                           RenderingHints.VALUE_ANTIALIAS_ON);
        // Here's the trick:
        g.setPaint(new TexturePaint(source,
                                    new Rectangle2D.Float(0, 0, source.getWidth(), source.getHeight())));
        g.fillRect(0, 0, source.getWidth(), source.getHeight());
    }
    else {
        // Multiple of 90 degrees:
        g.drawImage(source, 0, 0, null);
    }
}
finally {
    g.dispose();
}

天啊,我已经寻找解决方法好久了!谢谢! - François Gautier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接