0

放射状グラデーションで小さな円を描いています。結果の例 ( r= 10 ピクセル):

r=10

しかし、半径を小さくすると、奇妙なことが起こり始めます。r= 5px の場合:

r=5

10px の画像に合わせてスケーリング:

r=5、スケーリング

そして、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}
));
4

1 に答える 1

1

問題は、円の高さと幅が偶数であることに関係しています。以前はg.fill(new Ellipse2D.Float(r,r,r*2,r*2)); コードの一部として持っていました。これにより、円の幅と高さが常に均等になるようになりました。これは問題を引き起こします。コンピューターは完璧ではなく、円の中心に正確にピクセルを描くことができないためです。これを修正するために、円を描いた場所に 1 つ追加しました。作業コードは次のとおりです。

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"));
    }
}
于 2013-08-02T14:36:14.360 に答える