gpt4 book ai didi

java - JNA 库的屏幕截图比机器人类慢?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:00:10 26 4
gpt4 key购买 nike

由于 Robot.createScreenCaputure() 方法很慢,我决定使用原生库。我搜索并找到了这个 forum并找到特定的 code snipplet它使用 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();
}

还有一个测试代码,用来查看它比 Robot Class 快多少:

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

结果是

With JNA Library: 77
With Robot Class 37

伙计们,请有人解释一下为什么如何我可以固定它?

最佳答案

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

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

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

关于java - JNA 库的屏幕截图比机器人类慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6998438/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com