Как эффективно прокручивать и масштабировать большие изображения в JavaFX?

#java #javafx

#java #javafx

Вопрос:

В качестве части приложения для обработки изображений мне нужно создать простой модуль просмотра с функциями масштабирования, прокрутки и векторного наложения. Изображения довольно большие: ~ 40000×20000, что замедляет операции с ImageView, буферизует и т.д. Каковы наилучшие варианты улучшения пользовательского опыта при работе с огромными изображениями в JavaFX?

Комментарии:

1. Вы когда-нибудь выясняли, как сделать это производительным? Я пытаюсь поместить это изображение из синего мрамора в качестве фона и сталкиваюсь с аналогичными проблемами. Кэширование не помогает.

2. Я решил использовать реализацию плиточной панели, как здесь: gist.github.com/james-d/a249470377fb3c58784a9349a22641c4 Это многопоточность, и вы можете довольно легко реализовать кэш для этого решения. Конечно, вы должны использовать формат изображения, который поддерживает частичное чтение из определенного пикселя.

Ответ №1:

У меня есть изображение размером 8 на 4k, которое отлично масштабируется за счет кэширования области прокрутки, в которую я его поместил, и использования этого кода для масштабирования. Единственная проблема с панелью прокрутки и большими изображениями заключается в том, что панорамирование ужасно и медленно, для чего я пытаюсь найти решение в моем текущем приложении.

 final double SCALE_DELTA = 1.175;
private double SCALE_TOTAL = 1;
  

.

     //Adds functionality to scrolling
    mapScroll.addEventFilter(ScrollEvent.ANY, e ->{
        //Consumes the event
        e.consume();
        if(e.getDeltaY() == 0)
        {
            return;
        }
        double scaleFactor =
                  (e.getDeltaY() > 0)
                    ? SCALE_DELTA
                    : 1/SCALE_DELTA;
        //Ensures that you do not exceed the limits of the map
        if(scaleFactor * SCALE_TOTAL >= 1)
        {
            Bounds viewPort = mapScroll.getViewportBounds();
            Bounds contentSize = mapGrid.getBoundsInParent();

            double centerPosX = (contentSize.getWidth() - viewPort.getWidth()) * mapScroll.getHvalue()   viewPort.getWidth() / 2;
            double centerPosY = (contentSize.getHeight() - viewPort.getHeight()) * mapScroll.getVvalue()   viewPort.getHeight() / 2;

            mapGrid.setScaleX(mapGrid.getScaleX() * scaleFactor);
            mapGrid.setScaleY(mapGrid.getScaleY() * scaleFactor);
            SCALE_TOTAL *= scaleFactor;

            double newCenterX = centerPosX * scaleFactor;
            double newCenterY = centerPosY * scaleFactor;

            mapScroll.setHvalue((newCenterX - viewPort.getWidth()/2) / (contentSize.getWidth() * scaleFactor - viewPort.getWidth()));
            mapScroll.setVvalue((newCenterY - viewPort.getHeight()/2) / (contentSize.getHeight() * scaleFactor  -viewPort.getHeight()));
        }
    });