2013-07-15 43 views
6

Tôi đang tạo một chương trình yêu cầu phải chụp ít nhất 24 ảnh chụp màn hình mỗi giây. Hiện tại với đoạn code dưới đây tôi chỉ nhận được 1 cho mỗi ~ 94 mili giây, vì vậy khoảng 10 mỗi giây.Thay thế nhanh hơn cho java.awt.Robot.createScreenCapture?

Tôi không muốn sử dụng bất kỳ thư viện của bên thứ ba nào vì tôi đang cố gắng giữ cho thư viện càng nhỏ càng tốt, nhưng nếu tôi muốn tăng hiệu suất đáng kể, tôi sẵn sàng. Tôi cũng đang cố gắng giữ cho nền tảng này độc lập, nhưng một lần nữa, nếu nó sẽ là một sự gia tăng hiệu năng thực sự đáng kể, tôi sẽ sẵn sàng để giữ cho nó bị giới hạn trong Windows.

chỉnh sửa: Tôi hiện đã thử hai cách khác nhau; sử dụng một đoạn mã được tìm thấy trên trang web oracles và một đoạn được chỉ ra trong phần bình luận bên dưới. Cả ba đã mất khoảng thời gian đó, 2,1-2,2 triệu nanoseconds là khá damn không hiệu quả.

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

Âm thanh như bạn đang cố gắng để nắm bắt một video màn hình. –

+0

Bạn có thể xem [this] (http://www.rune-server.org/programming/application-development/387765-directrobot-fast-java-robot-allows-screen-recording.html), I ' đã không được sử dụng hoặc băng ghế dự bị đánh dấu nó mặc dù – MadProgrammer

+0

@JimGarrison Một cái gì đó như thế. –

Trả lời

2

Cách duy nhất để làm được điều này sẽ được thông qua JNI hoặc có thể JNA. Tôi đã làm một số điểm chuẩn và API chụp màn hình gốc và nó đã có thể duy trì khoảng 45 FPS vs Robots 8 FPS. Tôi có thể bắt đầu một dự án JNI để giải quyết vấn đề này trong tương lai gần. Tôi sẽ cập nhật bài đăng này với URL của dự án nếu nó tiếp tục.

+0

Mọi tin tức về điều này? thế nào để chúng tôi có một thay thế mà làm cho việc sử dụng JNI/JNA để chụp màn hình? –

+0

Tôi cũng muốn thấy điều này. –

+0

Yah, tôi chưa xong dự án. Tôi đang làm việc để đưa thư viện gốc vào maven rồi tôi sẽ bắt đầu phát triển. –

0

Tôi hiện đang thiết lập ví dụ làm việc về sử dụng VLCJ và sau đó sử dụng DirectMediaPlayer (https://github.com/caprica/vlcj/blob/master/src/test/java/uk/co/caprica/vlcj/test/direct/DirectTestPlayer.java) để nhận BufferedImage.

JFrame không cần thiết để nó hoạt động chính xác.

Tôi biết đây là một câu hỏi cũ, nhưng đây vẫn là vấn đề ngày hôm nay, vì vậy tôi nghĩ tôi sẽ chia sẻ.

VLCJ là các ràng buộc Java cho LibVLC.

Ví dụ mã:

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

    }