2013-07-15 2 views
6

Я делаю программу, требующую захвата не менее 24 снимков в секунду. В настоящее время с кодом ниже я получаю только 1 за каждые ~ 94 миллисекунды, примерно 10 в секунду.Более быстрая альтернатива java.awt.Robot.createScreenCapture?

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

Редактировать: Я теперь попробовал это два разных способа; используя фрагмент, найденный на веб-сайте oracles, и тот, который указан в комментариях ниже. Все три заняли примерно одно и то же время: 2,1-2,2 млн. Наносекунд, что довольно неэффективно.

public abstract class Benchmark { 

    private final int iterations; 

    public Benchmark(int iterations) { 
     this.iterations = iterations; 
    } 

    public abstract void logic(); 

    public void start() { 
     long start = System.nanoTime(); 
     for (int iteration = 0; iteration < iterations; iteration++) { 
      long iterationStart = System.nanoTime(); 
      logic(); 
      System.out.println("iteration: " + iteration + " took: " + (System.nanoTime() - iterationStart) + " nanoseconds."); 
     } 
     long total = (System.nanoTime() - start); 
     System.out.println(iterations + " iterations took: " + total + " nanoseconds. Average iteration was: " + (total/iterations)); 
    } 
} 

_

import java.awt.AWTException; 
import java.awt.Rectangle; 
import java.awt.Robot; 
import java.awt.Toolkit; 

public class RobotBenchmark extends Benchmark { 

    private final Robot robot; 
    private final Rectangle screen; 

    public static void main(String[] args) { 
     Benchmark benchmark; 
     try { 
      benchmark = new RobotBenchmark(24); 
      benchmark.start(); 
     } catch (AWTException e) { 
      e.printStackTrace(); 
     } 
    } 

    public RobotBenchmark(int iterations) throws AWTException { 
     super(iterations); 
     robot = new Robot(); 
     screen = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()); 
    } 

    @Override 
    public void logic() { 
     robot.createScreenCapture(screen); 
    } 

} 

_

import java.awt.AWTException; 
import java.awt.GraphicsDevice; 
import java.awt.HeadlessException; 
import java.awt.Rectangle; 

public class DirectRobotBenchmark extends Benchmark { 

    private final GraphicsDevice device; 
    private final Rectangle screenRectangle; 
    private final DirectRobot robot; 

    private int[] screen; 

    public static void main(String[] args) { 
     Benchmark benchmark; 
     try { 
      benchmark = new DirectRobotBenchmark(24); 
      benchmark.start(); 
     } catch (HeadlessException | AWTException e) { 
      e.printStackTrace(); 
     } 
    } 

    public DirectRobotBenchmark(int iterations) throws HeadlessException, AWTException { 
     super(iterations); 
     device = DirectRobot.getDefaultScreenDevice(); 
     screenRectangle = new Rectangle(1920, 1080); 
     robot = new DirectRobot(device); 
     screen = new int[screenRectangle.width * screenRectangle.height]; 
    } 

    @Override 
    public void logic() { 
     screen = robot.getRGBPixels(screenRectangle); 
    } 
} 

_

import java.awt.AWTException; 
import java.awt.GraphicsEnvironment; 
import java.awt.Rectangle; 
import java.awt.Robot; 
import java.awt.Toolkit; 
import java.awt.peer.RobotPeer; 

import sun.awt.SunToolkit; 

@SuppressWarnings("restriction") 
public class RobotPeerBenchmark extends Benchmark { 

    private final SunToolkit toolkit; 
    private final RobotPeer peer; 
    private final Rectangle screenRectangle; 

    private int[] screen; 

    public static void main(String[] args) { 
     try { 
      Benchmark robotPeerBenchmark = new RobotPeerBenchmark(24); 
      robotPeerBenchmark.start(); 
     } catch (AWTException e) { 
      e.printStackTrace(); 
     } 
    } 

