setStroke()和setFill()产生不同的像素颜色

时间:2019-01-30 10:09:12

标签: java javafx colors

我试图了解JavaFX canvas setStroke方法的工作方式。它不会将像素的颜色设置为所需的值。 但是setFill方法没问题。

Canvas canvas = new Canvas(500, 500);
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFill(Color.RED);
gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());

int x = 10;
int y = 10;
printPixelRGB(x, y);    // displays:  red=255, green=0, blue=0      -> OK

// scenario 1: using fill-methods
gc.setStroke(Color.WHITE);
gc.strokeRect(x, y, 200, 200);
printPixelRGB(x, y);    // displays:  red=255, green=191, blue=191  -> ????

// scenario 2: using stroke-methods 
gc.setFill(Color.WHITE);
gc.fillRect(x, y, 200, 200);
printPixelRGB(x, y);    // displays:  red=255, green=255, blue=255  -> OK


private void printPixelRGB(int x, int y) {
    WritableImage snap = gc.getCanvas().snapshot(null, null);
    int color = snap.getPixelReader().getArgb(x, y);
int red = (color >> 16) & 0xff;
    int green = (color >> 8) & 0xff;
    int blue = color & 0xff;
    System.out.printf("red=%-3d, green=%-3d, blue=%-3d \n", red, green, blue);
}  // printPixelRGB()

方案2的结果符合预期。 另一方面,场景1的结果很奇怪:像素不是完全白色!怎么会来?

我该如何解决?

谢谢

1 个答案:

答案 0 :(得分:2)

这是抗锯齿的效果。

该像素没有被线条100%覆盖。因此,结果颜色将在绘制操作之前的像素颜色和笔触颜色之间进行插值。

以下代码可让您观察效果:

@Override
public void start(Stage primaryStage) {
    Canvas canvas = new Canvas(800, 300);

    GraphicsContext gc = canvas.getGraphicsContext2D();
    gc.setFill(Color.RED);
    gc.fillRect(0, 0, 800, 300);

    gc.setStroke(Color.WHITE);

    final double dx = 0;

    for (double x = 10, s = 1; x < (800 - 40); s++, x += 50) {
        gc.setLineWidth(s);
        gc.strokeLine(x + dx, 0, x + dx, 300);
    }

    WritableImage snap = canvas.snapshot(null, null);
    PixelReader reader = snap.getPixelReader();

    for (int x = 10; x < (800 - 40); x += 50) {
        Color color = reader.getColor(x, 150);
        System.out.printf("red=%-3d, green=%-3d, blue=%-3d\n", (int) (color.getRed() * 0xFF),
                (int) (color.getGreen() * 0xFF), (int) (color.getBlue() * 0xFF));
    }

    primaryStage.setScene(new Scene(new StackPane(canvas)));
    primaryStage.show();
}

绘制的第一行覆盖[10-lineWidth/2, 10+lineWidth/2] = [9.5, 10.5]的x间隔。索引为10的列仅覆盖了一半,这就是为什么生成的颜色为((255, 0, 0) + (255, 255, 255)) / 2 = (255, 127, 127)(已经四舍五入为整数值)的原因

修改dx以完全覆盖该列,您将获得笔触颜色:

final double dx = 0.5;

您在代码中填充的矩形完全覆盖了像素,因此将颜色设置为填充颜色。将0.5添加到您填充的矩形的一个起始坐标中,您将观察到与笔触相似的效果。