java - java.awt.Robot.createScreenCapture 的更快替代品?

标签 java image performance screenshot awtrobot

我正在制作一个程序,要求每秒至少捕获 24 个屏幕截图。目前使用下面的代码,我每大约 94 毫秒只能得到 1 个,所以大约每秒 10 个。

我不想使用任何第 3 方库,因为我试图让它尽可能小,但如果我能获得显着的性能提升,我愿意这样做。我也在努力保持这个平台的独立性,但同样,如果这真的能带来显着的性能提升,我愿意将它限制在 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);
    }
}

最佳答案

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

关于java - java.awt.Robot.createScreenCapture 的更快替代品?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17665529/

相关文章:

java - 如何使用 JGit 获取提交的文件列表

c# - 如何使用 C# 将图像插入到 pdf 文档中?

sql-server - 请帮我做这个查询(sql server 2008)

c++ - 在大型文本文件中搜索数千个字符串

java - 如何使用 ASM 创建局部变量?

java - 如果 Kubernetes 上存在多个 pod,则从单个 pod 运行 Spring 中的 Scheduled Cron 方法

java - 在 Java 中用前导零填充等于零的二进制字符串 ("0")

javascript - 如何将本地镜像加载到按钮中

python - 如何将从 url 检索到的图像放入图像小部件

ruby-on-rails - 测试 Rails 查询计数