【问题标题】:Why this RadialGradientPaint is drawn incorrectly?为什么这个 RadialGradientPaint 绘制不正确?
【发布时间】:2013-08-02 13:45:05
【问题描述】:

我正在绘制带有径向渐变的小圆圈。示例结果(r = 10 像素):

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

缩放以匹配 10px 图像:

如果 r = 2px(再次缩放),情况会变得更糟:

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

我用来生成上述图片的代码(SSCCE,可编译和可运行):

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, (int) r*4, 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, (int) r*4);
        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,r*2));
        g.dispose();
        ImageIO.write(img, "png", new File("out.png"));
    }
}

我尝试切换渲染提示,但结果没有改变。什么可能导致此问题?

编辑:

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

“固定”代码:

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}
));

【问题讨论】:

    标签: java swing graphics drawing gradient


    【解决方案1】:

    问题与圆的高度和宽度是偶数有关。你曾经有g.fill(new 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 在设置渐变时可能会使用像素的中心而不是左上角,但我不知道他们为什么会这样做。
    猜你喜欢
    • 2012-06-24
    • 1970-01-01
    • 2013-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-20
    • 2011-03-29
    相关资源
    最近更新 更多