本文介绍了使用 Java 和 awt.Robot 时提高屏幕捕获速度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果有人还有任何其他提高屏幕截图性能的建议,请随时分享,因为它可能完全解决我的问题!

If anyone also has any other recommendations for increasing performance of screen capture please feel free to share as it might fully address my problem!

各位开发人员,

我正在为自己开发一些基本的屏幕截图软件.截至目前,我已经获得了一些使用 java.awt.Robot 将屏幕捕获为 BufferedImage 的概念/修补代码证明.然后我在指定的时间内执行此捕获,然后将所有图片转储到磁盘.根据我的测试,我每秒获得大约 17 帧.

I'm working on some basic screen capture software for myself. As of right now I've got some proof of concept/tinkering code that uses java.awt.Robot to capture the screen as a BufferedImage. Then I do this capture for a specified amount of time and afterwards dump all of the pictures to disk. From my tests I'm getting about 17 frames per second.

时长:15 秒捕获的图像:255

Length: 15 secondsImages Captured: 255

时长:15 秒捕获的图像:229

Length: 15 secondsImages Captured: 229

显然,这对于真正的屏幕捕获应用程序来说还不够好.特别是因为这些捕获是我只是在我的 IDE 中选择了一些文本,而不是图形密集的.

Obviously this isn't nearly good enough for a real screen capture application. Especially since these capture were me just selecting some text in my IDE and nothing that was graphically intensive.

我现在有两个类,一个 Main 类和一个Monitor"类.Monitor 类包含捕获屏幕的方法.我的 Main 类有一个基于时间的循环,它调用 Monitor 类并将它返回的 BufferedImage 存储到 BufferedImages 的 ArrayList 中.如果我修改我的主类以生成多个线程,每个线程都执行该循环并收集有关捕获图像时的系统时间的信息,我可以提高性能吗?我的想法是使用共享数据结构,当我插入它们时,它会根据捕获时间自动对帧进行排序,而不是将连续图像插入到数组列表中的单个循环.

I have two classes right now a Main class and a "Monitor" class. The Monitor class contains the method for capturing the screen. My Main class has a loop based on time that calls the Monitor class and stores the BufferedImage it returns into an ArrayList of BufferedImages.If I modify my main class to spawn several threads that each execute that loop and also collect information about the system time of when the image was captured could I increase performance? My idea is to use a shared data structure that will automatically sort the frames based on capture time as I insert them, instead of a single loop that inserts successive images into an arraylist.

代码:

public class Monitor {

/**
 * Returns a BufferedImage
 * @return
 */
public BufferedImage captureScreen() {
    Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
    BufferedImage capture = null;

    try {
        capture = new Robot().createScreenCapture(screenRect);
    } catch (AWTException e) {
        e.printStackTrace();
    }

    return capture;
}
}

主要

public class Main {


public static void main(String[] args) throws InterruptedException {
    String outputLocation = "C:\\Users\\ewillis\\Pictures\\screenstreamer\\";
    String namingScheme = "image";
    String mediaFormat = "jpeg";
    DiscreteOutput output = DiscreteOutputFactory.createOutputObject(outputLocation, namingScheme, mediaFormat);

    ArrayList<BufferedImage> images = new ArrayList<BufferedImage>();
    Monitor m1 = new Monitor();

    long startTimeMillis = System.currentTimeMillis();
    long recordTimeMillis = 15000;

    while( (System.currentTimeMillis() - startTimeMillis) <= recordTimeMillis ) {
        images.add( m1.captureScreen() );
    }

    output.saveImages(images);

}
}

推荐答案

重新使用屏幕矩形和机器人类实例将为您节省一点开销.真正的瓶颈是将所有 BufferedImage 存储到数组列表中.

Re-using the screen rectangle and robot class instances will save you a little overhead. The real bottleneck is storing all your BufferedImage's into an array list.

我会首先测试你的机器人有多快.createScreenCapture(screenRect);调用没有任何 IO(不保存或存储缓冲图像).这将为机器人课程提供理想的吞吐量.

I would first benchmark how fast your robot.createScreenCapture(screenRect); call is without any IO (no saving or storing the buffered image). This will give you an ideal throughput for the robot class.

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

如果结果显示 captureScreen 可以达到您想要的 FPS,则不需要多线程机器人实例.

If it turns out that captureScreen can reach the FPS you want there is no need to multi-thread robot instances.

我没有缓冲图像的数组列表,而是有一个来自 AsynchronousFileChannel.write 的 Future 数组列表.

Rather than having an array list of buffered images I'd have an array list of Futures from the AsynchronousFileChannel.write.

  • 捕获循环
    • 获取缓冲图像
    • 将 BufferedImage 转换为包含 JPEG 数据的字节数组
    • 创建一个到输出文件的异步通道
    • 开始写入并将立即返回值(未来)添加到您的 ArrayList
    • 检查您的 Futures ArrayList 并确保它们都已完成

    这篇关于使用 Java 和 awt.Robot 时提高屏幕捕获速度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 11:45