Java中如何快速截图?

2023-12-15

我正在实现一个简单的眼动仪,它需要在从网络摄像头捕获视频的同时快速截取屏幕上发生的情况。

问题是用机器人来做这件事的方式,这里提到:https://stackoverflow.com/questions/2475303/java-library-for-capturing-active-window-screenshot非常慢。

顺便说一句,从网络摄像头检索视频的速度要快得多,并返回字节数组,处理速度非常快。

有人知道更快的解决方案吗?可以链接到 Java 来执行此操作的 C++ 库也可能有所帮助。

谢谢你!

更新: 决定切换到 OpenCV,现在正在寻找用它制作屏幕截图的方法:)


这是一个使用 JNA 的 Windows 特定版本,我正在我的一个项目中使用它。

我发现它比Robot,即使有本机调用开销。

import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferUShort;
import java.awt.image.DirectColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;

import com.sun.jna.Native;
import com.sun.jna.platform.win32.W32API;
import com.sun.jna.win32.W32APIOptions;

public class JNAScreenShot {

    public static BufferedImage getScreenshot(Rectangle bounds) {
        W32API.HDC windowDC = GDI.GetDC(USER.GetDesktopWindow());
        W32API.HBITMAP outputBitmap =
            GDI.CreateCompatibleBitmap(windowDC,
                                       bounds.width, bounds.height);
        try {
            W32API.HDC blitDC = GDI.CreateCompatibleDC(windowDC);
            try {
                W32API.HANDLE oldBitmap =
                    GDI.SelectObject(blitDC, outputBitmap);
                try {
                    GDI.BitBlt(blitDC,
                               0, 0, bounds.width, bounds.height,
                               windowDC,
                               bounds.x, bounds.y,
                               GDI32.SRCCOPY);
                } finally {
                    GDI.SelectObject(blitDC, oldBitmap);
                }
                GDI32.BITMAPINFO bi = new GDI32.BITMAPINFO(40);
                bi.bmiHeader.biSize = 40;
                boolean ok =
                    GDI.GetDIBits(blitDC, outputBitmap, 0, bounds.height,
                                  (byte[]) null, bi, GDI32.DIB_RGB_COLORS);
                if (ok) {
                    GDI32.BITMAPINFOHEADER bih = bi.bmiHeader;
                    bih.biHeight = - Math.abs(bih.biHeight);
                    bi.bmiHeader.biCompression = 0;
                    return bufferedImageFromBitmap(blitDC, outputBitmap, bi);
                } else {
                    return null;
                }
            } finally {
                GDI.DeleteObject(blitDC);
            }
        } finally {
            GDI.DeleteObject(outputBitmap);
        }
    }

    private static BufferedImage
    bufferedImageFromBitmap(GDI32.HDC        blitDC,
                            GDI32.HBITMAP    outputBitmap,
                            GDI32.BITMAPINFO bi) {
        GDI32.BITMAPINFOHEADER bih = bi.bmiHeader;
        int height = Math.abs(bih.biHeight);
        final ColorModel cm;
        final DataBuffer buffer;
        final WritableRaster raster;
        int strideBits =
            (bih.biWidth * bih.biBitCount);
        int strideBytesAligned =
            (((strideBits - 1) | 0x1F) + 1) >> 3;
        final int strideElementsAligned;
        switch (bih.biBitCount) {
        case 16:
            strideElementsAligned = strideBytesAligned / 2;
            cm = new DirectColorModel(16, 0x7C00, 0x3E0, 0x1F);
            buffer =
                new DataBufferUShort(strideElementsAligned * height);
            raster =
                Raster.createPackedRaster(buffer,
                                          bih.biWidth, height,
                                          strideElementsAligned,
                                          ((DirectColorModel) cm).getMasks(),
                                          null);
            break;
        case 32:
            strideElementsAligned = strideBytesAligned / 4;
            cm = new DirectColorModel(32, 0xFF0000, 0xFF00, 0xFF);
            buffer =
                new DataBufferInt(strideElementsAligned * height);
            raster =
                Raster.createPackedRaster(buffer,
                                          bih.biWidth, height,
                                          strideElementsAligned,
                                          ((DirectColorModel) cm).getMasks(),
                                          null);
            break;
        default:
            throw new IllegalArgumentException("Unsupported bit count: " + bih.biBitCount);
        }
        final boolean ok;
        switch (buffer.getDataType()) {
            case DataBuffer.TYPE_INT:
                {
                    int[] pixels = ((DataBufferInt) buffer).getData();
                    ok = GDI.GetDIBits(blitDC, outputBitmap, 0, raster.getHeight(), pixels, bi, 0);
                }
                break;
            case DataBuffer.TYPE_USHORT:
                {
                    short[] pixels = ((DataBufferUShort) buffer).getData();
                    ok = GDI.GetDIBits(blitDC, outputBitmap, 0, raster.getHeight(), pixels, bi, 0);
                }
                break;
            default:
                throw new AssertionError("Unexpected buffer element type: " + buffer.getDataType());
        }
        if (ok) {
            return new BufferedImage(cm, raster, false, null);
        } else {
            return null;
        }
    }

