JNA库截图比机器人类慢?

2023-11-27

Since Robot.createScreenCaputure()方法很慢,我决定使用本机库。我搜索并找到了这个forum并找到一个具体的代码片段它使用JNA图书馆。这是一个旧版本,所以我重写了代码:

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.win32.W32APIOptions;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.platform.win32.WinGDI;

public class JNAScreenShot {

    public static BufferedImage getScreenshot(Rectangle bounds) {
        WinDef.HDC windowDC = GDI.GetDC(USER.GetDesktopWindow());
        WinDef.HBITMAP outputBitmap =
                GDI.CreateCompatibleBitmap(windowDC,
                bounds.width, bounds.height);
        try {
            WinDef.HDC blitDC = GDI.CreateCompatibleDC(windowDC);
            try {
                WinNT.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);
                }
                WinGDI.BITMAPINFO bi = new WinGDI.BITMAPINFO(40);
                bi.bmiHeader.biSize = 40;
                boolean ok =
                        GDI.GetDIBits(blitDC, outputBitmap, 0, bounds.height,
                        (byte[]) null, bi, WinGDI.DIB_RGB_COLORS);
                if (ok) {
                    WinGDI.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(WinDef.HDC blitDC,
            WinDef.HBITMAP outputBitmap,
            WinGDI.BITMAPINFO bi) {
        WinGDI.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,
        com.sun.jna.platform.win32.WinGDI,
        com.sun.jna.platform.win32.WinDef {

    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);

    com.sun.jna.platform.win32.WinDef.HWND GetDesktopWindow();
}

以及测试代码看看快了多少比机器人类:

import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;

public class testClass {

    public static void main(String[] args) {

        BufferedImage bi = null, bj = null;
        Rectangle rect = new Rectangle(0, 0, 810, 384);
        long startTime, finishTime;

        startTime = System.currentTimeMillis();
        for (int i = 0; i < 10; i++) {
            bi = JNAScreenShot.getScreenshot(rect);
        }
        finishTime = System.currentTimeMillis();

        System.out.println("With JNA Library: " + (finishTime - startTime)/10);

        Robot robo = null;

        startTime = System.currentTimeMillis();
        try {
            robo = new Robot();
        } catch (AWTException a) {
        }
        for (int i = 0; i < 10; i++) {
            bj = robo.createScreenCapture(rect);
        }
        finishTime = System.currentTimeMillis();
        System.out.println("With Robot Class " + (finishTime - startTime)/10);
    }
}

结果是

JNA 图书馆:77
与机器人37级

各位大佬请解释一下why是那个并且how我可以把它系紧吗?


不要过早尝试优化。创建一个合理的接口来获取您想要的数据(屏幕截图),然后基于 Robot、JNA 或 JNI 创建您想要的实现。

我猜想不同的实现会根据其运行的环境给出完全不同的结果。

编程规则一:首先让它工作。然后进行分析,找到瓶颈并消除或减轻瓶颈的影响。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JNA库截图比机器人类慢? 的相关文章

随机推荐

  • 在向量::resize()和向量::reserve()之间选择

    我正在为我的 a 预先分配一些内存vector数据成员 例子 class A vector
  • 在批处理文件中检查计算机是否已插入交流电源

    如何在 Windows 7 中的批处理文件中检查计算机是否已插入交流电源 例如on ac power在linux下有吗 有一种直接批处理文件的方式 WMIC Path Win32 Battery Get BatteryStatus 使用这个
  • 使用字符串数组填充 WPF 列表框

    而不是将每一项一项一项添加到ListBox中destinationList从字符串数组m List像这样 foreach object name in m List destinationList Items Add string name
  • glutInitContextVersion 的文档在哪里?

    FreeGLUT API 文档不包含以下条目glutInitContextVersion当我用谷歌搜索它时 我发现的只是一系列问题 这些问题并没有直接解决它的用法或效果 它在任何地方都有记录吗 glutInitContextVersion不
  • 使文本溢出省略号在 Firefox 和 Chrome 中的工作方式类似

    我创建了一个布局来显示一些文章标题及其状态 文章名称框具有固定宽度 我使用 text overflow ellipsis 来剪切太长的文章名称 另外 我在文章标题的末尾添加了浅灰色虚线 如果不是太长 以使标题和状态之间的差距看起来更好 问题
  • 为什么 servletContext.getRealPath 在 tomcat 8 上返回 null?

    我有以下代码行 servletContext getRealPath resources images video icon png 当我使用jetty 使用maven插件 运行应用程序时 此代码行返回正确的值 当我使用 tomcat 8
  • 在 Python 中的 plt.colorbar() 上格式化数字以包含逗号

    我正在尝试格式化我的颜色条 以便数字用逗号格式化 任何帮助将不胜感激 import numpy as np import matplotlib pyplot as plt plt matshow np array 30000 8000 12
  • UI跨线程操作异常后的Task.ConfigureAwait行为

    我正在玩Task ConfigureAwait为了更好地了解引擎盖之外的情况 所以我在将一些 UI 访问内容与ConfigureAwait 下面是使用简单 Windows 窗体的示例应用程序 其中 1Button接下来是测试结果 priva
  • 在 Doctrine 2.0 实体中使用 EntityManager

    我有 2 个实体 国家 地区 id 名称 和映射 id 对象 internalId externalId 国家和映射不通过关联连接 因为映射不仅具有国家 地区的行 我需要使用以下条件获取国家 地区的外部 ID country id mapp
  • 自定义错误页面中的 AspxErrorPath

    目前 我们有一个页面 用于在我们的网站上发生错误时显示一般错误消息 除了显示一个提到有错误的标签之外 它没有任何其他功能 这是我的问题 我们的客户已经进行了安全审查 并告诉我们 由于查询字符串中的 URL 我们的错误页面包含网络钓鱼 现在我
  • 如何删除两个特定字符之间的子字符串

    所以我有一个字符串 this is the beginning this is what i want to remove and this is the end 如何使用 Javascript 来定位逗号和正斜杠之间的字符串 我还想删除逗
  • 缩放和平移包含超过 10k 个对象的 HTML5 画布的最佳实践

    我需要在画布中构建一种地图 它显示超过 10 000 个元素 圆圈 并且需要缩放和平移 我在这里描述了我的方法Android 在调整多个画布元素大小和移动多个画布元素时速度显着变慢并改变了我对评论中提出的建议的实施 平移地图setTrans
  • 如何自动从 JUnit 4 迁移到 JUnit 5?

    本着这个问题从 JUnit 3 到 JUnit 4 是否有任何正则表达式列表高效地从 junit 4 API 迁移到 junit 5 API 无论代码大小如何 目前的工具还不是很好 但正在改进 IntelliJ 将大多数注释迁移到 JUni
  • Ubuntu 8.04 上打开文件过多错误

    mysqldump Couldn t execute show fields from tablename Out of resources when opening file databasename tablename P p125 M
  • Android onActivityResult 提前调用

    我有 2 个活动 每个活动都在单独的应用程序中 Activity 1 有一个用户可以单击的按钮 它使用其 Intent 调用第二个 ActivityonClick method Intent myIntent getPackageManag
  • 如果用户拒绝推送通知提示的回调方法?

    我的问题是我想显示初始推送通知提示 应用程序想要向您发送推送通知 的加载屏幕 所以如果用户点击yes我可以继续并在随后调用的委托方法中启动应用程序 void application UIApplication application did
  • Kotlin 协程暂停 fun + Retrofit 抛出“未找到 Retrofit 注解”错误

    我试图在 2 5 1 SNAPSHOT 中使用 Retrofit 的协程支持 但我不断遇到奇怪的异常 我的改造服务类别有 GET weather suspend fun getForecast Query q query String Qu
  • 手机快速点击-防止鬼焦

    我正在为移动浏览器进行快速点击 当我快速单击当前页面的链接时 它会使用 ajax 加载到下一页 我的快速点击脚本现在可以停止幽灵点击 但如果当前页面的点击位置下一页有一个输入元素 它仍然会获得焦点并显示虚拟键盘 如何防止鬼焦点事件呢 要阻止
  • 替代applet的替代技术?

    我有一个 未签名的 小程序 可以让您绘制逻辑电路并在屏幕上测试它 有点像电子工作台 然后它序列化电路 内部形式 而不是视觉表示 并将其发送到服务器其中运行大量自动化测试并生成性能报告 这是一个更大的网络应用程序中很小但至关重要的部分 然而
  • JNA库截图比机器人类慢?

    Since Robot createScreenCaputure 方法很慢 我决定使用本机库 我搜索并找到了这个forum并找到一个具体的代码片段它使用JNA图书馆 这是一个旧版本 所以我重写了代码 import java awt Rect