我有一个程序,可以通过ImageView
可视化多个图像,这些图像的大小从大约32x32像素增加到55x55像素。
不幸的是,所有图像都具有透明背景的“边框”,因此图像之间显示有间隙。
有没有一种方法可以在javaFX中裁剪图像,使其缩小为实际图片?
示例:
所需的外观(手工裁剪很差)
实际外观
答案 0 :(得分:2)
Afaik没有为此提供内置方法。正如@Slaw在他的评论中提到的那样,您需要使用PixelReader
来检查空的行/列。根据该信息,您可以为viewport
设置ImageView
属性:
@Override
public void start(Stage primaryStage) {
// using stackoverflow logo, since your image is completely opaque
Image image = new Image("https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-icon.png");
ImageView imageView = new ImageView(image);
int w = (int) image.getWidth();
int h = (int) image.getHeight();
int firstNonEmptyColumn = 0;
int firstNonEmptyRow = 0;
int lastNonEmptyColumn = w - 1;
int lastNonEmptyRow = h - 1;
PixelReader reader = image.getPixelReader();
outer: for (; firstNonEmptyColumn < w; firstNonEmptyColumn++) {
for (int y = 0; y < h; y++) {
// stop, if most significant byte (alpha channel) is != 0
if ((reader.getArgb(firstNonEmptyColumn, y) & 0xFF000000) != 0) {
break outer;
}
}
}
if (firstNonEmptyColumn == w) {
imageView.setImage(null); // image completely transparent
} else {
outer: for (; lastNonEmptyColumn > firstNonEmptyColumn; lastNonEmptyColumn--) {
for (int y = 0; y < h; y++) {
if ((reader.getArgb(lastNonEmptyColumn, y) & 0xFF000000) != 0) {
break outer;
}
}
}
outer: for (; firstNonEmptyRow < h; firstNonEmptyRow++) {
// use info for columns to reduce the amount of pixels that need checking
for (int x = firstNonEmptyColumn; x <= lastNonEmptyColumn; x++) {
if ((reader.getArgb(x, firstNonEmptyRow) & 0xFF000000) != 0) {
break outer;
}
}
}
outer: for (; lastNonEmptyRow > firstNonEmptyRow; lastNonEmptyRow--) {
for (int x = firstNonEmptyColumn; x <= lastNonEmptyColumn; x++) {
if ((reader.getArgb(x, lastNonEmptyRow) & 0xFF000000) != 0) {
break outer;
}
}
}
// set viewport to only show the opaque parts
imageView.setViewport(new Rectangle2D(
firstNonEmptyColumn,
firstNonEmptyRow,
lastNonEmptyColumn - firstNonEmptyColumn + 1,
lastNonEmptyRow - firstNonEmptyRow + 1));
}
// visualize image bounds
Rectangle rect = new Rectangle(imageView.prefWidth(-1), imageView.prefHeight(-1), Color.LIGHTGREEN);
StackPane root = new StackPane(rect, imageView);
root.setStyle("-fx-background-color:blue");
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}