    private static final User32 USER = User32.INSTANCE;

    private static final GDI32 GDI = GDI32.INSTANCE;

}

interface GDI32 extends com.sun.jna.platform.win32.GDI32 {
    GDI32 INSTANCE =
        (GDI32) Native.loadLibrary(GDI32.class);
    boolean BitBlt(HDC hdcDest,
                   int nXDest,
                   int nYDest,
                   int nWidth,
                   int nHeight,
                   HDC hdcSrc,
                   int nXSrc,
                   int nYSrc,
                   int dwRop);
    HDC GetDC(HWND hWnd);
    boolean GetDIBits(HDC dc, HBITMAP bmp, int startScan, int scanLines,
                      byte[] pixels, BITMAPINFO bi, int usage);
    boolean GetDIBits(HDC dc, HBITMAP bmp, int startScan, int scanLines,
                      short[] pixels, BITMAPINFO bi, int usage);
    boolean GetDIBits(HDC dc, HBITMAP bmp, int startScan, int scanLines,
                      int[] pixels, BITMAPINFO bi, int usage);
    int SRCCOPY = 0xCC0020;
}

interface User32 extends com.sun.jna.platform.win32.User32 {
    User32 INSTANCE =
        (User32) Native.loadLibrary(User32.class,
                                    W32APIOptions.UNICODE_OPTIONS);
    HWND GetDesktopWindow();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java中如何快速截图? 的相关文章

  • 使用 Intellij Idea 和 gradle 在应用程序引擎上调试 localhost

    我正在使用 IntelliJ 社区添加并使用 Gradle 构建应用程序引擎标准环境应用程序 在迁移到 IntelliJ 和端点框架之前 我使用的是 Android Studio 我无法调试我的本地主机 我添加了 jvmFlags 如下所述
  • 我是否需要安装 SQLite 才能使 SQLiteJDBC 正常工作?

    我想我只是没有 明白 如果我的计算机上尚未安装 SQLite 并且我想编写一个使用嵌入式数据库的 Java 应用程序 并且我将 SQLiteJDBC JAR 下载 导入到我的项目中 那么这就是我所需要的吗 或者 我是否需要先安装 SQLit
  • Java:扩展类并实现具有相同方法的接口

    可能无法完成以下操作 我收到编译错误 继承的方法 A doSomthing int 无法隐藏 B 中的公共抽象方法 public class A int doSomthing int x return x public interface
  • TreeMap 删除所有大于某个键的键

    在项目中 我需要删除键值大于某个键的所有对象 键类型为Date 如果重要的话 据我所知TreeMapJava中实现的是红黑树 它是一种二叉搜索树 所以我应该得到O n 删除子树时 但除了制作尾部视图并一一删除之外 我找不到任何方法可以做到这
  • Java Logger 未记录到 Netbeans 中的输出

    我正在 Netbeans 中使用 Maven 启动一个 Java 项目 我编写了一些代码来使用 Logger 类进行日志记录 但是 日志记录似乎不起作用 在程序开始时 我运行 Logger getLogger ProjectMainClas
  • java.lang.ClassNotFoundException:javax.mail.MessagingException

