2013-07-15 14 views
6

キャプチャするには、少なくとも24枚のスクリーンショットが必要なプログラムを作成しています。現在、以下のコードでは、毎秒〜94ミリ秒ごとに1つしかないので、毎秒約10です。java.awt.Robot.createScreenCaptureへのより迅速な代替手段はありますか?

できるだけ小さくしておきたいので、サードパーティのライブラリを使用したくないのですが、パフォーマンスが大幅に向上したら喜んでいただけます。私はこのプラットフォームを独立させようと努力していますが、実際のパフォーマンスが大幅に向上するならば、Windowsに限定しておきたいと思います。

編集:もう2つの方法も試しました。 oraclesのウェブサイトにあるスニペットと、下記のコメントで指摘されているスニペットを使用しています。 3人ともほぼ同じ時間で、2.1-220万ナノセカンドの時間を費やしました。これはかなり非効率的です。

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

あなたは[this](http://www.rune-server.org/programming/application-development/387765-directrobot-fast-java-robot-allows-screen-recording.html)を見ることができます。使用していないかベンチマークしていますが – MadProgrammer

+0

@JimGarrison何かそんな感じです。 –

答えて

2

JNA JNIを介して、または多分になり、これを行うための唯一の方法。私はいくつかのベンチマークとネイティブスクリーンキャプチャAPIを行い、約45FPS対Robots8FPSを維持することができました。近い将来、この問題を解決するために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はLibVLCのJavaバインディングです。

コード例:あなたは、画面の映像をキャプチャしようとしているように

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); 
     } 

    } 
関連する問題