2015-08-17 2 views
1

Я изучаю, имеет ли смысл передавать приложение из Swing в JavaFx 8, и мне нужна помощь. Приложение визуализирует изображения в реальном времени, в основном я обновляю изображение с определенной частотой, например, 1 секунду. Размерность изображений составляет 28k x 4k; Когда я использую изображение JavaFx imageView, производительность плоха по сравнению с Swing. (Частота fps низкая, около 1-2, приложение отстает). Я делаю это следующим образом:JavaFx vs Swing Image Visualization

animation = new Timeline(); 
    animation.getKeyFrames().add(new KeyFrame(Duration.millis(1000), new EventHandler<ActionEvent>() { 
     @Override 
     public void handle(ActionEvent actionEvent) { 
      for (int count = 0; count < 1; count++) { 
       if (indicator) 
        imageView.setImage(writableImage); 
       else 
        imageView.setImage(image1); 
       indicator = !indicator; 
      } 
     } 
    })); 
    animation.setCycleCount(Animation.INDEFINITE); 

Так что я пытался использовать JavaFX холст:

imageCanvas.setHeight(image1.getHeight()); 
    imageCanvas.setWidth(image1.getWidth()); 
    imageCanvas.getGraphicsContext2D().drawImage(image1, 0, 0); 

Когда я пытаюсь это, я получаю следующее сообщение об ошибке.

java.lang.NullPointerException 
    at com.sun.prism.impl.BaseGraphics.drawTexture(BaseGraphics.java:400) 
    at com.sun.prism.impl.ps.BaseShaderGraphics.drawTexture(BaseShaderGraphics.java:139) 
    at com.sun.javafx.sg.prism.NGCanvas.handleRenderOp(NGCanvas.java:1336) 
    at com.sun.javafx.sg.prism.NGCanvas.renderStream(NGCanvas.java:1086) 
    at com.sun.javafx.sg.prism.NGCanvas.renderContent(NGCanvas.java:595) 
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2067) 
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1959) 
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:235) 
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:576) 
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2067) 
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1959) 
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:235) 
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:576) 
    at com.sun.javafx.sg.prism.NGNode.renderForClip(NGNode.java:2308) 
    at com.sun.javafx.sg.prism.NGNode.renderRectClip(NGNode.java:2202) 
    at com.sun.javafx.sg.prism.NGNode.renderClip(NGNode.java:2228) 
    at com.sun.javafx.sg.prism.CacheFilter.impl_renderNodeToCache(CacheFilter.java:663) 
    at com.sun.javafx.sg.prism.CacheFilter.render(CacheFilter.java:567) 
    at com.sun.javafx.sg.prism.NGNode.renderCached(NGNode.java:2372) 
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2058) 
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1959) 
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:235) 
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:576) 
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2067) 
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1959) 
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:235) 
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:576) 
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2067) 
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1959) 
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:235) 
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:576) 
    at com.sun.javafx.sg.prism.NGNode.renderForClip(NGNode.java:2308) 
    at com.sun.javafx.sg.prism.NGNode.renderRectClip(NGNode.java:2202) 
    at com.sun.javafx.sg.prism.NGNode.renderClip(NGNode.java:2228) 
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2061) 
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1959) 
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:235) 
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:576) 
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2067) 
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1959) 
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:235) 
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:576) 
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2067) 
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1959) 
    at com.sun.javafx.tk.quantum.ViewPainter.doPaint(ViewPainter.java:474) 
    at com.sun.javafx.tk.quantum.ViewPainter.paintImpl(ViewPainter.java:320) 
    at com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:91) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) 
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) 
    at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125) 
    at java.lang.Thread.run(Thread.java:745) 

Проблема связана с размером изображения, поскольку он работает с меньшими. Во-первых, я не понимаю, почему производительность намного хуже с ImageView по сравнению с Swing? (В качелях я использую панель, которая расширяет метод JPanel и paintComponent.)

Во-вторых, существует ли какой-то предел размера холста в JavaFx?

Заранее спасибо.

ответ

2

Почему приложение JavaFX не работает

28k х 4k является абсолютно массивным изображением и JavaFX 8 не поддерживает непосредственно против аппаратного трубопровода. Я не знаю, официально ли это ограничение официально зарегистрировано.

См. Maximum dimensions of canvas in JavaFX.

Конвейер рендеринга JavaFX по умолчанию попытается нарисовать изображения (и холсты) текстурами на видеокарте (для поддержки аппаратного ускоренного компоновки). Видеокарты ограничены по размеру текстур, которые они поддерживают, как правило, это две степени, например, 8192 x 8192. JavaFX (по крайней мере, в предыдущих версиях, которые я использовал) просто выбросит исключение, если вы попытаетесь отобразить изображение больше максимального размера текстуры, поддерживаемого базовым видеооборудованием.

Потенциальные Обходные

Чтобы обойти ограничение на размер текстуры в JavaFX, обрабатывать поступающие данные для изображения и загрузить его в 7 4k х 4k изображений (с использованием записываемых изображений с пиксельной писателем). Когда вы это сделаете, убедитесь, что входные данные закодированы в соответствующем PixelFormat, например. ByteBgraPreInstance, otherwise data conversion will be required, что может сильно повлиять на производительность вашего приложения.

Есть недокументированные переключатели для JavaFX, чтобы отключить аппаратное рендеринг и вместо этого использовать конвейер рендеринга программного обеспечения. Эти коммутаторы могут или могут не позволять вашему приложению работать с большими размерами изображений без реализации вышеупомянутого алгоритма разбиения, однако, вероятно, это лучше для вашего приложения в целом, чтобы поддерживать аппаратный ускоренный графический конвейер и кодировать ваше приложение для работы внутри ограничения этого конвейера (путем реализации пользовательского алгоритма черепицы для поддержки большого изображения).

аспекты производительности

Что касается разницы в производительности в программе JavaFX против программы свинг, что невозможно анализировать без исходного кода для обеих программ (и, возможно, трудно сделать, даже если источник поставлялись). Поэтому я больше не буду комментировать этот аспект вашего вопроса.

Canvas - это более сложный элемент управления, чем ImageView, и использование Canvas для этой задачи вряд ли даст вам какую-либо улучшенную производительность при использовании ImageView.