Java 为什么此RadialGradientPaint绘制不正确?

Java 为什么此RadialGradientPaint绘制不正确?,java,swing,graphics,drawing,gradient,Java,Swing,Graphics,Drawing,Gradient,我画的是径向渐变的小圆圈。示例结果(r=10 px): 但是当我减小半径时,奇怪的事情开始发生。如果r=5px: 缩放以匹配10px图像: 如果r=2px(同样,按比例计算),情况会变得更糟: 如您所见,渐变的中心始终偏离圆心(向下和向右) 我用于生成上述图像的代码(SSCCE、可编译和可运行): 我尝试切换渲染提示,但结果没有改变。是什么导致了这个问题 编辑: 将RadialGradientPaint偏移0.5f左上角将生成正确的图像(r=2): “固定”代码: 问题在于你的圆的高度

我画的是径向渐变的小圆圈。示例结果(
r
=10 px):

但是当我减小半径时,奇怪的事情开始发生。如果
r
=5px:

缩放以匹配10px图像:

如果r=2px(同样,按比例计算),情况会变得更糟:

如您所见,渐变的中心始终偏离圆心(向下和向右)

我用于生成上述图像的代码(SSCCE、可编译和可运行):

我尝试切换渲染提示,但结果没有改变。是什么导致了这个问题

编辑:

将RadialGradientPaint偏移
0.5f
左上角将生成正确的图像(r=2):

“固定”代码:


问题在于你的圆的高度和宽度是一个偶数。您以前有
g.fill(新的Ellipse2D.Float(r,r,r*2,r*2))
作为代码的一部分。这使得你的圆圈的宽度和高度总是均匀的。这会产生问题,因为计算机不是完美的,而且不可能精确地在一个尺寸均匀的圆的中心绘制一个像素。为了解决这个问题,我在你画圆的地方加了一个。工作守则如下:

import java.awt.image.*;
import javax.imageio.ImageIO;
import java.io.File;
import java.awt.*;
import java.awt.geom.*;

public class Test {
    public static void main(String[] args) throws Exception {
        float r = 2;
        BufferedImage img = new BufferedImage((int) r*4 + 1, (int) r*4 + 1, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = img.createGraphics();
        RenderingHints rh = new RenderingHints(null);
        rh.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        rh.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        rh.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
        rh.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g.addRenderingHints(rh);
        g.setBackground(Color.WHITE);
        g.clearRect(0, 0, (int) r*4 + 1, (int) r*4 + 1);
        g.setPaint(new RadialGradientPaint(
           r*2,r*2,r*2,
           new float[] {0.1f,0.35f},
           new Color[] {Color.RED, Color.GREEN}
        ));
        g.fill(new Ellipse2D.Float(r,r,r*2 + 1,r*2 + 1));
        g.dispose();
        ImageIO.write(img, "png", new File("out.png"));
    }
}

是的,我同意像素的问题-但为什么同样的情况发生在抗锯齿上?抗锯齿不就是为了解决这个问题吗?确实如此,但抗锯齿只能使边缘看起来更平滑。Java仍然需要找到一个放置圆心的位置,并且对于大小均匀的边,不可能将其放置在精确的中心,因此Java将圆心放置在不完全精确的中心。这不是真的-请参阅我的新编辑(将渐变中心偏移0.5f将产生完全居中的渐变)。我现在看到了。我想不出为什么会有这种抵消。可能Graphics2D在设置梯度时使用像素的中心,而不是左上角,但我不知道为什么他们会这样做。
g.setPaint(new RadialGradientPaint(
    r*2-0.5f, r*2-0.5f, r*2,
    new float[] {0.1f,0.35f},
    new Color[] {Color.RED, Color.GREEN}
));
import java.awt.image.*;
import javax.imageio.ImageIO;
import java.io.File;
import java.awt.*;
import java.awt.geom.*;

public class Test {
    public static void main(String[] args) throws Exception {
        float r = 2;
        BufferedImage img = new BufferedImage((int) r*4 + 1, (int) r*4 + 1, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = img.createGraphics();
        RenderingHints rh = new RenderingHints(null);
        rh.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        rh.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        rh.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
        rh.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g.addRenderingHints(rh);
        g.setBackground(Color.WHITE);
        g.clearRect(0, 0, (int) r*4 + 1, (int) r*4 + 1);
        g.setPaint(new RadialGradientPaint(
           r*2,r*2,r*2,
           new float[] {0.1f,0.35f},
           new Color[] {Color.RED, Color.GREEN}
        ));
        g.fill(new Ellipse2D.Float(r,r,r*2 + 1,r*2 + 1));
        g.dispose();
        ImageIO.write(img, "png", new File("out.png"));
    }
}