setStroke () и setFill () производят разные цвета пикселей - PullRequest
0 голосов
/ 30 января 2019

Я пытаюсь понять, как работает метод setStroke холста JavaFX.Он не устанавливает цвет пикселей на желаемое значение.Никаких проблем с методом 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 голосов
/ 30 января 2019

Это эффект сглаживания.

Пиксель не покрывается линией на 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].Столбец с индексом 10 покрыт только наполовину, поэтому результирующий цвет равен ((255, 0, 0) + (255, 255, 255)) / 2 = (255, 127, 127) (уже округлен до целых значений)

Измените dx, чтобы полностью покрыть столбец, и вы получите цвет обводки:

final double dx = 0.5;

Пиксель полностью покрыт прямоугольником, который вы вводите в свой код, и по этой причине цвет устанавливается на цвет заливки.Добавьте 0.5 к одной из начальных координат прямоугольника, который вы заполняете, и вы увидите эффект, подобный обводке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...