问题
What I need to do:
I trying to write some code for visualise every pixel of any character. I decided best way for it will be show pixels as rectangle in Tile Pane. So this is effect which i need to reach:
What's my problem:
I wrote some code to make it by take snaphost of text1
and save it as WritableImage
. Then i use PixelReader
for read each pixel of this image by argb
method. In loop when each integer rgb value is greater than TRESHOLD (is brighter) I add new tile with white background. Unless I add tile with black background. But something is still wrong with my idea and I get this effect:
There is my code:
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);
}
}
What I doing wrong? Maby are other ways to take this effect?
回答1:
Your outer loop variable is the x-coordinate and the inner loop variable is the y-coordinate.
This means you read the pixels column by column left to right. TilePane
however requires the children list to be ordered row by row from top to bottom.
To fix the issue simply swap the loops. Use:
for (int y = 0; y < imgHeight; y++) {
for (int x = 0; x < imgWidth; x++) {
...
}
}
Instead of
for (int x = 0; x < imgWidth; x++) {
for (int y = 0; y < imgHeight; y++) {
...
}
}
来源:https://stackoverflow.com/questions/40745356/letter-visualisation-in-tilepane-in-javafx