有没有办法在缩放Canvas时停止模糊?我认为这与GPU插值有关。但我需要的是像素完美的“像素化”缩放。只使用最近的“真实”相邻像素的颜色。
我已经看到了这里的解决方案,但两个建议中工作的(#1 /#4),#4明显是CPU缩放,我猜想#1也是。
这种缩放需要快速操作 - 我希望能够支持多达20-25个图层(可能是StackPane中的Canvases,但只要它们不会损坏CPU,我对其他想法持开放态度)。我怀疑没有GPU支持不可能完成此操作,虽然JFX提供了这种支持,但也许API不够灵活。像链接答案中依赖于CPU重新缩放的#4之类的策略可能行不通。
如果您使用此代码缩放到最高缩放级别,则可以明显看到模糊。
我们需要更新JFX API以支持此功能吗?这应该是可以做到的。
我已经看到了这里的解决方案,但两个建议中工作的(#1 /#4),#4明显是CPU缩放,我猜想#1也是。
这种缩放需要快速操作 - 我希望能够支持多达20-25个图层(可能是StackPane中的Canvases,但只要它们不会损坏CPU,我对其他想法持开放态度)。我怀疑没有GPU支持不可能完成此操作,虽然JFX提供了这种支持,但也许API不够灵活。像链接答案中依赖于CPU重新缩放的#4之类的策略可能行不通。
如果您使用此代码缩放到最高缩放级别,则可以明显看到模糊。
我们需要更新JFX API以支持此功能吗?这应该是可以做到的。
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Paint;
import javafx.stage.Stage;
public class ScaleTest extends Application {
private static final int width = 1200;
private static final int height = 800;
private static final int topMargin = 32;
private StackPane stackPane;
private IntegerProperty zoomLevel = new SimpleIntegerProperty(100);
@Override
public void start(Stage stage) {
stage.setWidth(width);
stage.setMinHeight(height);
stackPane = new StackPane();
stackPane.setLayoutY(topMargin);
Canvas canvas = new Canvas(width, height - topMargin);
Label label = new Label();
label.setLayoutY(2);
label.setLayoutX(2);
label.setStyle("-fx-text-fill: #FFFFFF");
label.textProperty().bind(zoomLevel.asString());
Button zoomInBtn = new Button("Zoom In");
zoomInBtn.setLayoutY(2);
zoomInBtn.setLayoutX(50);
zoomInBtn.onActionProperty().set((e) -> {
if (zoomLevel.get() < 3200) {
zoomLevel.set(zoomLevel.get() * 2);
stackPane.setScaleX(zoomLevel.get() / 100.0);
stackPane.setScaleY(zoomLevel.get() / 100.0);
}
});
Button zoomOutBtn = new Button("Zoom Out");
zoomOutBtn.setLayoutY(2);
zoomOutBtn.setLayoutX(140);
zoomOutBtn.onActionProperty().set((e) -> {
if (zoomLevel.get() > 25) {
zoomLevel.set(zoomLevel.get() / 2);
stackPane.setScaleX(zoomLevel.get() / 100.0);
stackPane.setScaleY(zoomLevel.get() / 100.0);
}
});
Pane mainPane = new Pane(stackPane, label, zoomInBtn, zoomOutBtn);
mainPane.setStyle("-fx-background-color: #000000");
Scene scene = new Scene(mainPane);
stage.setScene(scene);
drawGrid(canvas, 0, 0, width, height - topMargin, 16);
stackPane.getChildren().add(canvas);
stage.show();
}
private void drawGrid(Canvas canvas, int xPos, int yPos, int width, int height, int gridSize) {
boolean darkX = true;
String darkCol = "#111111";
String lightCol = "#222266";
for (int x = xPos; x < canvas.getWidth(); x += gridSize) {
boolean dark = darkX;
darkX = !darkX;
if (x > width) {
break;
}
for (int y = yPos; y < canvas.getHeight(); y += gridSize) {
if (y > height) {
break;
}
dark = !dark;
String color;
if (dark) {
color = darkCol;
} else {
color = lightCol;
}
canvas.getGraphicsContext2D().setFill(Paint.valueOf(color));
canvas.getGraphicsContext2D().fillRect(x, y, gridSize, gridSize);
}
}
}
}