返回

低于17毫秒截取屏幕图像:终极解决方案

java

以低于 17 毫秒的速度截取屏幕图像:终极指南

作为一名经验丰富的程序员,我一直在寻求以低于 17 毫秒的速度截取屏幕图像的方法。在本文中,我将分享我遇到的挑战、探索过的解决方案以及最终找到的突破性方法。

问题陈述:

对于许多图像处理和计算机视觉任务,至关重要的是以高帧率捕获屏幕图像。然而,使用传统的 Kotlin 解决方案,例如 Robot().createScreenCapture(),我发现无法达到所需的 17 毫秒速度。

尝试过的解决方案:

为了解决这个问题,我尝试了各种方法,包括:

  • 多线程 Robot: 使用多个 Robot 线程来并行化屏幕截图过程。
  • FFMpegGrabber: 使用开源 FFMpeg 库来捕获屏幕视频并从中提取图像。
  • 程序的多个实例: 启动程序的多个实例,每个实例负责捕获特定区域的屏幕。

突破性方法:

尽管这些解决方案有所改善,但它们仍然无法达到 17 毫秒的速度目标。最终,我转向了特定于操作系统的低级库,如:

  • Windows: DirectX (DXGI) 或 Windows Graphics Device Interface (GDI)
  • Linux: Xlib
  • macOS: Core Graphics (Core Graphics)

通过使用 Java Native Interface (JNI),我能够调用这些低级库并大幅提升屏幕截图性能。

实现:

以下是如何使用 DXGI 在 Windows 中截取屏幕图像的示例代码:

import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinNT.RECT;
import com.sun.jna.ptr.IntByReference;

public class ScreenCapture {

    private static final User32 USER32 = User32.INSTANCE;
    private static final Kernel32 KERNEL32 = Kernel32.INSTANCE;

    public static BufferedImage captureScreen() {
        HWND hwnd = USER32.GetDesktopWindow();
        RECT rect = new RECT();
        USER32.GetWindowRect(hwnd, rect);

        int width = rect.right - rect.left;
        int height = rect.bottom - rect.top;

        Pointer hdc = USER32.GetWindowDC(hwnd);
        IntByReference hdcMem = new IntByReference();
        IntByReference hbmp = new IntByReference();

        hdcMem.setValue(GDI32.CreateCompatibleDC(hdc));
        hbmp.setValue(GDI32.CreateCompatibleBitmap(hdc, width, height));

        GDI32.SelectObject(hdcMem, hbmp);
        GDI32.BitBlt(hdcMem, 0, 0, width, height, hdc, 0, 0, GDI32.SRCCOPY);

        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = image.createGraphics();
        g2d.drawImage(GDI32.GetBitmapBits(hbmp, image.getWidth() * image.getHeight() * 3), 0, 0, null);

        GDI32.DeleteObject(hbmp);
        GDI32.DeleteObject(hdcMem);
        USER32.ReleaseDC(hwnd, hdc);

        return image;
    }
}

优化:

为了进一步提高性能,可以考虑以下优化技术:

  • 并行处理: 将屏幕图像的捕获过程分成多个并行任务。
  • 缓存: 缓存屏幕截图以避免重复捕获。
  • 帧跳过: 只捕获必要帧,而不是每个帧。

结论:

通过使用特定于操作系统的低级库并实施优化技术,可以将屏幕截图性能提升至低于 17 毫秒的速度。这对于图像处理、计算机视觉和许多其他需要高帧率捕获的应用程序非常有价值。

常见问题解答:

  1. 为什么我无法使用 Robot().createScreenCapture() 达到 17 毫秒的速度?

    Robot 类使用 Java AWT,它具有较高的开销。低级库绕过了这一开销。

  2. 使用 JNI 有哪些风险?

    不当使用 JNI 可能会导致内存泄漏和程序崩溃。确保仔细清理资源。

  3. 如何优化屏幕截图性能?

    并行化捕获过程,缓存屏幕截图,并仅捕获必要的帧。

  4. 我可以在哪些平台上使用低级库?

    本指南介绍了 Windows、Linux 和 macOS 的低级库。

  5. 我可以在哪里找到更多信息?

    有关特定于操作系统的低级库的更多信息,请参阅 Microsoft、X.Org Foundation 和 Apple 的文档。