    我想使用 eclipse 将电子邮件从我的 gmail 帐户发送到另一个邮件帐户 我使用 apache tomcat 7 0 34 作为我的 Web 服务器 并使用端口 8080 作为 apache 服务器 HTTP 1 1 并使用 JRE
  • 如何在 JavaFX 中连接可观察列表?

    我所说的串联是指获得一个新列表 该列表侦听所有串联部分的更改 方法的目的是什么FXCollections concat ObservableList
  • 两个整数乘积的模

    我必须找到c c a b mod m a b c m 是 32 位整数 但 a b 可以超过 32 位 我正在尝试找出一种计算 c 的方法 而不使用 long 或任何 gt 32 位的数据类型 有任何想法吗 如果m是质数 事情可以简化吗 注
  • 垃圾收集器如何在幕后工作来收集死对象?

    我正在阅读有关垃圾收集的内容 众所周知 垃圾收集会收集死亡对象并回收内存 我的问题是 Collector 如何知道任何对象已死亡 它使用什么数据结构来跟踪活动对象 我正在研究这个问题 我发现GC实际上会跟踪活动对象 并标记它们 每个未标记的
  • 什么是抽象类? [复制]

    这个问题在这里已经有答案了 当我了解抽象类时 我说 WT H 问题 创建一个无法实例化的类有什么意义呢 为什么有人想要这样的课程 什么情况下需要抽象类 如果你明白我的意思 最常见的是用作基类或接口 某些语言有单独的interface构建 有
  • 如何在 Java 中向时间戳添加/减去时区偏移量?

    我正在使用 JDK 8 并且玩过ZonedDateTime and Timestamp很多 但我仍然无法解决我面临的问题 假设我得到了格式化的Timestamp在格林威治标准时间 UTC 我的服务器位于某处 假设它设置为Asia Calcu
  • Java 中如何将 char 转换为 int? [复制]

    这个问题在这里已经有答案了 我是Java编程新手 我有例如 char x 9 我需要得到撇号中的数字 即数字 9 本身 我尝试执行以下操作 char x 9 int y int x 但没有成功 那么我应该怎么做才能得到撇号中的数字呢 ASC
  • Android 无法解析日期异常

    当尝试解析发送到我的 Android 客户端的日期字符串时 我得到一个无法解析的日期 这是例外 java text ParseException 无法解析的日期 2018 09 18T00 00 00Z 位于 偏移量 19 在 java t
  • Java Applet 中的 Apache FOP - 未找到数据的 ImagePreloader

    我正在研究成熟商业产品中的一个问题 简而言之 我们使用 Apache POI 库的一部分来读取 Word DOC 或 DOCX 文件 并将其转换为 XSL FO 以便我们可以进行标记替换 然后 我们使用嵌入到 Java 程序中的 FOP 将
  • 从jar中获取资源

    我有包含文件的 jar myJar res endingRule txt myJar wordcalculator merger Marge class 在 Marge java 中我有代码 private static final Str
  • Akka 与现有 java 项目集成的示例

    如果我已经有现有的javaWeb 应用程序使用spring and servlet容器 将 Akka 集成到其中的正确方法是什么 就像我将会有Actor1 and Actor2互相沟通的 开始使用这些演员的切入点是什么 例如 1 把它放在那
  • 在Java中运行bat文件并等待

    您可能会认为从 Java 启动 bat 文件是一项简单的任务 但事实并非如此 我有一个 bat 文件 它对从文本文件读取的值循环执行一些 sql 命令 它或多或少是这样的 FOR F x in CD listOfThings txt do
  • 如何区分从 Saxon XPathSelector 返回的属性节点和元素节点

    给定 XML
  • Log4j2 ThreadContext 映射不适用于parallelStream()

    我有以下示例代码 public class Test static System setProperty isThreadContextMapInheritable true private static final Logger LOGG
  • MiniDFSCluster UnsatisfiedLinkError org.apache.hadoop.io.nativeio.NativeIO$Windows.access0

    做时 new MiniDFSCluster Builder config build 我得到这个异常 java lang UnsatisfiedLinkError org apache hadoop io nativeio NativeIO

随机推荐