Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么这条线渲染时没有适当的抗锯齿?_Java_Swing - Fatal编程技术网

Java 为什么这条线渲染时没有适当的抗锯齿?

Java 为什么这条线渲染时没有适当的抗锯齿?,java,swing,Java,Swing,我试图渲染一条线,但如果线从实际画布边界之外开始,我会得到奇怪的行为 例如,我有时会得到以下图像,而不是正确的线条: 正确的线路应该是这样的: 以下是生成此示例的可运行代码: import java.awt.image.*; import javax.imageio.ImageIO; import java.io.File; import java.awt.*; import java.awt.geom.*; public class Render { public static

我试图渲染一条线,但如果线从实际画布边界之外开始,我会得到奇怪的行为

例如,我有时会得到以下图像,而不是正确的线条:

正确的线路应该是这样的:

以下是生成此示例的可运行代码:

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

public class Render {
    public static void main(String[] args) throws Exception {
        BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = (Graphics2D) image.getGraphics();

        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

        g.setColor(Color.WHITE);
        g.fillRect(0, 0, 100, 100);

        g.setColor(Color.BLACK);
        g.setStroke(new BasicStroke(2));
        g.draw(new Line2D.Double(-92, 37, 88, 39));

        g.dispose();
        ImageIO.write(image, "png", new File("output.png"));
    }
}
我尝试过使用很多不同的渲染提示,但没有一种组合可以解决这个问题。罪魁祸首可能是什么

编辑:

以下是带有RenderingHights.VALUE\u STROKE\u NORMALIZE的图像:

图像的缩放版本(
g.scale(10,10)
):


您观察到的行为与线条从画布外部开始这一事实无关。如果完全在画布内部使用线条,您将观察到相同的行为

问题来自于小斜率
dy/dx=1/90
、小宽度(
2
)和抗锯齿算法的组合

无抗锯齿

带抗锯齿


您观察到的行为完全正常,这是由于抗锯齿算法造成的。

我认为在您的特定情况下渲染存在一些问题,您的采样线开始于
x=-92
(线的起点位置和坡度在此比例中是一个例外)。但是正如您可能注意到的,画布之外的值没有问题,比如
x=-12
x=-22
x=-82
甚至
x=-102
。您需要提供建议的唯一提示是:

g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
我认为如果
g.setStroke(新的基本行程(2))
实际上并不重要,您可以将其更改为
g.setStroke(新的BasicStroke(1))
甚至完全忽略它。这将使您的线条更加流畅。

我认为这是算法中的一个缺陷,与从画布开始有关。(我向Oracle提交了该文件(审查ID:JI-9026491,Oracle错误数据库:))

请参阅此示例(Ubuntu 14.04,Java 8u66):

如果我反转y坐标:

最终测试:

导入java.awt.image.*;
导入javax.imageio.imageio;
导入java.io.File;
导入java.awt.*;
导入java.awt.geom.*;
公共类测试{
公共静态void main(字符串[]args)引发异常{
BuffereImage=新的BuffereImage(400400,BuffereImage.TYPE_INT_ARGB);
Graphics2D g=(Graphics2D)image.getGraphics();
g、 setRenderingHint(RenderingHits.KEY\u ANTIALIASING,RenderingHits.VALUE\u ANTIALIAS\u ON);
g、 setColor(Color.WHITE);
g、 fillRect(0,040400);
g、 设置颜色(颜色为黑色);
g、 设定行程(新基本行程(2));

对于(int i=0;i,将示例与Path2D而不是Line2D一起使用可以改进输出

    BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g = (Graphics2D) image.getGraphics();

    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    g.setColor(Color.WHITE);
    g.fillRect(0, 0, 100, 100);

    g.setColor(Color.BLACK);
    g.setStroke(new BasicStroke(2));
    Path2D path = new Path2D.Double();
    path.moveTo(-92, 37);
    path.lineTo(88, 39);
    g.draw(path);
    g.dispose();
    ImageIO.write(image, "png", new File("output.png"));

在我看来,这是在画布外开始行时抗锯齿算法中的一个错误

在反复使用渲染提示、逐像素移动线条并分析一些值(如坡度、长度、画布内外部分)后,我得出结论,如果您不想深入了解现有抗锯齿算法的工作方式,您可能会对适当的解决方法感到满意:

  • 从最后一块画布周围的巨大安全区域开始
  • 像往常一样绘制图像,只需移动安全区域的范围
  • 切断安全区
  • 例如:

    import java.awt.image.*;
    import javax.imageio.ImageIO;
    import java.io.File;
    import java.awt.*;
    import java.awt.geom.*;
    
    public class Render {
        public static void main(String[] args) throws Exception {
    
            // YOUR DESIRED SIZE OF CANVAS
            int size = 100;
            // THE SAFEZONE AROUND THE CANVAS
            int safezone = 1000;
    
            // THE IMAGE GETS INITIALIZED WITH SAFEZONE APPLIED
            BufferedImage image = new BufferedImage(size+safezone, size+safezone, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = (Graphics2D) image.getGraphics();
    
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    
            g.setColor(Color.WHITE);
    
            // THE IMAGE GETS FILLED, DON'T FORGET THE SAFEZONE
            g.fillRect(0, 0, size+safezone, size+safezone);
    
            // THE ORIGINAL VALUES WITH THE SAFEZONE APPLIED
            int x1 = -92 + safezone/2;
            int x2 = 88 + safezone/2;
            int y1 = 37 + safezone/2;
            int y2 = 39 + safezone/2;
    
            g.setColor(Color.BLACK);
            g.setStroke(new BasicStroke(2));
            g.draw(new Line2D.Double(x1, y1, x2, y2));
    
            g.dispose();
    
            // CROP THE IMAGE
            image = image.getSubimage(safezone/2, safezone/2, size, size);
            ImageIO.write(image, "png", new File("output.png"));
        }
    }
    
    这将为您提供:

    当然,代码必须适合您的需要,但是为了示例,它是有效的


    虽然这不是一个很好的解决方案,但结果是令人满意的,我希望它能有所帮助!:)

    寻找斜率为1/90的两像素线。@trashgod-我用右边的线附加了一个图像-它是以相同的斜率和位置生成的,但整个宽度都有很好的填充效果。唯一的区别是画布外的长度更短-这条线是使用
    g.draw(new Line2D.Double(98,38188,39))绘制的
    。可能是笔划设置,2.4。可能是要设置的亚像素渲染(这不是纯的,而是默认的)-RGB亚像素的布局可能与渲染所认为的不同。@JoopEggen亚像素渲染的不同设置更改了图片,但问题仍然存在(我将图片附在问题后面)。我尝试使用不同的图像类型而不是INT_ARGB,但结果仍然相同。笔划设置可以做什么?对于亚像素渲染,请参见。对于便携式非亚像素渲染,我只能建议放大100倍并查看内容。也许其他人可以帮上忙。请看我的第一张示例图片-它是d使用抗锯齿绘制,但它看起来与您的第二张图片不一样。如果我在画布内部(甚至外部,但不太远)开始绘制线条,我将观察到非常不同的行为,如我的第二张示例图片所示。我使用与您完全相同的设置修改了图像。唯一的更改是在键上的抗锯齿。如果您在画布外开始线条,您将更改坡度,这可能是您看到的差异的原因。如果我错了,请纠正我,但我认为(8,37)->(188,39)与(98,38)->(188,39)-1/90具有相同的斜率?如果您仍然喜欢分析,可以将此代码粘贴到写入图像的点下方:
    x1-=safezone/2;x2-=safezone/2;y1-=safezone/2;y2-=safezone/2;double length=Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))双斜率=((双)x2-x1))/(y2-y1);系统输出println(“斜率:+slope”);系统输出println(“长度:+Length”);系统输出println(“第1点:+x1+”|“+y1”);系统输出println(“第2点:+x2+”|“+y2”);系统输出println(“内部零件:+x2/长度);系统输出println(“外部零件:+Math.abs(x1/长度))是的,这个解决方案正在运行。不幸的是,我每秒需要创建大量这样的图像,安全区将不再有效
    
    import java.awt.image.*;
    import javax.imageio.ImageIO;
    import java.io.File;
    import java.awt.*;
    import java.awt.geom.*;
    
    public class Testing {
        public static void main(String[] args) throws Exception {
    
            BufferedImage image = new BufferedImage(400, 400, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = (Graphics2D) image.getGraphics();
    
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    
            g.setColor(Color.WHITE);
            g.fillRect(0, 0, 400, 400);
    
            g.setColor(Color.BLACK);
            g.setStroke(new BasicStroke(2));
            for (int i=0; i<400; i+=5)
            {
                double dy = 8.0*(i-100.0) / 200.0;
                g.setColor(Color.BLACK);
                g.draw(new Line2D.Double(-100, dy+i, 90, i));
                g.draw(new Line2D.Double(200+-100, dy+i, 200+90, i));
            }
    
            g.dispose();
            ImageIO.write(image, "png", new File("output.png"));
        }
    }
    
        BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = (Graphics2D) image.getGraphics();
    
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, 100, 100);
    
        g.setColor(Color.BLACK);
        g.setStroke(new BasicStroke(2));
        Path2D path = new Path2D.Double();
        path.moveTo(-92, 37);
        path.lineTo(88, 39);
        g.draw(path);
        g.dispose();
        ImageIO.write(image, "png", new File("output.png"));
    
    import java.awt.image.*;
    import javax.imageio.ImageIO;
    import java.io.File;
    import java.awt.*;
    import java.awt.geom.*;
    
    public class Render {
        public static void main(String[] args) throws Exception {
    
            // YOUR DESIRED SIZE OF CANVAS
            int size = 100;
            // THE SAFEZONE AROUND THE CANVAS
            int safezone = 1000;
    
            // THE IMAGE GETS INITIALIZED WITH SAFEZONE APPLIED
            BufferedImage image = new BufferedImage(size+safezone, size+safezone, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = (Graphics2D) image.getGraphics();
    
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    
            g.setColor(Color.WHITE);
    
            // THE IMAGE GETS FILLED, DON'T FORGET THE SAFEZONE
            g.fillRect(0, 0, size+safezone, size+safezone);
    
            // THE ORIGINAL VALUES WITH THE SAFEZONE APPLIED
            int x1 = -92 + safezone/2;
            int x2 = 88 + safezone/2;
            int y1 = 37 + safezone/2;
            int y2 = 39 + safezone/2;
    
            g.setColor(Color.BLACK);
            g.setStroke(new BasicStroke(2));
            g.draw(new Line2D.Double(x1, y1, x2, y2));
    
            g.dispose();
    
            // CROP THE IMAGE
            image = image.getSubimage(safezone/2, safezone/2, size, size);
            ImageIO.write(image, "png", new File("output.png"));
        }
    }