Я хотел бы рисовать на холсте JavaFX. Координаты для холста предоставляются двойными значениями, но я понимаю, что для «привязки» к пиксельной сетке мне нужны целые числа, чтобы избежать отрисовки «между» пикселями, что приведет к размытию/сглаживанию по краям.
Рассмотрим этот минимальный пример:
public class App extends Application {
@Override
public void start(Stage stage) {
var vbox = new VBox();
var canvas = new Canvas(600, 400);
var gc = canvas.getGraphicsContext2D();
// draw a background
gc.beginPath();
gc.setFill(Color.rgb(200,200,200));
gc.rect(0, 0, 600, 400);
gc.fill();
// draw a smaller square
gc.beginPath();
gc.setFill(Color.rgb(100,100,100));
gc.rect(9.0, 9.0, 50, 50); // snap to grid
gc.fill();
vbox.getChildren().addAll(canvas);
var scene = new Scene(vbox, 640, 480);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
Это работает и приведет к четкому краю, рассмотрите это изображение:
Теперь предположим, что HighDPI включен, т.е. рассмотрим, масштабируем ли мы графику в Windows 10 до 125 процентов. Это приведет к коэффициенту масштабирования 1,25 (мы можем получить его с помощью getOutputScaleX/Y).
Однако тогда весь холст масштабируется с этим коэффициентом, и мы получаем размытие. Посмотрите прикрепленные изображения (но вам нужно увеличить масштаб и, возможно, просмотреть их в графической программе, а не в браузере).
Затем я подумал, что мы можем настроить исходные координаты так, чтобы масштабированные координаты давали целые числа. Например, чтобы убедиться, что мы попали в целое число со смещением 9 * 1,25 = 11,25 на масштабированном изображении, давайте вместо этого попробуем нацелиться на 11,0, т.е. изменим эту строку
gc.rect(9.0, 9.0, 50, 50);
to
gc.rect(11.0/1.25, 11.0/1.25, 50, 50);
Но это еще приводит к размытию края.
Как мы можем обойти это? В идеале я хотел бы полностью отключить масштабирование dpi для холста и выполнить свои собственные (с точностью до пикселя) вычисления. Возможно ли это или есть другое решение?
Для drawImage есть параметр setSmoothing, но при рисовании фигур напрямую (например, rect) ничего нет.
HighDPI
варианте вы говорите? Настраивали ли вы какие-либо параметры, которые Windows предлагает для исполняемых файлов, такие как настройки высокого разрешения или режимы совместимости? Поскольку вам не нужно делать это для JavaFX, он поддерживает высокое разрешение. - person john16384   schedule 13.06.2020