我正在尝试用JavaFX重写Swing图像查看器,但是JavaFX Image构造函数使用的缩放算法质量很低。不幸的是,我不得不依靠调整构造器中图像的大小,因为某些图像太大而无法完全加载到JavaFX的内存中(即使它曾经在Swing中工作)。
这是一个比较。左侧,使用BufferedImage.drawImage
缩小图片,并在Graphics.drawImage
中使用paintComponent
进行渲染(使用抗锯齿渲染提示),而右侧则以相同的缩小分辨率通过JavaFX Image构造函数(将平滑设置为true)。
如您所见,JavaFX缩减算法引入了一种锯齿效应。我该如何补救?我认为问题出在图片没有完全加载到内存中,但看来我别无选择。
这是将生成比较的代码。以下面的picture为例。
public static BufferedImage scale(BufferedImage img, int width, int height) {
int imageType = (img.getTransparency() == Transparency.OPAQUE)
? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
BufferedImage scaled = new BufferedImage(width, height, imageType);
Graphics2D context = scaled.createGraphics();
context.setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
context.drawImage(img, 0, 0, width, height, null);
context.dispose();
return scaled;
}
@Override
public void start(Stage stage) {
// Load full image in memory, downscale using BufferedImage
Image image1 = new Image("file:4000x3600.jpg");
BufferedImage bimg = SwingFXUtils.fromFXImage(image1, null);
bimg = scale(bimg, 600, 600);
image1 = SwingFXUtils.toFXImage(bimg, null);
// Downscale in the Image constructor, saves memory
Image image2 = new Image("file:4000x3600.jpg", 600, 600, false, true);
AnchorPane root = new AnchorPane();
ImageView view1 = new ImageView(image1);
view1.setLayoutX(0.0);
view1.setLayoutY(0.0);
ImageView view2 = new ImageView(image2);
view2.setLayoutX(600.0);
view2.setLayoutY(0.0);
root.getChildren().add(view1);
root.getChildren().add(view2);
Scene scene = new Scene(root, 1200, 600);
stage.setScene(scene);
stage.show();
}