java.awt.Robot.createScreenCapture更快的替代方案? [英] Faster alternative to java.awt.Robot.createScreenCapture?

查看:172
本文介绍了java.awt.Robot.createScreenCapture更快的替代方案?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个每秒至少需要截屏24张的程序。目前使用下面的代码我每隔约94毫秒就会得到1个,所以大约每秒10个。

I'm making a program that requires at least 24 screenshots per second to be captured. Currently with the code below I'm only getting 1 per every ~94 milliseconds, so about 10 per second.

我不想使用任何第三方库,因为我试图让它尽可能小,但如果我的性能会有显着提高,我愿意。我也试图保持这个平台的独立性,但同样,如果它的性能提升非常显着,我愿意将它限制在Windows内。

I'd prefer not to use any 3rd party libraries because I'm trying to keep it as small as possible, but if I'd get significant performance increase I'd be willing to. I'm also trying to keep this platform independent, but again, if it would be a really significant performance increase I'd be willing to keep it limited to Windows.

编辑:我现在也尝试了两种不同的方式;使用在oracles网站上找到的片段以及下面评论中指出的片段。所有三个大约在同一时间,210-2.2百纳秒,这是非常低效。

edit: I've now tried it two different ways as well; using a snippet found on oracles website and the one pointed out in the comments below. All three took around the same time, 2.1-2.2 million nanoseconds which is pretty damn inefficient.

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


推荐答案

唯一的方法是通过JNI或JNA。我做了一些基准测试和原生屏幕捕获API,它能够维持大约45 FPS与机器人8 FPS。我可能会在JNI项目上开始在不久的将来解决这个问题。如果继续,我会用项目URL更新这篇文章。

The only way to do this will be through JNI or possibly JNA. I did some benchmarking and native screen capture API and it was able to sustain about 45 FPS vs the Robots 8 FPS. I might be starting on a JNI project to solve this issue in the near future. I will update this post with the project URL if that goes forward.

这篇关于java.awt.Robot.createScreenCapture更快的替代方案?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