    public RobotPeerBenchmark(int iterations) throws AWTException { 
     super(iterations); 
     toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); 
     peer = toolkit.createRobot(new Robot(), GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()); 
     screenRectangle = new Rectangle(toolkit.getScreenSize()); 
     screen = new int[screenRectangle.width * screenRectangle.height]; 
    } 

    @Override 
    public void logic() { 
     screen = peer.getRGBPixels(screenRectangle); 
    } 
} 
+2

Похоже, вы пытаетесь захватить видео экран. –

+0

Вы можете взглянуть на [это] (http://www.rune-server.org/programming/application-development/387765-directrobot-fast-java-robot-allows-screen-recording.html), I ' я не использовал или скамейку, отмеченную им, хотя – MadProgrammer

+0

@JimGarrison Что-то в этом роде. –

ответ

2

Единственный способ сделать это будет через JNI или, возможно, ЮНА. Я сделал некоторый бенчмаркинг и собственный API захвата экрана, и он смог выдержать около 45 FPS против Robots 8 FPS. Я мог бы начать проект JNI для решения этой проблемы в ближайшем будущем. Я буду обновлять этот пост с URL-адресом проекта, если это произойдет.

+0

Есть новости на эту тему? есть ли у нас альтернатива, которая использует JNI/JNA для захвата экрана? –

+0

Я тоже хотел бы видеть это. –

+0

Да, я провалился над проектом. Я работаю над тем, чтобы получить исходную библиотеку в maven, после чего я начну расстраиваться. –

0

В настоящее время я создал рабочий пример использования VLCJ, а затем с помощью DirectMediaPlayer (https://github.com/caprica/vlcj/blob/master/src/test/java/uk/co/caprica/vlcj/test/direct/DirectTestPlayer.java), чтобы получить BufferedImage.

JFrame не требуется для правильной работы.

Я знаю, что это старый вопрос, но сегодня это проблема, поэтому я решил поделиться с вами.

VLCJ - это привязки Java для LibVLC.

Пример кода:

private BufferedImage image; 
    private MediaPlayerFactory factory; 
    private DirectMediaPlayer mediaPlayer; 

    public void start() { 

      image = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(width, height); 
      image.setAccelerationPriority(1.0f); 

      String mrl = "screen://"; 
      String[] options = { 
        ":screen-fps=30", 
        ":live-caching=0", 
        ":screen-width=1920", 
        ":screen-height=1080", 
        ":screen-left=0", 
        ":screen-top=0" 
      }; 
      factory = new MediaPlayerFactory(); 
      mediaPlayer = factory.newDirectMediaPlayer(new TestBufferFormatCallback(), new TestRenderCallback()); 
      mediaPlayer.playMedia(mrl, options); 
    } 

    // Callbacks are required. 
    private final class TestRenderCallback extends RenderCallbackAdapter { 

     public TestRenderCallback() { 
      super(((DataBufferInt) image.getRaster().getDataBuffer()).getData()); 
     } 

     @Override 
     public void onDisplay(DirectMediaPlayer mediaPlayer, int[] data) { 
      // The image data could be manipulated here... 

      /* RGB to GRAYScale conversion example */ 
//   for(int i=0; i < data.length; i++){ 
//    int argb = data[i]; 
//    int b = (argb & 0xFF); 
//    int g = ((argb >> 8) & 0xFF); 
//    int r = ((argb >> 16) & 0xFF); 
//    int grey = (r + g + b + g) >> 2 ; //performance optimized - not real grey! 
//    data[i] = (grey << 16) + (grey << 8) + grey; 
//   } 
//   imagePane.repaint(); 
     } 
    } 

    private final class TestBufferFormatCallback implements BufferFormatCallback { 

     @Override 
     public BufferFormat getBufferFormat(int sourceWidth, int sourceHeight) { 
      return new RV32BufferFormat(width, height); 
     } 

    } 
Смежные вопросы