Я пытаюсь переписать средство просмотра изображений Swing в JavaFX, однако алгоритм масштабирования, используемый конструктором изображений JavaFX, имеет очень низкое качество. К сожалению, мне приходится полагаться на изменение размера изображения в конструкторе, потому что некоторые изображения слишком велики для полной загрузки в память для JavaFX (даже если раньше это работало в Swing).
Вот сравнение. Слева, используя BufferedImage.drawImage
, чтобы уменьшить масштаб изображения и отрендерив его с помощью Graphics.drawImage
в paintComponent
(используя подсказку рендеринга сглаживания), а справа это же изображение, загруженное с тем же уменьшенным разрешением через конструктор JavaFX Image ( установить в true).
Сравнение
Как вы можете видеть, алгоритм уменьшения масштаба JavaFX вводит форму пилообразного эффекта. Как я мог исправить это? Я полагаю, что проблема заключается в том, что изображение не полностью загружено в память, но, похоже, у меня нет другого выбора.
Вот код, который сгенерирует сравнение. Используя в качестве примера следующее изображение .
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();
}