JavaFX 中 TilePane 中的字母可视化
Letter visualisation in TilePane in JavaFX
我需要做的事情:
我正在尝试编写一些代码来可视化任何字符的每个像素。我决定最好的方法是在 Tile Pane 中将像素显示为矩形。所以这是我需要达到的效果:
我的问题是什么:
我写了一些代码来获取 text1
的 snaphost 并将其保存为 WritableImage
。然后我使用 PixelReader
通过 argb
方法读取该图像的每个像素。在循环中,当每个整数 rgb 值大于 TRESHOLD(更亮)时,我添加带有白色背景的新图块。除非我添加黑色背景的瓷砖。但是我的想法仍然有问题,我得到了这个效果:
有我的代码:
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
//Create single letter string
String letter = "a";
//Create new text
Text text1 = new Text(letter);
//Set font for text
text1.setFont(Font.font("Calibri", FontWeight.NORMAL, 12));
//Save text1 as writable image
WritableImage newImg = text1.snapshot(null, null);
//Take bounds of letter
int imgHeight = (int) newImg.getHeight();
int imgWidth = (int) newImg.getWidth();
//Create pixel reader from newImg
PixelReader reader = newImg.getPixelReader();
//This is for preview image
ImageView imgPreview = new ImageView(newImg);
//Create tilePane
TilePane tilePane = new TilePane();
//New group with tilePane inside
Group display = new Group(tilePane);
//Bg color
tilePane.setStyle("-fx-background-color: gray;");
//Small gaps between tiles
tilePane.setHgap(2);
tilePane.setVgap(2);
//Set quantity of columns equals image width
tilePane.setPrefColumns(imgWidth);
//Set quantity of rows equals image height
tilePane.setPrefRows(imgHeight );
//Here I set tolerance treshold
int TOLERANCE_THRESHOLD = 0xf0;
for (int x = 0; x < imgWidth; x++) {
for (int y = 0; y < imgHeight; y++) {
int argb = reader.getArgb(x, y);
int r = (argb >> 16) & 0xFF;
int g = (argb >> 8) & 0xFF;
int b = argb & 0xFF;
if (r >= TOLERANCE_THRESHOLD
&& g >= TOLERANCE_THRESHOLD
&& b >= TOLERANCE_THRESHOLD) {
tilePane.getChildren().add(createElement(Color.WHITE));
}
else tilePane.getChildren().add(createElement(Color.BLACK));
}
}
// Create new stage
Stage stage = new Stage();
//Create new group
Group grupa = new Group();
Scene scene = new Scene(grupa, 400, 300, Color.GRAY);
grupa.getChildren().addAll(display);
stage.setScene(scene);
stage.show();
}
private Rectangle createElement(Color color) {
Rectangle rectangle = new Rectangle(15, 15);
//rectangle.setStroke(Color.ORANGE);
rectangle.setFill(color);
return rectangle;
}
public static void main(String[] args) {
launch(args);
}
}
我做错了什么?也许还有其他方法可以达到这种效果?
你的外循环变量是x坐标,内循环变量是y坐标。
这意味着您从左到右逐列读取像素。 TilePane
但是要求子列表从上到下逐行排序。
要解决此问题,只需交换循环即可。使用:
for (int y = 0; y < imgHeight; y++) {
for (int x = 0; x < imgWidth; x++) {
...
}
}
而不是
for (int x = 0; x < imgWidth; x++) {
for (int y = 0; y < imgHeight; y++) {
...
}
}
我需要做的事情:
我正在尝试编写一些代码来可视化任何字符的每个像素。我决定最好的方法是在 Tile Pane 中将像素显示为矩形。所以这是我需要达到的效果:
我的问题是什么:
我写了一些代码来获取 text1
的 snaphost 并将其保存为 WritableImage
。然后我使用 PixelReader
通过 argb
方法读取该图像的每个像素。在循环中,当每个整数 rgb 值大于 TRESHOLD(更亮)时,我添加带有白色背景的新图块。除非我添加黑色背景的瓷砖。但是我的想法仍然有问题,我得到了这个效果:
有我的代码:
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
//Create single letter string
String letter = "a";
//Create new text
Text text1 = new Text(letter);
//Set font for text
text1.setFont(Font.font("Calibri", FontWeight.NORMAL, 12));
//Save text1 as writable image
WritableImage newImg = text1.snapshot(null, null);
//Take bounds of letter
int imgHeight = (int) newImg.getHeight();
int imgWidth = (int) newImg.getWidth();
//Create pixel reader from newImg
PixelReader reader = newImg.getPixelReader();
//This is for preview image
ImageView imgPreview = new ImageView(newImg);
//Create tilePane
TilePane tilePane = new TilePane();
//New group with tilePane inside
Group display = new Group(tilePane);
//Bg color
tilePane.setStyle("-fx-background-color: gray;");
//Small gaps between tiles
tilePane.setHgap(2);
tilePane.setVgap(2);
//Set quantity of columns equals image width
tilePane.setPrefColumns(imgWidth);
//Set quantity of rows equals image height
tilePane.setPrefRows(imgHeight );
//Here I set tolerance treshold
int TOLERANCE_THRESHOLD = 0xf0;
for (int x = 0; x < imgWidth; x++) {
for (int y = 0; y < imgHeight; y++) {
int argb = reader.getArgb(x, y);
int r = (argb >> 16) & 0xFF;
int g = (argb >> 8) & 0xFF;
int b = argb & 0xFF;
if (r >= TOLERANCE_THRESHOLD
&& g >= TOLERANCE_THRESHOLD
&& b >= TOLERANCE_THRESHOLD) {
tilePane.getChildren().add(createElement(Color.WHITE));
}
else tilePane.getChildren().add(createElement(Color.BLACK));
}
}
// Create new stage
Stage stage = new Stage();
//Create new group
Group grupa = new Group();
Scene scene = new Scene(grupa, 400, 300, Color.GRAY);
grupa.getChildren().addAll(display);
stage.setScene(scene);
stage.show();
}
private Rectangle createElement(Color color) {
Rectangle rectangle = new Rectangle(15, 15);
//rectangle.setStroke(Color.ORANGE);
rectangle.setFill(color);
return rectangle;
}
public static void main(String[] args) {
launch(args);
}
}
我做错了什么?也许还有其他方法可以达到这种效果?
你的外循环变量是x坐标,内循环变量是y坐标。
这意味着您从左到右逐列读取像素。 TilePane
但是要求子列表从上到下逐行排序。
要解决此问题,只需交换循环即可。使用:
for (int y = 0; y < imgHeight; y++) {
for (int x = 0; x < imgWidth; x++) {
...
}
}
而不是
for (int x = 0; x < imgWidth; x++) {
for (int y = 0; y < imgHeight; y++) {
...
}
}