为什么这个RadialGradientPaint绘制错误?

时间:2013-08-02 13:45:06

标签: java swing graphics drawing gradient

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

r=10

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

r=5

缩放以匹配10px图像:

r=5,scaled

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

enter image description here

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

我用于生成上述图像的代码(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"));
    }
}

我尝试切换渲染提示,但结果不会改变。可能导致这个问题的原因是什么?

修改

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

enter image description here

“已修复”代码:

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

1 个答案:

答案 0 :(得分: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"));
    }
}