Java Graphics2D正在关闭一个像素(舍入错误?) [英] Java Graphics2D is Drawing One Pixel Off (Rounding error?)

查看:160
本文介绍了Java Graphics2D正在关闭一个像素(舍入错误?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试使用Graphics2D和PaintComponent在Java中创建程序。但是,Java没有正确地舍入一些值,导致一些点被渲染成与它应该给出不洁图像的位置不同的像素。你可以在下面的图片中看到我的意思。





这是我的代码。我可以改变什么来解决这个问题?谢谢!

  public void paintComponent(Graphics g)
{
super.paintComponent(g);

g.setColor(Color.red);

int orginX = getWidth()/ 2;
int orginY = getHeight()/ 2;

for(int i = 0; i< = 360; i + = 10)
{
double angle = Math.toRadians(i);
double centerX = radius * Math.cos(angle)+ orginX;
double centerY = radius * Math.sin(angle)+ orginY;
int [] anglePointsX = {(int)(radius * Math.cos(angle + Math.toRadians(60))+ centerX),(int)(radius * Math.cos(angle-Math.toRadians(60) ))+ centerX),orginX};
int [] anglePointsY = {(int)(radius * Math.sin(angle + Math.toRadians(60))+ centerY),(int)(radius * Math.sin(angle-Math.toRadians(60) ))+ centerY),orginY};
g.drawPolygon(anglePointsX,anglePointsY,3);
}


解决方案

尝试使用 i< 360 而不是 i< = 360 ,因为你已经在这个角度画了一条线(0 == 360)



尝试使用 Path2D GeneralPath 而不是 drawPolygon 因为这会给你 float double 精确度



查看



然后我使用<$ c $更改了绘图c> drawPolygon 使用 Shape API,特别是 Path2D

  @Override 
protected void paintComponent(Graphics g){
super.paintComponent(g);

Graphics2D g2d =(Graphics2D)g.create();

g2d.setColor(Color.red);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING,RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,RenderingHints.VALUE_STROKE_PURE);

int orginX = getWidth()/ 2;
int orginY = getHeight()/ 2;

int dif =(int)(360 / 6d);
for(int i = 0; i< 360; i + = dif){
double angle = Math.toRadians(i);
double centerX = radius * Math.cos(angle)+ orginX;
double centerY = radius * Math.sin(angle)+ orginY;

Path2D path = new Path2D.Double();
path.moveTo(radius * Math.cos(angle + Math.toRadians(60))+ centerX,radius * Math.sin(angle + Math.toRadians(60))+ centerY);
path.lineTo((radius * Math.cos(angle - Math.toRadians(60))+ centerX),(radius * Math.sin(angle - Math.toRadians(60))+ centerY));
path.lineTo(orginX,orginY);

g2d.draw(路径);
}
g2d.dispose();
}

有和没有呈现提示





尽管如此,即使没有提示提示,问题也就消失了


I have been trying to make a program in Java using Graphics2D and PaintComponent. However, Java is not rounding some values correctly resulting in a few points being rendered a pixel different from where it supposed to be which gives an unclean image. You can see what I mean in the picture below.

Here is my code. What can I change to fix this? Thank you!

public void paintComponent( Graphics g )
{
  super.paintComponent( g );

  g.setColor(Color.red);

  int orginX = getWidth()/2;
  int orginY = getHeight()/2;

  for(int i=0; i<=360; i+= 10)
  {
      double angle = Math.toRadians(i);
      double centerX = radius * Math.cos(angle) + orginX;
      double centerY = radius * Math.sin(angle) + orginY;
      int[] anglePointsX = {(int) (radius * Math.cos(angle+Math.toRadians(60)) + centerX), (int) (radius * Math.cos(angle-Math.toRadians(60)) + centerX), orginX};
      int[] anglePointsY = {(int) (radius * Math.sin(angle+Math.toRadians(60)) + centerY), (int) (radius * Math.sin(angle-Math.toRadians(60)) + centerY), orginY};
      g.drawPolygon(anglePointsX, anglePointsY, 3);
  }

解决方案

Try using i < 360 instead i<=360, as you've already drawen a line at this angle (0 == 360)

Try using a Path2D or GeneralPath rather then drawPolygon as this will give you float and double precision

Have a look at Drawing Arbitrary Shapes for more details

Updated...

So I changed i <= 360 to i < 360 and didn't see any immediate changes, however, then applied some rendering hints and it seemed to improve the problem.

I started by reducing the number of elements to 6 (this is where I started seeing an issue) with

int dif = (int) (360 / 6d);

for (int i = 0; i < 360; i += dif) {

Then I applied some rendering hints...

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    Graphics2D g2d = (Graphics2D) g.create();

    g2d.setColor(Color.red);
    g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
    g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
    g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
    g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);

    int orginX = getWidth() / 2;
    int orginY = getHeight() / 2;

    int dif = (int) (360 / 6d);

    for (int i = 0; i < 360; i += dif) {
        double angle = Math.toRadians(i);
        double centerX = radius * Math.cos(angle) + orginX;
        double centerY = radius * Math.sin(angle) + orginY;
        int[] anglePointsX = {(int) (radius * Math.cos(angle + Math.toRadians(60)) + centerX), (int) (radius * Math.cos(angle - Math.toRadians(60)) + centerX), orginX};
        int[] anglePointsY = {(int) (radius * Math.sin(angle + Math.toRadians(60)) + centerY), (int) (radius * Math.sin(angle - Math.toRadians(60)) + centerY), orginY};
        g2d.drawPolygon(anglePointsX, anglePointsY, 3);
    }
    g2d.dispose();
}

Before and after comparison...

I then changed the drawing from using drawPolygon to use the Shape API, in particular a Path2D

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    Graphics2D g2d = (Graphics2D) g.create();

    g2d.setColor(Color.red);
    g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
    g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
    g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
    g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);

    int orginX = getWidth() / 2;
    int orginY = getHeight() / 2;

    int dif = (int) (360 / 6d);
    for (int i = 0; i < 360; i += dif) {
        double angle = Math.toRadians(i);
        double centerX = radius * Math.cos(angle) + orginX;
        double centerY = radius * Math.sin(angle) + orginY;

        Path2D path = new Path2D.Double();
        path.moveTo(radius * Math.cos(angle + Math.toRadians(60)) + centerX, radius * Math.sin(angle + Math.toRadians(60)) + centerY);
        path.lineTo((radius * Math.cos(angle - Math.toRadians(60)) + centerX), (radius * Math.sin(angle - Math.toRadians(60)) + centerY));
        path.lineTo(orginX, orginY);

        g2d.draw(path);
    }
    g2d.dispose();
}

With and without rendering hints

As you can, even without rendering hints, the issue is gone

这篇关于Java Graphics2D正在关闭一个像素(舍入错误?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