使用Java和awt.Robot时提高屏幕捕获速度

使用Java和awt.Robot时提高屏幕捕获速度,java,java-2d,javax.imageio,awtrobot,Java,Java 2d,Javax.imageio,Awtrobot,编辑:如果有人对提高屏幕捕获性能有任何其他建议,请随意分享,因为这可能完全解决我的问题 各位开发者好 我正在为自己开发一些基本的屏幕捕获软件。到目前为止,我已经有了一些概念验证/修补代码,它使用java.awt.Robot将屏幕捕获为缓冲区图像。然后我在指定的时间内进行此捕获,然后将所有图片转储到磁盘。从我的测试中,我每秒得到17帧 审判#1 长度:15秒 拍摄图像:255 审判#2 长度:15秒 拍摄图像:229 显然,对于真正的屏幕捕获应用程序来说,这还远远不够。特别是因为这些捕获只是我在I

编辑:如果有人对提高屏幕捕获性能有任何其他建议,请随意分享,因为这可能完全解决我的问题

各位开发者好

我正在为自己开发一些基本的屏幕捕获软件。到目前为止,我已经有了一些概念验证/修补代码,它使用java.awt.Robot将屏幕捕获为缓冲区图像。然后我在指定的时间内进行此捕获,然后将所有图片转储到磁盘。从我的测试中,我每秒得到17帧

审判#1 长度:15秒 拍摄图像:255

审判#2 长度:15秒 拍摄图像:229

显然,对于真正的屏幕捕获应用程序来说,这还远远不够。特别是因为这些捕获只是我在IDE中选择了一些文本,而没有任何图形化的内容

我现在有两节课,一节主课和一节“班长”课。Monitor类包含捕获屏幕的方法。我的主类有一个基于时间的循环,它调用Monitor类并将返回的BuffereImage存储到BuffereImage的ArrayList中。 如果我修改我的主类以生成多个线程,每个线程执行该循环,并收集有关捕获映像的系统时间的信息,那么我可以提高性能吗?我的想法是使用一个共享数据结构,在插入帧时根据捕获时间自动对帧进行排序,而不是使用一个循环将连续图像插入arraylist

代码:

班长 主要
公共类主{
公共静态void main(字符串[]args)引发InterruptedException{
String outputLocation=“C:\\Users\\ewillis\\Pictures\\screenstreamer\\”;
字符串namingScheme=“image”;
字符串mediaFormat=“jpeg”;
DiscreteOutput=DiscreteOutputFactory.createOutputObject(outputLocation,namingScheme,mediaFormat);
ArrayList images=新的ArrayList();
监视器m1=新监视器();
long startTimeMillis=System.currentTimeMillis();
长记录时间毫秒=15000;

虽然((System.currentTimeMillis()-startTimeMillis)我想这里的内存占用率是个问题。您在测试中捕获了大约250个屏幕截图。根据屏幕分辨率,这是:

1280x800 : 250 * 1280*800  * 3/1024/1024 ==  732 MB data
1920x1080: 250 * 1920*1080 * 3/1024/1024 == 1483 MB data
尝试在不将所有图像保留在内存中的情况下进行caputuring


正如@Obicere所说,让Robot实例保持活动状态是个好主意。

重新使用屏幕矩形和Robot类实例将节省一点开销。真正的瓶颈是将所有buffereImage存储到数组列表中

我首先要测试一下robot.createScreenCapture(screenRect)的速度;调用没有任何IO(没有保存或存储缓冲图像)。这将为robot类提供理想的吞吐量

long frameCount = 0;
while( (System.currentTimeMillis() - startTimeMillis) <= recordTimeMillis ) {
    image = m1.captureScreen();
    if(image !== null) {
        frameCount++;
    }
    try {
        Thread.yield();
    } catch (Exception ex) {
    }
}
long frameCount=0;

while((System.currentTimeMillis()-startTimeMillis)你一直在创建新的矩形和新的机器人。尝试为实例制作最终的矩形和机器人,只使用字段而不是制作新的。这应该会有所帮助。@Obicere我这样做了,我仍然获得类似的性能。但是你知道或认为多线程的想法值得追求吗?我不太熟悉你正在做的事情,但它会似乎如果你创建了一个机器人/核心,你就可以在主核心繁忙时在每个机器人之间循环,并在不同的核心上拍摄屏幕截图。如果你进行多线程处理,也许你可以使用一个队列,并在向其中添加图像时对其进行同步。你可以避免在以这种方式输入图像时对图像进行排序。或者,您可以在所有图像完成后进行排序。如果您关心的是FPS,则在添加图像时,您不希望执行任何排序计算。它不是使用awt.Robot,但速度更快。是的。从我所做的所有读取来看,似乎需要做的是捕获初始图像。然后获取字节[]该映像和所有后续映像的数据。对于所有后续映像,将其字节[]数据转换为第一个字节[]的增量编码版本大大降低了空间需求。然后,如果您需要写入磁盘,它也会更快。回答得好。我认为需要对捕获循环进行的一个修改是将字节数组转换为第一个捕获的图像的增量编码字节数组。然后,您应该有一个可以压缩和存储的稀疏数据数组uch更容易。@EthanWillis您知道推荐的用于Java的增量编码字节数组实现吗?
1280x800 : 250 * 1280*800  * 3/1024/1024 ==  732 MB data
1920x1080: 250 * 1920*1080 * 3/1024/1024 == 1483 MB data
long frameCount = 0;
while( (System.currentTimeMillis() - startTimeMillis) <= recordTimeMillis ) {
    image = m1.captureScreen();
    if(image !== null) {
        frameCount++;
    }
    try {
        Thread.yield();
    } catch (Exception ex) {
    }
}